排序算法之快速排序!
发表于更新于
计算机基础算法排序算法之快速排序!
月伴飞鱼快速排序的基本思想:
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小。
- 则可分别对这两部分记录继续进行排序,以达到整个序列有序。
先从数列中取出一个数作为基准数。
分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
再对左右区间重复第二步,直到各区间只有一个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class QuickSort { public static void quickSort(int[]arr,int low,int high){ if (low < high) { int middle = getMiddle(arr, low, high); quickSort(arr, low, middle - 1); quickSort(arr, middle + 1, high); } } public static int getMiddle(int[] list, int low, int high) { int tmp = list[low]; while (low < high) { while (low < high && list[high] >= tmp) { high--; } list[low] = list[high]; while (low < high && list[low] <= tmp) { low++; } list[high] = list[low]; } list[low] = tmp; return low; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class QuickSort { public static void quickSort(int data[], int left, int right) { int base = data[left]; int ll = left; int rr = right; while (ll < rr) { while (ll < rr && data[rr] >= base) { rr--; } if (ll < rr) { int temp = data[rr]; data[rr] = data[ll]; data[ll] = temp; ll++; } while (ll < rr && data[ll] <= base) { ll++; } if (ll < rr) { int temp = data[rr]; data[rr] = data[ll]; data[ll] = temp; rr--; } } if (left < ll) quickSort(data, left, ll - 1); if (ll < right) quickSort(data, ll + 1, right); } }
|
优化点:
基本的快速排序选取第一个或最后一个元素作为基准。
如果数组已经有序时,此时的分割就是一个非常不好的分割。
因为每次划分只能使待排序序列减一,此时为最坏情况,快速排序沦为冒泡排序,时间复杂度为O(n^2)。
三数取中:
一般的做法是使用左端、右端和中心位置上的三个元素的中值作为枢纽元。
举例:待排序序列为:8 1 4 9 6 3 5 2 7 0。
左边为:8,右边为0,中间为6。
这里取三个数排序后,中间那个数作为枢轴,则枢轴为6。
插入排序:
当待排序序列的长度分割到一定大小后,使用插入排序。
原因:对于很小和部分有序的数组,快排不如插排好。
当待排序序列的长度分割到一定大小后,继续分割的效率比插入排序要差,此时可以使用插排而不是快排。
重复数组:
在一次分割结束后,可以把与Key相等的元素聚在一起,继续下次分割时,不用再对与key相等元素分割。
在一次划分后,把与key相等的元素聚在一起,能减少迭代次数,效率会提高不少。
在处理过程中,会有两个步骤:
- 第一步,在划分过程中,把与key相等元素放入数组的两端。
- 第二步,划分结束后,把与key相等的元素移到枢轴周围。