希爾排序
https://blog.csdn.net/u012918361/article/details/68921601
希爾排序作爲第一批突破O(n^2)的算法之一,在數據中等規模時候性能很好,大規模時候沒有快排好
時間複雜度O(nlogn)不好證明
基本思路:插入排序的改進,就是不斷分組,每組進行插入排序
注意傳入引用,不然按值傳遞速度很慢
void ShellSort(vector<int>& v)
{
int length = v.size();
for (int gap = length / 2; gap > 0; gap = gap / 2) // d,分的組數,比如數組長度14,則分爲7,3,1
{
//插入排序
for (int i = gap; i < length; i++) // i遍歷每組中未排序元素
{
int temp = v[i];
int j = 0;
for (j = i - gap; j >= 0; j -= gap) // j遍歷已排序數組(從後往前),把i插入到適當位置
{
if (temp < v[j]) {
v[j + gap] = v[j]; //後移
} else {
break;
}
}
v[j + gap] = temp;
}
}
}
快速排序(分治+挖坑法)
https://cloud.tencent.com/developer/article/1338521
https://www.cxyxiaowu.com/5262.html
先後策略來把一個序列分爲較小和較大的2個子序列,然後遞歸地排序兩個子序列。
分治思想:
1.挑選基準值 2.分割:所有比基準值小的元素放在基準值前面,大的都放到基準值後面,在這個過程結束後,基準值的排序就完成了。3。遞歸
挖坑思想:
分割的時候使用挖坑法:每次取第一個作爲基準值,然後從右向左排坑,再從左向右排坑,每次循環會把一個大數放後面,把一個小的數放前面。完整循環後,會把基準數放到正確的位置。
// 快排分解解析
// partition方法就是把傳入的數組中第一個數作爲基準值,然後把基準值放到正確的位置,返回這個位置
int partition(vector<int>& arr, int l, int r)
{
int temp = arr[l]; // 基準值
while (l < r) {
while (l < r && arr[r] >= temp)
r--;
arr[l] = arr[r];
while (l < r && arr[l] <= temp)
l++;
arr[r] = arr[l];
}
arr[l] = temp;
return l;
}
//分治代碼
void quickSort(vector<int>& arr, int low, int high)
{
if (low >= high)
return;
//每次把基準值的位置放正確
int index = partition(arr, low, high);
// Separately sort elements before
// partition and after partition
quickSort(arr, low, index - 1); //對基準值左側進行排序
quickSort(arr, index + 1, high); // 對基準值右側再排序
}
整理後的簡潔代碼
void QuickSort(vector<int>& s, int l, int r)
{
//終止條件
if (l >= r)
return;
//每次基準值的放置,使用挖坑法
int i = l, j = r; //定義左右兩個指針
int x = s[l]; //選取第一個數作爲基準值
while (i < j) {
// 從右向左找第一個小於基準數的數
while (i < j && s[j] >= x)
j--;
if (i < j) {
s[i] = s[j]; // 找到該數,放入坑中,
i++; //左指針後移一位
}
// 從左向右找第一個大於等於基準數的數
while (i < j && s[i] < x)
i++;
if (i < j) {
s[j] = s[i];
j--;
}
//一次循環後,把一個大於基準數的數放到右邊,一個小於基準數的數放到左邊
} //整個循環後,大於基準數的數都放到了右邊,小於key都放到了左邊
s[i] = x; // 基準數找到了合適的位置
//分治,遞歸調用
QuickSort(s, l, i - 1); //基準值左邊
QuickSort(s, i + 1, r); //基準值右邊
}
測試用例
#include <iostream>
#include <vector>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
int N = 1000000; //一百萬
// int N = 1000;
srand(time(NULL)); //生成隨機數種子
//放到vector中
vector<int> nums(N);
for (int i = 0; i < N; ++i) {
nums[i] = 1 + (rand() % N);
}
//開始計時
double start, finish;
start = (double)clock();
// ShellSort(nums); // 525ms
QuickSort(nums, 0, N - 1); // 180ms
// quickSort(nums, 0, N - 1); // 200ms
finish = (double)clock();
//打印
// for (auto item : nums) {
// cout << item << ",";
// }
cout << endl;
printf("%.4fms\n", (finish - start));
}