排序算法
快速排序
快速排序是一种常见的排序算法,其核心思想是分治法。下面是快速排序的步骤:
选取一个基准数(pivot)
将序列中比基准数大的元素放在基准数的右边,比基准数小的元素放在基准数的左边。
递归地对基准数左右两边的序列进行排序,直到序列长度为1或0。
快速排序中最重要的就是第2步,也就是partation阶段。快速排序有很多不同的实现方式,每次选择最右侧的数作为pivot进行partation。
1 2 3 4 5 6 7 8 9 10 11 12 int partation (vector<int > &nums, int left, int right) { int pvoit = nums[right]; int i = left - 1 ; for (int j = left; j <= right; ++j) { if (nums[j] <= pvoit) swap (nums[++i], nums[j]); } return i; }
通过上面的代码我们可以看出,每次partation必然会将一个数放到最终的位置,然后再递归处理pivot左右两侧的区间,那么最好的情况就是每次partation都将数组两等分,而最坏的情况是每次partation划分出的区间都在pivot的一侧。
那么如何避免最坏情况的发生呢?这里可以每次选择一个随机数作为pivot然后进行划分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int randomPartation (vector<int > &nums, int left, int right) { int p = rand () % (right - left + 1 ) + left; swap (nums[p], nums[right]); return partation (nums, left, right); }int partation (vector<int > &nums, int left, int right) { int pvoit = nums[right]; int i = left - 1 ; for (int j = left; j <= right; ++j) { if (nums[j] <= pvoit) { ++i; swap (nums[i], nums[j]); } } return i; }
完整的代码如下:
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 36 37 38 vector<int > sortArray (vector<int >& nums) { srand ((unsigned )time (NULL )); randomQuickSort (nums, 0 , (int )nums.size () - 1 ); return nums; }void randomQuickSort (vector<int > &nums, int left, int right) { if (left >= right) return ; int p = randomPartation (nums, left, right); randomQuickSort (nums, left, p - 1 ); randomQuickSort (nums, p + 1 , right); }int randomPartation (vector<int > &nums, int left, int right) { int p = rand () % (right - left + 1 ) + left; swap (nums[p], nums[right]); return partation (nums, left, right); }int partation (vector<int > &nums, int left, int right) { int pvoit = nums[right]; int i = left - 1 ; for (int j = left; j <= right; ++j) { if (nums[j] <= pvoit) { ++i; swap (nums[i], nums[j]); } } return i; }
归并排序
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 #include <iostream> #include <vector> void merge (std::vector<int >& arr, int left, int mid, int right) { int n1 = mid - left + 1 ; int n2 = right - mid; std::vector<int > L (n1) , R (n2) ; for (int i = 0 ; i < n1; ++i) { L[i] = arr[left + i]; } for (int j = 0 ; j < n2; ++j) { R[j] = arr[mid + 1 + j]; } int i = 0 , j = 0 , k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; ++i; } else { arr[k] = R[j]; ++j; } ++k; } while (i < n1) { arr[k] = L[i]; ++i; ++k; } while (j < n2) { arr[k] = R[j]; ++j; ++k; } }void mergeSort (std::vector<int >& arr, int left, int right) { if (left < right) { int mid = left + (right - left) / 2 ; mergeSort (arr, left, mid); mergeSort (arr, mid + 1 , right); merge (arr, left, mid, right); } }void mergeSort (std::vector<int >& arr) { int n = arr.size (); if (n > 1 ) { mergeSort (arr, 0 , n - 1 ); } }int main () { std::vector<int > arr = {12 , 11 , 13 , 5 , 6 , 7 }; mergeSort (arr); std::cout << "Sorted array is: " ; for (int num : arr) { std::cout << num << " " ; } std::cout << std::endl; return 0 ; }