作为最常用的三大排序方法,必须掌握。这里给出递归写法C++实现,相比迭代写法会更容易理解。
- #include
- #include
-
- using namespace std;
-
- class Solution {
- public:
- void SortArr(vector<int>& nums) {
- //quickSort(nums, 0, nums.size() - 1);
- //mergeSort(nums, 0, nums.size() - 1);
- heapSort(nums);
- }
-
- private:
- void quickSort(vector<int>& nums, int l, int r) {
- if (l < r) {
- int pos = partition2(nums, l, r);
- quickSort(nums, l, pos - 1);
- quickSort(nums, pos + 1, r);
- }
- }
-
- // 以pivot分隔,选最左为pivot
- // 第一种Partition方式,对撞指针法
- int partition(vector<int>& nums, int l, int r) {
- // 随机化加速,抑制最坏时间复杂度
- int i = rand() % (r - l + 1) + l;
- swap(nums[i], nums[l]);
- int pivot = nums[l];
- while (l < r) {
- // 右侧第一个小于pivot的元素
- while (l < r && nums[r] >= pivot) --r;
- nums[l] = nums[r];
- // 左侧第一个大于pivot的元素
- while (l < r && nums[l] <= pivot) ++l;
- nums[r] = nums[l];
- }
- nums[l] = pivot;
- return l;
- }
-
- // 第二种Partition方式,快慢指针法
- int partition2(vector<int>& nums, int l, int r) {
- // 随机化加速,抑制最坏时间复杂度
- int tmp = rand() % (r - l + 1) + l;
- swap(nums[tmp], nums[l]);
- int pivot = nums[l];
- int i = l + 1;
- for (int j = l + 1; j <= r; ++j) {
- if (nums[j] <= pivot) {
- swap(nums[i], nums[j]);
- ++i;
- }
- }
- swap(nums[i-1], nums[l]);
- return i-1;
- }
-
- void mergeSort(vector<int>& nums, int l, int r) {
- if (l == r) return;
-
- // 分解
- int mid = l + (r - l) / 2;
- mergeSort(nums, l, mid);
- mergeSort(nums, mid + 1, r);
-
- // 合并
- int i = l, j = mid + 1, pos = 0;
- vector<int> tmp(r - l + 1); // 合并时需要辅助数组
- while (i <= mid && j <= r) {
- tmp[pos++] = nums[i] <= nums[j] ? nums[i++] : nums[j++];
- }
- // 还有剩余
- while (i <= mid) {
- tmp[pos++] = nums[i++];
- }
- while (j <= r) {
- tmp[pos++] = nums[j++];
- }
- copy(tmp.begin(), tmp.end(), nums.begin() + l);
- }
-
- void heapSort(vector<int>& vec) {
- int sz = vec.size();
- // S1.建大顶堆
- // sz/2-1是最后一个非叶子节点
- for (int i = sz / 2 - 1; i >= 0; --i) {
- down(vec, i, sz);
- }
-
- // S2.大顶堆一个一个把最大的移到末尾
- for (int i = sz - 1; i > 0; --i) {
- swap(vec[0], vec[i]); // 把最大的移到末尾
- down(vec, 0, i); // 维持大顶堆,只需调整i=0,注意sz变为了i
- }
- }
-
- void down(vector<int> &vec, int i, int sz) {
- // 核心就是找i和其lSon、rSon三者最大的换到i的位置
- int lSon = i * 2 + 1;
- int rSon = i * 2 + 2;
- int maxIdx = i;
- if (lSon < sz && vec[lSon] > vec[maxIdx]) maxIdx = lSon;
- if (rSon < sz && vec[rSon] > vec[maxIdx]) maxIdx = rSon;
-
- if (maxIdx != i) {
- swap(vec[i], vec[maxIdx]);
- down(vec, maxIdx, sz);
- }
- }
- };
-
- int main() {
- Solution sln = Solution();
- vector<int> nums = { 1, 3, 5, 2, 2, 6 };
- sln.SortArr(nums);
- for (int num : nums) {
- cout << num << ' ';
- }
- return 0;
- }
快排本身有劣势,数字一样变n方。
实现思路可参考: