目录
一、希尔排序
二、堆排序
三、归并排序
四、快速排序
五、计数排序
六、基数排序
思路:
时间复杂度:不稳定,与数组的初始有序度及gap的计算方法有关,介于O(n) ~ O(n^2)
void ShellSort(int* arr, int size)
{
int gap = size;
while (gap > 1)
{
gap = gap / 3 + 1;
int i = 0;
for (i = 0; i < size - gap; ++i)
{
int end = i;
int tmp = arr[end + gap];
while (end >= 0 && tmp < arr[end])
{
arr[end + gap] = arr[end];
end -= gap;
}
arr[end + gap] = tmp;
}
}
}
思路:
时间复杂度:稳定,每次从堆顶向下调整为 lg(n),总复杂度为 n * lg(n)
#include
void Swap(int* arr, int pi, int pj)
{
int tmp = arr[pi];
arr[pi] = arr[pj];
arr[pj] = tmp;
}
//大根堆:升序
//小根堆:降序
void AdjustDown(int* arr, int parent, int size)
{
int child = parent * 2 + 1;
while (child < size) {
if (child + 1 < size && arr[child + 1] > arr[child])
++child;
if (arr[parent] < arr[child])
{
Swap(arr, parent, child);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* arr, int size)
{
int parent = (size - 2) / 2;
int i;
for (i = parent; i >= 0; --i)
{
AdjustDown(arr, i, size); //构建大根堆
}
while (size)
{
Swap(arr, 0, --size);
AdjustDown(arr, 0, size);
}
}
思路:
时间复杂度:稳定,递归的复杂度为 lg(n),每个数都会遍历一次,总复杂度为 n * lg(n)
void _MergeSort(int* arr, int begin, int end, int* count)
{
if (begin >= end)
return;
int mid = (begin + end) / 2;
_MergeSort(arr, begin, mid, count);
_MergeSort(arr, mid + 1, end, count);
int begin1 = begin, end1 = mid;
int begin2 = mid + 1, end2 = end;
int i = begin;
while (begin1 <= end1 && begin2 <= end2)
{
if (arr[begin1] < arr[begin2])
count[i++] = arr[begin1++];
else
count[i++] = arr[begin2++];
}
while (begin1 <= end1)
{
count[i++] = arr[begin1++];
}
while (begin2 <= end2)
{
count[i++] = arr[begin2++];
}
memcpy(arr + begin, count + begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* arr, int size)
{
int* count = (int*)malloc(sizeof(int) * size);
int mid = size / 2;
_MergeSort(arr, 0, mid, count);
_MergeSort(arr, mid + 1, size - 1, count);
free(count);
count = NULL;
}
思路:
时间复杂度:不稳定,平均复杂度是O(n * lg(n))
void Swap(int* arr, int pi, int pj)
{
int tmp = arr[pi];
arr[pi] = arr[pj];
arr[pj] = tmp;
}
//取中位数
int MidNum(int* arr, int l, int m, int r)
{
if (arr[l] < arr[r])
{
if (arr[m] < arr[l])
return l;
else if (arr[m] < arr[r])
return m;
else
return r;
}
else
{
if (arr[m] > arr[l])
return l;
else if (arr[m] > arr[r])
return m;
else
return r;
}
}
//前后指针法
int PtrPrt(int* arr, int begin, int end)
{
int mid = (begin + end) / 2;
int keyi = MidNum(arr, begin, mid, end);
Swap(arr, keyi, begin);
int front = begin;
int back = begin + 1;
while (back <= end)
{
if (arr[back] < arr[begin] && ++front != back)
Swap(arr, front, back);
++back;
}
Swap(arr, begin, front);
return front;
}
void QuickSort(int* arr, int begin, int end)
{
if (begin >= end)
return;
int keyi = PtrPrt(arr, begin, end);
QuickSort(arr, begin, keyi - 1);
QuickSort(arr, keyi + 1, end);
}
思路:
复杂度:不稳定,介于O(n) ~ O(n^2)
void CountSort(int* arr, int size)
{
int min = arr[0], max = arr[0];
int i;
for (i = 0; i < size; ++i)
{
if (arr[i] < min)
min = arr[i];
if (arr[i] > max)
max = arr[i];
}
int* count = (int*)malloc(sizeof(int) * (max - min + 1));
memset(count, 0, max - min + 1);
for (i = 0; i < size; ++i)
{
count[arr[i] - min]++;
}
int j = 0;
for (i = 0; i < max - min + 1; ++i)
{
while (count[i]--)
{
arr[j++] = i + min;
}
}
}
思路:
时间复杂度:与最大值的位数K有关,K * O(n),所以时间复杂度为O(n)
#include
#include
using namespace std;
#define K 3 //数组中最大数据的位数
#define RADIX 10
//定义基数
queue g_q[RADIX];
int GetKey(int val, int k)
{
int key = val % 10;
while (k--)
{
val /= 10;
key = val % 10;
}
return key;
}
void Distribute(int* arr, int left, int right, int k)
{
for (int i = left; i <= right; ++i)
{
int key = GetKey(arr[i], k);
g_q[key].push(arr[i]);
}
}
void Collect(int* arr)
{
int j = 0;
for (int i = 0; i < RADIX; ++i)
{
while (!g_q[i].empty())
{
arr[j++] = g_q[i].front();
g_q[i].pop();
}
}
}
void RadixSort(int* arr, int size)
{
for (int i = 0; i < K; ++i)
{
Distribute(arr, 0, size - 1, i); //分发数据
Collect(arr); //收集数据
}
}