int PartSort1(int *a, int left, int right)
{
int index = GetMid(a, left, right); //三数取中,选取基准值
Swap(&a[index], &a[right]); //将基准值和最右边的值交换
int key = a[right];
int begin = left;
int end = right;
while (begin < end)
{
//begin选大
while (begin < end && a[begin] <= key) //"="可省略
{
begin++;
}
//end选小
while (begin < end && a[end] >= key) //"="不可省略
{
end--;
}
if (begin < end)
{
Swap(&a[begin], &a[end]);
}
}
Swap(&a[begin], &a[right]);
return begin;
}
int PartSort2(int *a, int left, int right)
{
int index = GetMid(a, left, right); //三数取中,选取基准值
Swap(&a[index], &a[right]); //将基准值和最右边的值交换
int key = a[right]; //保存基准值
int begin = left;
int end = right;
while (begin < end)
{
//begin选大
while (begin < end && a[begin] <= key)
{
begin++;
}
a[end] = a[begin];
//end选小
while (begin < end && a[end] >= key)
{
end--;
}
a[begin] = a[end];
}
a[begin] = key;
return begin;
}
void QuickSort(int *a, int left, int right)
{
assert(a);
Stack s;
StackInit(&s);
StackPush(&s, left);
StackPush(&s, right);
while (!StackEmpty(&s))
{
intend = StackTop(&s);
StackPop(&s);
intbegin = StackTop(&s);
StackPop(&s);
int div = PartSort1(a, begin, end);
if (begin < div - 1)
{
StackPush(&s, begin);
StackPush(&s, div - 1);
}
if (div + 1 < end)
{
StackPush(&s, div + 1);
StackPush(&s, end);
}
}
}
分析:
时间复杂度:
最好情况:O(N*lgN)
最坏情况:O(N^2)
平均情况:O(N*lgN)
空间复杂度:O(lgN)——递归深度 稳定性:不稳定
七、归并排序
基本思想:
将待排序的元素序列分成两个长度相等的子序列,对每一个子序列排序,然后再将它们合并成一个有序序列。
图解:
合并图解:
代码实现:
//归并局部递归void _MergeSort(int *a, int left, int right, int *tmp)
{
if (left >= right)
{
return;
}
if (right - left < 10) //优化:在区间较小时,插入排序的效率高
{
InsertSort(a, right - left + 1);
return;
}
int mid = left + ((right - left) >> 1);
_MergeSort(a, left, mid, tmp);
_MergeSort(a, mid + 1, right, tmp);
int p = left;
int q = mid + 1;
intindex = 0;
while (p <= mid&&q <= right)
{
if (a[p] <= a[q]) //加上"="可保持稳定性
{
tmp[index++] = a[p++];
}
else
{
tmp[index++] = a[q++];
}
}
while (p <= mid)
{
tmp[index++] = a[p++];
}
while (q <= mid)
{
tmp[index++] = a[q++];
}
int j = 0;
for (int i = left; i <= right; i++)
{
a[i] = tmp[j++];
}
}
void MergeSort(int *a, int left, int right)
{
assert(a);
int *tmp = (int*)malloc((right - left + 1)*sizeof(int));
memset(tmp, 0, (right - left + 1)*sizeof(int));
//或者:int *tmp = (int *)calloc(right - left + 1,sizeof(int));
_MergeSort(a, left, right, tmp);
free(tmp);
}
分析:
时间复杂度:O(N*lgN) 空间复杂度:O(N)——临时数组 稳定性:稳定
八、计数排序
基本思想:
统计待排序序列中每个元素出现的次数,再根据统计的结果重新对元素进行回收。
图解:
代码实现:
void CountSort(int *a, int size)
{
assert(a);
//(1)找出最值,确定范围,以便开辟空间int max = a[0];
int min = a[0];
intindex = 0;
for (index = 1; index < size; index++)
{
if (a[index]>max)
{
max = a[index];
}
if (a[index] < min)
{
min = a[index];
}
}
int range= max - min + 1;
//(2)统计出现次数int *tmp = (int*)calloc(range, sizeof(int));
for (index = 0; index < size; index++)
{
tmp[a[index] - min]++;
}
//(3)回收int i = 0;
for (index = 0; index < range; index++)
{
while (tmp[index])
{
a[i++] = index + min;
tmp[index]--;
}
}
free(tmp);
tmp = NULL;
}