常见排序算法

交换方法

1     public static void swap(int[] nums, int a, int b) { // 交换数组中的两个数
2         int tmp = nums[a];
3         nums[a] = nums[b];
4         nums[b] = tmp;
5     }

 

冒泡排序

 1     public static void bubbleSort(int[] nums) { // 冒泡排序
 2         int tmp;
 3         for (int i = nums.length - 1; i > 0; i--) {
 4             for (int j = 0; j < i; j++) {
 5                 if (nums[j] > nums[j + 1]) {
 6                     swap(nums, j, j + 1);
 7                 }
 8             }
 9         }
10     }

 冒泡排序时间复杂度为O(n2),并且涉及到多次交换(在查找排序中有改进),效率很低。

快速排序

 1     public static void quickSort(int[] nums, int left, int right) { // 快速排序
 2         if (left >= right) return;
 3         int tmp = nums[left];
 4         int l = left, r = right;
 5         while (l < r) {
 6             while (nums[r] >= tmp && l < r) {
 7                 r--; // 右指针先移动
 8             }
 9             while (nums[l] <= tmp && l < r) {
10                 l++; // 左指针后移动
11             }
12             if (l != r) {
13                 swap(nums, l, r); // 交换左右指针位置上的数
14             }
15         }
16         swap(nums, left, r);
17         quickSort(nums, left, r - 1);
18         quickSort(nums, r + 1, right);
19     }

快速排序平均时间复杂度为O(nlogn),效率高但不稳定,当数组有序时,时间复杂度为O(n2)。

 归并排序

 1     public static void mergeSort(int[] nums, int left, int right) { // 归并排序
 2         if (left >= right) return;
 3         int mid = left - (left - right) / 2;
 4         mergeSort(nums, left, mid);
 5         mergeSort(nums, mid + 1, right);
 6         // 创建辅助数组 创建指针
 7         int[] tmp = new int[right - left + 1];
 8         int l = left, r = mid + 1, t = 0;
 9         // 两组中放满一组
10         while (l <= mid && r <= right) {
11             if (nums[l] < nums[r]) {
12                 tmp[t] = nums[l];
13                 l++;
14                 t++;
15             }else {
16                 tmp[t] = nums[r];
17                 r++;
18                 t++;
19             }
20         }
21         // 处理没放完的
22         if (l > mid) {
23             while (r <= right) {
24                 tmp[t] = nums[r];
25                 r++;
26                 t++;
27             }
28         }else if (r > right) {
29             while (l <= mid) {
30                 tmp[t] = nums[l];
31                 l++;
32                 t++;
33             }
34         }
35         // 最后将tmp数组中排序了的数放入原数组中
36         for (int n : tmp) {
37             nums[left] = n;
38             left++;
39         }
40         
41     }

 

简化:

 1     public static void mergeSort(int[] nums, int left, int right) { // 归并排序
 2         if (left >= right) return;
 3         int mid = left - (left - right) / 2;
 4         mergeSort(nums, left, mid);
 5         mergeSort(nums, mid + 1, right);
 6         // 创建辅助数组 创建指针
 7         int[] tmp = new int[right - left + 1];
 8         int l = left, r = mid + 1, t = 0;
 9         // 两组中放满一组
10         while (l <= mid && r <= right) {
11             if (nums[l] < nums[r]) {
12                 tmp[t++] = nums[l++];
13             }else {
14                 tmp[t++] = nums[r++];
15             }
16         }
17         // 处理没放完的
18         if (l > mid) {
19             while (r <= right) tmp[t++] = nums[r++];
20         }else if (r > right) {
21             while (l <= mid) tmp[t++] = nums[l++];
22         }
23         // 最后将tmp数组中排序了的数放入原数组中
24         for (int n : tmp) {
25             nums[left] = n;
26             left++;
27         }
28         
29     }

归并排序的时间复杂度非常稳定,为O(nlogn),空间复杂度为O(n)。

 堆排序

 1     public static void heapSort(int[] nums) { // 堆排序
 2         int size = nums.length;
 3         // 初始化堆
 4         for (int i = 0; i < size; i++) {
 5             while (i > 0) {
 6                 int j = (i - 1) / 2;
 7                 if (nums[i] < nums[j]) break; // 比父节点小则退出循环
 8                 swap(nums, i, j);
 9                 i = j; // 继续向上比较
10             }
11         }
12         // 交换首尾
13         swap(nums, 0, size - 1);
14         size--;
15         // 循环(重建堆,交换首尾)
16         while (size > 1) {
17             int i = 0;
18             while (i * 2 + 1 < size) { // 至少存在左子节点
19                 int j = i * 2 + 1;
20                 if (j + 1 < size) { // 两个子节点同时存在
21                     if (nums[i] < nums[j] || nums[i] < nums[j + 1]) { // 有一个子节点比父节点大
22                         int k = nums[j] > nums[j + 1] ? j : j + 1;
23                         swap(nums, i, k);
24                         i = k;
25                     }else { // 两个子节点都比父节点小
26                         break;
27                     }
28                 }else if (nums[i] < nums[j]) { //左子节点比父节点大
29                     swap(nums, i, j);
30                     i = j;
31                 }else { // 左子节点比父节点小
32                     break;
33                 }
34             }
35             swap(nums, 0, size - 1);
36             size--;
37         }
38     }

 堆排序中,初始化堆的时间复杂度为O(n),重建堆的时间复杂度为O(nlogn)。

posted @ 2020-09-09 19:58  昆梧  阅读(156)  评论(0)    收藏  举报