美文网首页Android开发经验谈Android技术知识
为什么算法容易忘记之快速排序

为什么算法容易忘记之快速排序

作者: 工程师milter | 来源:发表于2016-06-28 06:12 被阅读950次

    本文用来帮助大家理解记忆快速排序,方法和上篇文章一样,着重理解算法基本思想及其代码中的循环控制变量的意义。

    基本思想

    快速排序属于拿着元素找位置的算法。思路非常简单明了,首先给第一个元素找到它正确的位置并把它放置其中,此时该元素将原数组分为两半,左半边的元素都小于或等于它,右半边的元素都大于它,对这两个子数组重复刚才的操作,直到子数组中只有一个元素,此时排序完成。

    由思想到代码

    首先,我们用一个forInsert变量存储数组第一个位置上的元素的值。可以通俗理解为我们将第一个位置上的元素“挖”了出来,以便为它找到合适的位置,第一个位置此时已经是“空”的,位置是空的这一概念很关键,后面会用到。

    如何为该元素找到合适的位置呢?答案是先确定该元素所在位置的范围,不断缩小该范围,直到该范围是一个确定的位置,查找结束,把forInsert的值放到该位置上,再对该位置左右两个子数组进行迭代,直到子数组大小为1时结束,排序完成。为表示该元素所在位置的范围,我们需要定义两个变量left,right,代表元素所在位置的范围的左端和右端,显然left的初始值应为0,right的初始值应为N-1。

    下面开始缩小这一范围,将right位置上的元素与forInsert进行比较,如果大于forInsert,那么可以断定right这个位置肯定不是forInsert应当在的位置,因为如果将forInsert放置在right位置上,该位置上原来的元素将无处安放。所以我们可以将right减1(right--),这就缩小了位置的范围,然后我们继续将新的right位置上的元素与forInsert比较,如果还是大于forInsert,则可以继续将right减1后继续比较,直到right位置上的值小于forInsert的值时,就是magic发生的地方。

    由于right位置上的元素比forInsert小,我们无法判断该位置是否是forInsert应当在的位置,BTW,我们可以判定left这个位置肯定不是forInsert应当在的位置,为什么?请参照上文叙述自行理解。

    然后呢?我们可以将right位置上的值放置到left位置上,让left加1(left++),这进一步缩小了位置的范围。

    此时right位置我们认为是“空的”了,看到没,刚才left是空的,现在right是空的了。
    下步的思路肯定还是想办法继续缩小位置的范围。我们可以将left位置上的元素与forInsert比较,如果小于forInsert的值,我们可以断定,left这个位置肯定不是forInsert应当在的位置,为啥?因为将forInsert放置到该位置上,该位置上的元素只能往左边挪,而左边每个位置上都是比forInsert小的元素导致“无处可挪”,矛盾出现,反证结束。然后我们又可以放心地将left加1了,位置范围又缩小了,哦耶!

    我们继续将left位置上的元素与forInsert比较,直到发现left位置上的元素大于forInsert时,又要有magic发生了,我们将left位置上的元素放置到right位置上(还记得right位置此时是空的吗?),现在,left位置变成空的了,由于此时right位置上的元素是大于forInsert的,right位置肯定不是forInsert应当在的位置,所以我们要将right减1,进一步缩小待确定位置的范围。

    好了,让我们停一停,看看现在是什么状况,显然left增加了一些值,并且left位置此时是空的,right减少了一些值,整体上[left , right]包含的范围比初始时小了好多。如果left=right,我们知道,要找的位置就是现在left所指示的空位置,直接将forInsert放置到left位置上即可。然后开始左右两个子数组的迭代,如果left还是小于right,那我们只能继续进行缩小位置范围的工作,直到确定位置为止。

    这是代码

    void quick_sort(int s[], int l, int r)
    {
    if (l < r)
    {
    int i = l, j = r, x = s[l];
    while (i < j)
    {
    while(i < j && s[j] >= x)
    j--;
    if(i < j) s[i++] = s[j];
    while(i < j && s[i] < x)
    i++;
    if(i < j) s[j--] = s[i];
    }
    s[i] = x;
    quick_sort(s, l, i - 1); // 递归调用
    quick_sort(s, i + 1, r);
    }
    }

    相关文章

      网友评论

        本文标题:为什么算法容易忘记之快速排序

        本文链接:https://www.haomeiwen.com/subject/ktctjttx.html