快速排序(QuickSort)
- 原理
快速排序用到了分而治之的思想,操作过程是先随机将数组中的一个值暂定为基准值,将数组中大于基准值的数移到基准值右侧,小于基准值的数移至左侧(这一过程其实就是使基准值归位),第一轮基准值归位后,一个数组分为两个数组(不包括基准值),分别对基准值左侧和右侧数据重复基准值归位操作。 - 过程解析
以数组arr
[70,72,26,87,26,80,65,2,66,28,37,8,33,15,55,70,13,83…]为例
为了方便,第一轮选取arr[0]作为base(基准值)。
利用哨兵i,j, j从右侧往左遍历找到小于等于base的数,停下,然后i从左侧找到 大于或等于的数停下,交换i,j的值,直至i>j, 此时可以完成第一轮基准值归位
动图演示
- 基准值70 归位
刚开始 选70作为base值
i从左侧找,72比70大,停下,此时i=1,j从右侧找,38比70小,停下,此时j=45,交换arr[1] arr[45],也就是交换72和38,
70基准值归位全过程
现在左侧是比70小的数,右侧是比70大的数。继续以左侧数组为例解释,
- 19基准值归位
- 基准值 8归位
- 基准值4归位
-
基准值4归位
-
代码实现初版(java)
public static void main(String[] args) {
Quick_Sort(arr, 0, arr.length - 1);
for (int i : arr
) {
System.out.println(i);
}
}
public static void Quick_Sort(int[] arr, int begin, int end) {
if(begin>=end){
return;
}
int tmp = arr[begin];
int i = begin+1;
int j = end;
//基准位归位
while (i <= j+1) {
while (i<=j && arr[i] < tmp)
i++;
while (i<=j && arr[j] >= tmp )
j--;
if (j > i) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[j];
arr[j] = tmp;
Quick_Sort(arr, begin, j - 1);
Quick_Sort(arr, j + 1, end);
}
- 终版
public static void main(String[] args) {
Quick_Sort(arr, 0, arr.length - 1);
for (int i : arr
) {
System.out.println(i);
}
}
public static void Quick_Sort(int[] arr, int begin, int end) {
if(begin<end) {
int basicIndex = findBasicIndex(arr, begin, end);
Quick_Sort(arr, begin, basicIndex - 1);
Quick_Sort(arr, basicIndex + 1, end);
}
}
//基准值归位后的位置
static int findBasicIndex(int[] arr,int begin,int end){
int tmp = arr[begin];
int i = begin+1;
int j = end;
while (i<=j) {
while (i<=j && arr[i] < tmp)
i++;
while (i<=j && arr[j] >= tmp )
j--;
if (j > i) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[j];
arr[j] = tmp;
return j;
}
插入排序(InsertSort)
- 原理
插入排序将数组分为有序和无序两部分,依次将无序部分的数据插入到有序数组中。 - 过程
1 从数组中第二个元素依次开始抽取元素。
2 将它和左边的第一个元素比较,大于的话,继续和左边的元素比较,直至遇到比它小的元素,插入到该元素右边
3 重复上述步骤
代码实现
private static void Insertsort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
// 记录要插入的数据
int tmp = arr[i];
// 从已经排序的序列最右边的开始比较,找到比其小的数
int j = i;
while (j > 0 && tmp < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
// 存在比其小的数,插入
if (j != i) {
arr[j] = tmp;
}
}
}
希尔排序(ShellSort)
- 优化过的插入排序,
- 代码实现
private static void shellsort(int[] arr){
for (int gap = arr.length/2; gap >0 ; gap /=2) {
for (int i = gap; i < arr.length; i++) {
int tmp = arr[i];
int j=i;
while(j-gap>=0&&tmp<arr[j-gap]){
arr[j] = arr[j-gap];
j-=gap;
}
// 存在比其小的数,插入
if (j != i) {
arr[j] = tmp;
}
}
}
}
排序算法比较
排序算法 | 平均时间复杂度 | 平均空间复杂度 | 是否稳定 |
---|---|---|---|
快速排序 | O(nlogn) | O(nlogn) | F |
插入排序 | O(n2) | O(1) | T |
希尔排序 | O(n1.3) | O(1) | F |