赞
踩
快速排序的过程是这样的:
假设我们现在对“6 1 2 7 9 3 4 5 10 8”这个10个数进行排序。首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,就是一个用来参照的数,待会你就知道它用来做啥的了)。为了方便,就让第一个数6作为基准数吧。接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列。
3 1 2 5 4 6 9 7 10 8
方法其实很简单: 分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列次左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的次左边(即下标为1),指向数字1。让哨兵j指向序列的最右边(即下标为9),指向数字8。
哨兵i从左往右依次寻找到第一个比基准大的数,哨兵j从右往左依次寻找到第一个比基准小的数,然后交换。
交换:注意:交换之前需要检查i是否小于j,只有i < j的时候才能交换。否则不交换,然后进入最后的基准的位置调整。
再继续往前寻找(哨兵i寻找比基准大,哨兵j寻找比基准小的),直到哨兵i,j相遇或者j < i。
交换:
继续找:
这里由于不满足i < j,因此3和9不会进行交换。退出循环。
现在我们发现以3和9的中间为界,除了基准6以外,比6小的都在左边,比6大的都在右边。因此,此时还需要调整基准的位置。
这里需要注意的是,当选择的基准在最左边时,需要和右指针也就是j做交换;
如果选择的基准在最右边,则基准和左指针i进行交换。
当我们第一次排序结束以后,就需要对原数组进行划分处理,以上一个基准为界,分为两个数组,如下
然后再对子数组进行上述的排序操作,这是一个递归的思想。
上代码:
int quick(int *arr,int leftbound,int rightbound) { int leftptr = leftbound+1; int rightptr = rightbound; int pivot = arr[leftbound]; while(leftptr <= rightptr) { while(leftptr <= rightptr && arr[leftptr] < pivot) { leftptr++; } while(leftptr <= rightptr&& arr[rightptr] >= pivot) { rightptr--; } if(leftptr < rightptr) { swap(arr,leftptr,rightptr); } } swap(arr,leftbound,rightptr); return rightptr; } void quick_sort(int *arr,int left,int right) { if(right <= left) { return; } int mid = quick(arr,left,right); quick_sort(arr,left,mid-1); quick_sort(arr,mid+1,right); }
要点:
每次进入做交换的循环之前,需要判断左指针的下标是否小于等于右指针的下标,若小于等于则进入循环,否则不进入循环。
轴选在左侧,则判断左指针指向的值的时候,该值只有小于轴指向的数值的时候,左指针才会继续向右移,即左指针指向的值一定大于轴指向的值,不可以等于,否则排序会出错。然而,判断右指针的时候一定要包含轴的值。 反之,轴在右侧,则左指针的判断一定要包含轴,右指针则不能包含。
左右指针的值做交换之前,需要判断左指针(下标)是否小于右指针(下标),小于则进行交换,否则(大于等于)则不进行交换。
轴在左侧,则最后调整轴的位置的时候,需要将轴与右指针最后指向的位置的值做交换。轴在右侧的时候,则与左指针做交换。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。