(1)归并排序
算法思想:
(1)对于一个人数组,首先把数组平均分为两部分,即[low,mid]和[mid+1,high],
(2)分别对左右两部分进行再进行归并排序。
(3)将左右两步部分合并
例如以下例子:开始将数据看成长度为1的有序表,两两归并为长度为2的表,依次类推直到长度为n的有序表
性能分析:平均时间复杂度O(nlogn),空间复杂度O(1),比较稳定
代码:
void Merge(int pNew[], int low,int mid,int high,int b[])
{
int k = 1,i = low, j = mid + 1;
while (i<=mid && j<= high)
{
if (pNew[i] < pNew[j])
{
b[k] = pNew[i];
k++;
i++;
}
else
{
b[k] = pNew[j];
k++;
j++;
}
}
while (i <= mid)
{
b[k] = pNew[i];
i++;
k++;
}
while (j <= high)
{
b[k] = pNew[j];
j++;
k++;
}
}
void MSort(int a[], int low, int high, int b[])
{
//申请一个辅助空间,用来存放数组a的mid两边的已经归并好的数
int pNew[12];
//判断low与high是否相等,如果相等就直接可以放到,不需要归并排序了
if (low == high)
{
b[low] = a[low];
}
else
{
int mid = (low + high) / 2;
//对mid左边的数进行归并排序
MSort(a, low, mid, pNew);
//对mid右边的数进行归并排序
MSort(a, mid + 1, high, pNew);
//合并pNew中左右数
Merge(pNew, low, mid, high, b);
}
}
void MergeSort(int a[],int len)
{
MSort(a, 1, len, a);//做归并排序
}
(2)基数排序在, 比较适用于元素数值位数相差不大时候最好
算法思性:
(1)首先要有是个桶,其实就是十个队列,元素值得各位对应着桶的编号。
(2)把桶中数据一一拿出来放回原数组,比较元素的十位数,按十位数的大小与桶的编号对应起来。
(3)这时候再把桶中拿出来放回原数组,比较元素的百位数,操作和上面相同,直到到达位数中最大结束,这时候就是有序的了。
例子:例子: B = 5、2、9、7、18、17、52 用基数排序法进行排序。
首先根据元素的个位数放入各个桶:
收集桶中元素为:2 , 52, 5, 7, 17, 18, 9,再按十位放入桶
收集桶中元素为:2,,5,7,9,17,18,52,所以最后得到排序。
性能分析: 时间:上例中每个数有 t = 2 位,因此执行 t = 2 次分配和收集就可以了。在一般情况下,每个结点有 d 位关键字,必须执行 t = d次分配和收集操作。分配的代价:O(n) ,收集的代价:O(rd(rd是基数),总的代价为:O( d ×(n + rd)).
代码:
#define MAXSIZE 20
#include <queue>
queue<int> sta[10];
void RadixSort(int a[], size_t length)
{
int NumSum = 1;//表示数组中元素最大位数
while (NumSum!=4)
{
for (size_t i = 0; i < length; i++)
{
int n = (a[i] % (int)pow(10, NumSum)) / (pow(10, NumSum-1));
sta[n].push(a[i]);
}
int k = 0;
for (int i = 0; i < 10; i++)
{
while (!sta[i].empty())
{
a[k] = sta[i].front();
sta[i].pop();
k++;
}
}
NumSum++;
}
}
(3)小结:
排序方法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|
归并排序 | O(nlogn) | O(nlogn) | O(n) | 稳定 |
基数排序 | O(d(n+rd)) | O(d(n+rd)) | O(rd) | 稳定 |
R是关键字的取值范围,d是位数