4.选择排序
选择排序的基本思想就是:每一趟从待排序记录中选出关键字最小的记录,将顺序将其放在已排好序的序列的最后,知道排完为之。
4.1简单选择排序
又称直接选择排序。
就是从第一个开始,经过n-1排序,选出最小的记录。
//简单选择排序
void SelectSort(SqList &L)
{
int i;
for(i=0;i<L.length;i++)
{
k=SelectMinkey(L,i);
if(k!=i)//需要交换两个数值,方便后续寻找
{
int a;
a=L.r[i];
L.r[i]=L.r[k];
L.r[k]=a;
}
}
}
int SelectMinkey(SqList &L,int n)
{
int min;
int i;
min=n;
for(i=n;i<L.length;i++)
{
if(L.r[i]<L.r[min])
{
min=i;
}
}
return min;//返回最小值的位置,而不是最小值
}
时间复杂度为O(n的平方)。
空间复杂度为O(1)。
算法特点:本身是中稳定的排序方法,也可用于链式存储结构,移动次数比较少,当每一记录占用空间较多时,此方法比直接插入排序快。
4.2堆排序
堆排序是一种树形选择排序,在排序过程中,将排序记录看成一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点的内在关系,在当前无序的序列中选择关键字最大(或最小)的记录。
//堆排序(操作复杂度为logn)
void HeapAdjust(SqList &L,int i,int m)//这个就是将数组变成二叉树,然后调整成大根堆或者小根堆
{
int a;
a=L.r[i];//保留变量
for(j=2*i;j<=m;j*=2)//子树就是×2
{
if(L.r[j]<L.r[j+1])//先比较左右子树
{
j=j+1;
}
if(L.r[j]=<a)//这个就是较大的子树跟父亲结点比较
break;
L.r[i]=L.r[j];
i=j;//改变初变量的位置
}
L.r[i]=a;
}
void HeapSort(SqList &L)//调用前面的函数
{
int i;
for(i=L.length/2;i>0;i--)//从最后一个结点的父亲结点开始,从下往上依次调用
{
HeapAdjust(L,i,L.length);
}
for(i=L.length;i>0;i--)
{
int b;
b=L.r[i];
L.r[i]=L.r[1];
L.r[1]=b;//将头结点跟尾结点交换
HeapAdjust(L,1,i-1);//因为前面只是交换了一个结点,不需要重新排列,只需将第一个结点重新排序即可
}
}
时间复杂度堆排序在最坏的情况下,时间复杂度为O(nlogn)
实验研究表明,堆排序的平均性能接近于最坏性能
空间复杂度:O(1)
算法特点:是不稳定排序,不能用于链式存储结构,初始建堆所需的比较次数较多,因此记录数较少时不宜采用。最坏情况下,比快速排序更有优势,记录较多时较为高效。
5.归并排序
归并排序就是将两个或两个以上的有序表合并成一个有序表的过程。
//归并排序
void Merge(SqList &L,SqList &t,int low,int mid,int high)
{
int j=0;
for(i=low,k=mid+1;i<=mid&&k<=high;j++)
{
if(L.r[i]<=L.r[k])
{
T.r[j]=L.r[i];
i=i+1;
}
if(L.r[i]>L.r[k])
{
T.r[j]=L.r[k];
k=k+1;
}
}
while(i<=mid)
{
T.r[j++]=L.r[i++];
}
while(k<=high)
{
T.r[j++]=L.r[k++];
}
}
void MSort(SqList &L,SqList &t,int low,int high)//递归程序不太好想,就是先划分然后利用递归合并
{
if(low==high)//递归出口
{
t.r[low]=L.r[low];
}
else{
int m;
SqList S;//记得先给S分配空间
m=(low+high)/2;
MSort(L,S,low,m);//对左边进行划分
MSort(L,S,m+1,high);//对右边进行划分
Merge(S,T,low,m,high);//进行逆序合并,将S合并到T里面
}
}
写代码时先写两个有序表合成一个有序表的算法,最后再想递归。
时间复杂度:当有n个时,需要logn趟排序,每一趟关键字的比较不会超过n,移动次数都是n,所以时间复杂度为O(nlogn);
空间复杂度为:顺序表进行归并排序时,需要与待排序记录个数相等的辅助空间,为O(n)。
算法特点:稳定排序,可用于链式存储,不需要辅助空间,但递归时需要开辟相应的工作栈。
6.基数排序
基数排序是根据关键字中各位的值,通过对待排序记录进行若干趟“分配”与“收集”来实现排序的。
有最高位优先法和最低位优先法(先从最不重要的开始排)两种。
算法一般不需要掌握,了解过程即可。
时间复杂度为:O(d(n+rd))
空间复杂度为:O(n+rd)
算法特点:是稳定排序,可用于链式结构,也可用于顺序结构,时间复杂度可突破基于关键字比较一类方法的下界,达到O(n),基数排序使用条件有严格的要求:需要知道各级关键字的主次关系和各级关键字的取值范围。