常见排序算法
交换方法
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)。

浙公网安备 33010602011771号