算法篇——快速排序
Quicksort是对冒泡排序法的一种改进。由C. A. R. Hoare在1962年提出的。他的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
前两天看微软源码的时候无意间看到这个,打算深入了解一下。
快速排序法的基本原理就是,从数组中拿出一个数,以这个数为基数,将比它小的放在左边,比他大的放在右边,直到”基线”左边的数全部都比它小,基线右面的书全都比它大,以基线为分界,彻底将数组分离成两部分。然后这两部分以此类推重复上述操作。
为了不产生”阻断”现象,比如以下数组,设a0为基数,向后推移,a1比她小,那么把a1拿出来放在a[0]的位置,a[2]比它大,那么a[2]不动。问题出来了基线无法向下进行了,a[3]比它小,可是a[2]位置没动。故采取的左右进行的方式。
从右到左采取小的放左面,从左向右采取大的放右面,直到除基线以外的每个元素都与基线比较过,既左右进行的角标重合,这样就能合理分区了。演变过程如下图所示。
现在已经按照基线全部分开了,同时在基线两边分别分化出来两组数组,这两组数组也按照上述规则进行排序。这里可以用到一个递归。code如下。
public static void QuickSort(int[] nums, int left, int right)
{
int num = nums[left];
int x = left;
int y = right;
while (x < y)
{
//从右向左数,遇到比基线小的则将该较小的数填入左侧,并'遗留'右侧位置
while (x < y)
{
if (nums[y] < num)
{
nums[x] = nums[y];
x++;
break;
}
y--;
}
//从左向右数,遇到比基线大的则将该较大的数值填入右侧,并'遗留'左侧位置
//Ps:这时产生右侧位置则是上一个while循环遗留的位置
while (x < y)
{
if (nums[x] > num)
{
nums[y] = nums[x];
y--;
break;
}
x++;
}
}
//x=y既基线位置,将基数装入基线位置
nums[x] = num;
//左右数组分别递归
//判断条件防止堆栈溢出 --比如该数组只有一个相同的数字
if (x > 1)
QuickSort(nums, 0, x - 1);
if (x < right)
QuickSort(nums, x + 1, right);
}