文章目录
插入
InsertSort
void InsertSort(int* a, int n)
{
assert(a);
assert(n >= 0);
for (int i = 0; i < n-1; i++)
{
int end = i;
int tmp = a[end+1];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}

ShellSort
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap = (gap / 3 + 1);
for (int i = 0; i < n - gap; i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
a[end + gap] = tmp;
}
}
}
}

对比测试
void TestOP()
{
srand(time(0));
const int N = 100000;
int* a1 = (int*)malloc(sizeof(int) * N);
int* a2 = (int*)malloc(sizeof(int) * N);
int* a3 = (int*)malloc(sizeof(int) * N);
int* a4 = (int*)malloc(sizeof(int) * N);
int* a5 = (int*)malloc(sizeof(int) * N);
int* a6 = (int*)malloc(sizeof(int) * N);
for (int i = 0; i < N; ++i)
{
a1[i] = rand();
a2[i] = a1[i];
a3[i] = a1[i];
a4[i] = a1[i];
a5[i] = a1[i];
a6[i] = a1[i];
}
int begin1 = clock();
InsertSort(a1, N);
int end1 = clock();
int begin2 = clock();
ShellSort(a2, N);
int end2 = clock();
printf("InsertSort:%d\n", end1 - begin1);
printf("ShellSort:%d\n", end2 - begin2);
free(a1);
free(a2);
free(a3);
free(a4);
free(a5);
free(a6);
}
选择
SelectSort
void SelectSort(int* a, int n)
{
int left = 0;
int right = n - 1;
while (left < right)
{
int minIndex = left;
int maxIndex = left;
for (int i = left; i <= right; i++)
{
if (a[i] < a[minIndex])
{
minIndex = i;
}
if (a[i] > a[maxIndex])
{
maxIndex = i;
}
}
Swap(&a[left], &a[minIndex]);
if (left == maxIndex)
{
maxIndex = minIndex;
}
Swap(&a[right], &a[maxIndex]);
++left;
--right;
}
}
HeapSort
void AdjustDown(int* a, int n, int root)
{
int parent = root;
int child = parent * 2 + 1;
while (child < n)
{
if (child+1 < n && a[child+1] > a[child])
{
++child;
}
if (a[child]>a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* a, int n)
{
for (int i = (n-1-1)/2; i >= 0 ; i--)
{
AdjustDown(a, n, i);
}
int end = n - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, end, 0);
end--;
}
对比测试
InsertSort:1144
ShellSort:8
SelectSort:5162
HeapSort:7
交换
BubbleSort
void BubbleSort(int* a, int n)
{
for (int end = n; end > 0; end--)
{
int exchange = 0;
for (int i = 1; i < end; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
{
break;
}
}
}
QuickSort
void QuickSort(int* a, int begin, int end)
{
if (begin >= end)
return;
int left = begin, right = end;
int keyi = left;
while (left < right)
{
while (left < right && a[right] >= a[keyi])
{
--right;
}
while (left < right && a[left] <= a[keyi])
{
++left;
}
Swap(&a[left], &a[right]);
}
int meeti = left;
Swap(&a[keyi], &a[left]);
QuickSort(a, begin, meeti - 1);
QuickSort(a, meeti+1, end);
}
PartSort
void QuickSort(int* a, int begin, int end)
{
if (begin >= end)
return;
int keyi = PartSort1(a, begin, end);
QuickSort(a, begin, keyi - 1);
QuickSort(a, keyi +1, end);
}
用QuickSort去排一个有序的序列,比InsertSort还慢
InsertSort:1143
ShellSort:7
SelectSort:5092
HeapSort:7
QuickSort:1309
左右指针法
int PartSort1(int* a, int left, int right)
{
int keyi = left;
while (left < right)
{
while (left < right && a[right] >= a[keyi])
{
--right;
}
while (left < right && a[left] <= a[keyi])
{
++left;
}
Swap(&a[left], &a[right]);
}
Swap(&a[keyi], &a[left]);
return left;
}
挖坑法
int PartSort2(int* a, int left, int right)
{
int key = a[left];
while (left < right)
{
while (left < right && a[right] >= key)
{
--right;
}
a[left] = a[right];
while (left < right && a[left] <= key)
{
++left;
}
a[right] = a[left];
}
a[left] = key;
return left;
}

前后指针法
cur prev 一前一后
cur去找比keyi位置小的值
找到小之后,++prev,再交换prev和cur位置的值
直到数组尾
最后交换prev和keyi位置的值
思想: 把小的往左边留,大的往右边留,prev++是为了跟上cur

int PartSort3(int* a, int left, int right)
{
int midIndex = GetMidIndex(a, left, right);
Swap(&a[left], &a[midIndex]);
int keyi = left;
int prev = left, cur = left + 1;
while (cur <= right)
{
if (a[cur] < a[keyi] && ++prev != cur)
{
Swap(&a[prev], &a[cur]);
}
cur++;
}
Swap(&a[keyi], &a[prev]);
return prev;
}
优化
三数取中优化
int GetMidIndex(int* a, int left, int right)
{
int mid = (left + right) >> 1;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return left;
}
else
{
return right;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
int PartSort1(int* a, int left, int right)
{
int midIndex = GetMidIndex(a, left, right);
Swap(&a[left], &a[midIndex]);
int keyi = left;
while (left < right)
{
while (left < right && a[right] >= a[keyi])
{
--right;
}
while (left < right && a[left] <= a[keyi])
{
++left;
}
Swap(&a[left], &a[right]);
}
Swap(&a[keyi], &a[left]);
return left;
}
三数取中优化后,恰好是有序的数据
InsertSort:1134
ShellSort:8
SelectSort:5144
HeapSort:7
QuickSort:1
1000w的随机数据排序:
InsertSort:0
ShellSort:1217
SelectSort:0
HeapSort:2530
QuickSort:593
小区间优化
void QuickSort(int* a, int begin, int end)
{
if (begin >= end)
return;
if (end-begin > 10)
{
int keyi = PartSort3(a, begin, end);
QuickSort(a, begin, keyi - 1);
QuickSort(a, keyi + 1, end);
}
else
{
InsertSort(a + begin, end - begin + 1);
}
}
非递归
void QuickSortNonR(int* a, int begin, int end)
{
Stack st;
StackInit(&st);
StackPush(&st, begin);
StackPush(&st, end);
while (!StackEmpty(&st))
{
int left, right;
right = StackTop(&st);
StackPop(&st);
left = StackTop(&st);
StackPop(&st);
int keyi = PartSort3(a, left, right);
if (left<keyi-1)
{
StackPush(&st, left);
StackPush(&st, keyi-1);
}
if (keyi+1<right)
{
StackPush(&st, keyi + 1);
StackPush(&st, right);
}
}
StackDestroy(&st);
}
对比测试
InsertSort:1137
ShellSort:8
SelectSort:5149
HeapSort:8
QuickSort:5
InsertSort:1129
ShellSort:8
SelectSort:5112
HeapSort:8
QuickSort:1
归并
MergeSort

void _MergeSort(int* a, int left, int right, int* tmp)
{
if (left >= right)
{
return;
}
int mid = (left + right) >> 1;
_MergeSort(a, left, mid, tmp);
_MergeSort(a, mid+1, right, tmp);
int begin1 = left, end1 = mid;
int begin2 = mid+1, end2 = right;
int i = left;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
for (int j = left; j <= right; j++)
{
a[j] = tmp[j];
}
}
void MergeSort(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
_MergeSort(a, 0, n - 1, tmp);
free(tmp);
}
时间复杂度O(N*logN)
每一层归并都是N
logN层
空间复杂度O(N)
InsertSort:1141
ShellSort:7
SelectSort:5085
HeapSort:7
QuickSort:1
MergeSort:8
MergeSortNonR

void _Merge(int* a, int* tmp, int begin1, int end1, int begin2, int end2)
{
int i = begin1;
int j = begin1;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
for (; j <= end2; j++)
{
a[j] = tmp[j];
}
}
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i += 2 * gap)
{
_Merge(a, tmp, i, i + gap - 1, i + gap, i + 2 * gap - 1);
}
gap *= 2;
}
free(tmp);
}
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i += 2 * gap)
{
int begin1 = i, end1 = i + gap - 1, begin2 = i + gap, end2 = i + 2 * gap - 1;
if (begin2 >= n)
{
break;
}
if (end2 >= n)
{
end2 = n - 1;
}
_Merge(a, tmp, begin1, end1, begin2, end2);
}
gap *= 2;
}
free(tmp);
}

非比较排序
CountSort
绝对映射
统计出每个数出现的次数
A[i]是几就对Count数组对应位置的值++
统计出次数再排序
相对映射
映射时减去最小的那个值

void CountSort(int* a, int n)
{
int max = a[0], min = a[0];
for (int i = 0; i < n; i++)
{
if (a[i] > max)
max = a[i];
if (a[i] < min)
min = a[i];
}
int range = max - min + 1;
int* count = (int*)malloc(sizeof(int) * range);
if (count == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memset(count, 0, sizeof(int) * range);
for (int i = 0; i < n; i++)
{
count[a[i] - min]++;
}
int i = 0;
for (int j = 0; j < range; j++)
{
while (count[j]--)
{
a[i++] = j + min;
}
}
free(count);
}
内排序
外排序
总结

稳定性
