排序算法總結:
1.比較排序
- 插入排序:直接插入,希爾排序
- 選擇排序:直接選擇,堆排序
- 交換排序:冒泡排序,快速排序
- 歸併排序
2.非比較排序
- 計數排序
各自實現原理:
1.插入排序:遍歷整個數組,遍歷到每一位時,以這一位爲基準,往前遍歷,選擇合適的地方插入,不合適的元素往後移動
void InsertSort(int *arr, int size)
{
for (int i = 0; i < size; i++)
{
int key = arr[i];
int end = i - 1;
while (key < arr[end])//end來標記該插入的位置
{
arr[end + 1] = arr[end];
end--;
}
//到這裏已經找到插入的位置
arr[end+1] = key;
}
}
時間複雜度:O(N^2)
空間複雜度:O(1)
穩定性:穩定
適用場景:元素個數小 元素順序接近有序
2.希爾排序: 使用間隔分組的方法插入排序 不穩定(隔着元素交換就不穩定) 如圖:
分成三組
void ShellSort(int *arr, int size)
{
int grap = 3;
while (grap--)
{
for (int i = grap; i < size; i++)
{
int key = arr[i];
int end = i - grap;
while (key < arr[end])//end來標記該插入的位置
{
arr[end + grap] = arr[end];
end-=grap;
}
//到這裏已經找到插入的位置
arr[end + grap] = key;
}
}
}
空間複雜度;O(1)
時間複雜度;取決於ret,間距
適用場景:量大,亂序
3.選擇排序:遍歷整個數組,找到最大的數和最小的數,最大的數放在最右邊,最小的數放在最左邊,(特殊情況特殊處理,比如最大的數剛好在最右邊,最小的數剛好早最右邊) 缺陷:進行重複比較
void SelectSort(int* arr, int size)
{
int begin = 0;
int end = size - 1;
while (begin<end)
{
int maxpos = begin;
int minpos = begin;
int index = begin + 1;
while (index <= end)
{
if (arr[index]>arr[maxpos])
{
maxpos = index;
}
if (arr[index] < arr[minpos])
{
minpos = index;
}
index++;
}
if (maxpos != end)
swap(arr[maxpos], arr[end]);
if (minpos == end)
minpos = maxpos;
if (minpos != begin)
swap(arr[minpos], arr[begin]);
begin++;
end--;
}
}
4.冒泡排序:不穩定
void BubSort(int *arr, int size)
{
int flag = 0;
for (int i = 0; i < size-1; i++)
{
for (int j = 0; j < size - 1 - i; j++)
{
if (arr[j]>arr[j + 1])
{
flag = 1;
swap(arr[j], arr[j + 1]);
}
}
if (flag == 0)
{
break;
}
}
}
5.快速排序
//挖坑填數
int AdjustArray(int *arr, int left, int right)
{
int i = left;
int j = right;
int s = arr[left];
while (i < j)
{
while (i < j && arr[j] >= s)
j--;
if (i < j) //這時從右往左找到小於基準值的數
//arr[i]爲上一次的坑 填arr[i] 然後遍歷i
{
arr[i] = arr[j];
i++;
}
while (i < j && arr[i] <= s)
i++;
if (i < j) //這時從左往右找到大於基準值的數
//arr[j]爲上一次的坑 填arr[j] 然後遍歷j
{
arr[j] = arr[i];
j--;
}
}
//此時從左往右遍歷完,arr[i]此時爲坑,將基準值填入,左邊的數全比基準值小,
arr[i] = s;
return i;
}
//分治
void quicksort(int *arr, int left, int right)
{
if (left < right)
{
int ret = AdjustArray(arr, left, right);
quicksort(arr, left, ret);
quicksort(arr, ret + 1,right);
}
}
int main()
{
int arr[] = { 9, 7, 6, 4, 32, 1, 5, 9 };
int size = sizeof(arr) / sizeof(arr[0]);
quicksort(arr, 0, size-1);
for (int i = 0; i < size;i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
6.堆排序
/**
* 篩選位置i, 調整堆
* @param a 待排序序列(數組)
* @param i 篩選位置
* @param len 數組元素個數
*/
void HeapAdjust(int a[], int i, int n)
{
if(i > n / 2 - 1)
{// 葉子結點, 無子樹
return;
}
// 檢查結點i是否符合小堆特性, 如果不符合, 需要與最小子結點交換
for(int k = 2*i +1; k < n; k = 2*k + 1)
{
// 判斷右子樹是否比左子樹更小
if(k+1 < n && a[k+1] < a[k])
{
k ++; // 更新最小子結點
}
if(a[i] > a[k])
{
Swap(a[i], a[k]); // 與最小的子結點交換
i = k; // 將左子結點設爲當前結點
}
else
{// 符合小堆特性
break;
}
}
}
7.歸併排序
//合併兩個有序數組
void mergerarry(int *a, int first, int mid, int last, int *temp)
{
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
//到這裏將剩餘的數填入
while (i <= m)
{
temp[k++] = a[i++];
}
while (j <= n)
{
temp[k++] = a[j++];
}
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
//分治 遞歸分組,然後依次向上合併
void mergersort(int *a, int first, int last, int *temp)
{
if (first < last)
{
int mid = (first + last) / 2;
mergersort(a, first, mid, temp);
mergersort(a, mid+1, last, temp);
mergerarry(a, first, mid, last, temp);
}
}
//主調函數
bool Mergesort(int *a, int n)
{
int *p = new int[n];
if (p == NULL)
{
return false;
}
mergersort(a, 0, n - 1, p);
delete[]p;
return true;
}
int main()
{
int arr[] = { 9, 7, 6, 4, 32, 1, 5, 9 };
int size = sizeof(arr) / sizeof(arr[0]);
Mergesort(arr, size);
for (int i = 0; i < size;i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
8.計數排序
//時間複雜度:O(N)--->N代表元素個數
//空間複雜度: O(M)--->M代表數據範圍
void CountSort(int *arr, int size)
{
int minValue = arr[0];
int maxValue = arr[0];
for (int i = 1; i < size; i++)
{
if (arr[i]>maxValue)
{
maxValue = arr[i];
}
if (arr[i] < minValue)
{
minValue = arr[i];
}
}
//統計每個元素出現的次數
int range = maxValue - minValue + 1;
int *pCount = (int*)malloc(sizeof(int)*range);
if (NULL == pCount)
{
return;
}
memset(pCount, 0, sizeof(int)*range);
for (int i = 0; i < size; i++)
{
pCount[arr[i] - minValue]++;
}
int index = 0;
//排序 對pCount中的元素進行回收
for (int i = 0; i < range; i++)
{
while (pCount[i])
{
arr[index++] = i + minValue;
pCount[i]--;
}
}
free(pCount);
}
int main()
{
int arr[] = { 3, 4, 7, 1, 1, 0, 9, 8, 5, 2, 2, 5, 6 };
int size = sizeof(arr) / sizeof(arr[0]);
CountSort(arr, size);
for (int i = 0; i < size; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}