3 选择排序
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,temp;
int lowindex,lowkey;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
/* 选择排序*/
for(i=1;i<20;i++)
{
lowindex=i-1;
lowkey=num[i-1];
for(j=i;j<20;j++)
{
if(num[j]<lowkey)
{
lowindex=j;
lowkey=num[j];
}
}
temp=num[i-1];
num[i-1]=lowkey;
num[lowindex]=temp;
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
} 1 冒泡排序
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
for(i=1;i<20;i++)//对数组进行19次处理,每次处理余下数组中最小的数,移到最前面
for(j=19;j>=i;j--)
{
if(num[j]<num[j-1])
{
temp=num[j-1];
num[j-1]=num[j];
num[j]=temp;
}
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
2 插入排序
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
for(i=1;i<20;i++)
{
j=i;
while(num[j]<num[j-1]&&j>0)
{
temp=num[j-1];
num[j-1]=num[j];
num[j]=temp;
j--;
}
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
for(i=1;i<20;i++)//对数组进行19次处理,每次处理余下数组中最小的数,移到最前面
for(j=19;j>=i;j--)
{
if(num[j]<num[j-1])
{
temp=num[j-1];
num[j-1]=num[j];
num[j]=temp;
}
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
2 插入排序
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
for(i=1;i<20;i++)
{
j=i;
while(num[j]<num[j-1]&&j>0)
{
temp=num[j-1];
num[j-1]=num[j];
num[j]=temp;
j--;
}
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
4 快速排序
#include <stdio.h>
#include <stdlib.h>
void quicksort(int a[],int left,int right);
int main(void)
{
int i,j,temp;
int lowindex,lowkey;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
/* 快速排序*/
quicksort(num,0,19);
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
//版本1
void quicksort(int a[],int left,int right)
{
int upper,low,keypoint;
low=left;
upper=right;
if(low>=upper)
return;
keypoint=a[low];
while(low<upper)
{
while(a[upper]>=keypoint&&low<upper) upper--;
if(low<upper)
a[low++]=a[upper];
while(a[low]<=keypoint&&low<upper) low++;
if(low<upper)
a[upper--]=a[low];
}
a[low]=keypoint;
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
//版本2
void quicksort(int a[],int left,int right)
{
int upper,low,keypoint,temp;
low=left;
upper=right;
if(low>=upper)
return;
keypoint=a[low];
while(low<upper)
{
while(a[upper]>=keypoint&&low<upper) upper--;
while(a[low]<=keypoint&&low<upper) low++;
temp=a[low];
a[low]=a[upper];
a[upper]=temp;
}
a[left]=a[low];
a[low]=keypoint;
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
#include <stdio.h>
#include <stdlib.h>
void quicksort(int a[],int left,int right);
int main(void)
{
int i,j,temp;
int lowindex,lowkey;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
/* 快速排序*/
quicksort(num,0,19);
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
//版本1
void quicksort(int a[],int left,int right)
{
int upper,low,keypoint;
low=left;
upper=right;
if(low>=upper)
return;
keypoint=a[low];
while(low<upper)
{
while(a[upper]>=keypoint&&low<upper) upper--;
if(low<upper)
a[low++]=a[upper];
while(a[low]<=keypoint&&low<upper) low++;
if(low<upper)
a[upper--]=a[low];
}
a[low]=keypoint;
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
//版本2
void quicksort(int a[],int left,int right)
{
int upper,low,keypoint,temp;
low=left;
upper=right;
if(low>=upper)
return;
keypoint=a[low];
while(low<upper)
{
while(a[upper]>=keypoint&&low<upper) upper--;
while(a[low]<=keypoint&&low<upper) low++;
temp=a[low];
a[low]=a[upper];
a[upper]=temp;
}
a[left]=a[low];
a[low]=keypoint;
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
5 堆排序
#include <stdio.h>
#include <stdlib.h>
void heapify(int a[],int i,int n)//修正堆中的第i索引号元素(第一个元素的索引从0开始)
{
int l,r,temp,largest;//l表示i元素的左结点,r表示i元素的右结点
l=2*i+1;
r=2*i+2;
if(l<n&&a[l]>a[i])
largest=l;
else
largest=i;
if(r<n&&a[r]>a[largest])
largest=r;
if(largest!=i)
{
temp=a[i];
a[i]=a[largest];
a[largest]=temp;
heapify(a,largest,n);//递归调整largest结点
}
}
void bulidheap(int a[],int n)//建堆
{
int i;
i=(n-2)/2;//因为元素的索引是从0开始的,所以对于n个元素的完全二叉树,(n-2)/2是第一个非叶子节点
for(;i>=0;i--)
heapify(a,i,n);
}
int main(void)
{
int i,j,n,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
n=20;//n表示待排序数组的个数
bulidheap(num,n);
while(n>1)
{
temp=num[0];
num[0]=num[n-1];
num[n-1]=temp;
n--;
heapify(num,0,n);
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void heapify(int a[],int i,int n)//修正堆中的第i索引号元素(第一个元素的索引从0开始)
{
int l,r,temp,largest;//l表示i元素的左结点,r表示i元素的右结点
l=2*i+1;
r=2*i+2;
if(l<n&&a[l]>a[i])
largest=l;
else
largest=i;
if(r<n&&a[r]>a[largest])
largest=r;
if(largest!=i)
{
temp=a[i];
a[i]=a[largest];
a[largest]=temp;
heapify(a,largest,n);//递归调整largest结点
}
}
void bulidheap(int a[],int n)//建堆
{
int i;
i=(n-2)/2;//因为元素的索引是从0开始的,所以对于n个元素的完全二叉树,(n-2)/2是第一个非叶子节点
for(;i>=0;i--)
heapify(a,i,n);
}
int main(void)
{
int i,j,n,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
n=20;//n表示待排序数组的个数
bulidheap(num,n);
while(n>1)
{
temp=num[0];
num[0]=num[n-1];
num[n-1]=temp;
n--;
heapify(num,0,n);
}
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
6 归并排序
#include <stdio.h>
#include <stdlib.h>
void merge(int a[],int p,int q,int r)//合并a[p,
,q]与a[q+1,
.,r]为a[p,
..,r]
{
int i,k;
int begin1,end1,begin2,end2;
int *temp=(int*)malloc(sizeof(int)*(r-p+1));//分配r-p+1大小的一块临时内存,用来存放合并后的数
begin1=p; end1=q;
begin2=q+1; end2=r;
k=0;
while((begin1<=end1)&&(begin2<=end2))
{
if(a[begin1]<=a[begin2])
{
temp[k]=a[begin1];
begin1++;
}
else
{
temp[k]=a[begin2];
begin2++;
}
k++;
}
while(begin1<=end1)
{
temp[k++]=a[begin1++];
}
while(begin2<=end2)
{
temp[k++]=a[begin2++];
}
for(i=0;i<(r-p+1);i++)
a[p+i]=temp[i];
free(temp);
}
void mergesort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=(p+r)/2;
mergesort(a,p,q);
mergesort(a,q+1,r);
merge(a,p,q,r);
}
}
int main(void)
{
int i,j,n,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
mergesort(num,0,19);
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void merge(int a[],int p,int q,int r)//合并a[p,





{
int i,k;
int begin1,end1,begin2,end2;
int *temp=(int*)malloc(sizeof(int)*(r-p+1));//分配r-p+1大小的一块临时内存,用来存放合并后的数
begin1=p; end1=q;
begin2=q+1; end2=r;
k=0;
while((begin1<=end1)&&(begin2<=end2))
{
if(a[begin1]<=a[begin2])
{
temp[k]=a[begin1];
begin1++;
}
else
{
temp[k]=a[begin2];
begin2++;
}
k++;
}
while(begin1<=end1)
{
temp[k++]=a[begin1++];
}
while(begin2<=end2)
{
temp[k++]=a[begin2++];
}
for(i=0;i<(r-p+1);i++)
a[p+i]=temp[i];
free(temp);
}
void mergesort(int a[],int p,int r)
{
int q;
if(p<r)
{
q=(p+r)/2;
mergesort(a,p,q);
mergesort(a,q+1,r);
merge(a,p,q,r);
}
}
int main(void)
{
int i,j,n,temp;
int num[20]={51,22,36,413,165,16,71,98,91,100,111,172,13,714,115,6,1,18,159,200};
mergesort(num,0,19);
for(i=0;i<20;i++)
printf("%d\n",num[i]);
fflush(stdin);//刷新缓冲区
char q;
scanf("%c",&q);
return 0;
}
7 基数排序
#include <stdio.h>
#include <stdlib.h>
//计数排序,npRadix为对应的关键字序列,nMax是关键字的范围。npData是具体要
//排的数据,nLen是数据的范围,这里必须注意npIndex和npData对应的下标要一致
//也就是说npIndex[1] 所对应的值为npData[1]
int RadixCountSort(int* npIndex, int nMax, int* npData, int nLen)
{
//这里就不用说了,计数的排序。不过这里为了是排序稳定
//在标准的方法上做了小修改。
int* pnCount = (int*)malloc(sizeof(int)* nMax); //保存计数的个数
for (int i = 0; i < nMax; ++i)
{
pnCount[i] = 0;
}
for (int i = 0; i < nLen; ++i) //初始化计数个数
{
++pnCount[npIndex[i]];
}
for (int i = 1; i < 10; ++i) //确定不大于该位置的个数。
{
pnCount[i] += pnCount[i - 1];
}
int * pnSort = (int*)malloc(sizeof(int) * nLen); //存放零时的排序结果。
//注意:这里i是从nLen-1到0的顺序排序的,是为了使排序稳定。
for (int i = nLen - 1; i >= 0; --i)
{
--pnCount[npIndex[i]];
pnSort[pnCount[npIndex[i]]] = npData[i];
}
for (int i = 0; i < nLen; ++i) //把排序结构输入到返回的数据中。
{
npData[i] = pnSort[i];
}
free(pnSort); //记得释放资源。
free(pnCount);
return 1;
}
//基数排序
int RadixSort(int* nPData, int nLen)
{
//申请存放基数的空间
int* nDataRadix = (int*)malloc(sizeof(int) * nLen);
int nRadixBase = 1; //初始化倍数基数为1
bool nIsOk = false; //设置完成排序为false
//循环,知道排序完成
while (!nIsOk)
{
nIsOk = true;
nRadixBase *= 10;
for (int i = 0; i < nLen; ++i)
{
nDataRadix[i] = nPData[i] % nRadixBase;
nDataRadix[i] /= nRadixBase / 10;
if (nDataRadix[i] > 0)
{
nIsOk = false;
}
}
if (nIsOk) //如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。
{
break;
}
RadixCountSort(nDataRadix, 10, nPData, nLen);
}
free(nDataRadix);
return 1;
}
int main()
{
//测试基数排序。
int nData[10] = {123,5264,9513,854,9639,1985,159,3654,8521,8888};
RadixSort(nData, 10);
for (int i = 0; i < 10; ++i)
{
printf("%d ", nData[i]);
}
printf("\n");
system("pause");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
//计数排序,npRadix为对应的关键字序列,nMax是关键字的范围。npData是具体要
//排的数据,nLen是数据的范围,这里必须注意npIndex和npData对应的下标要一致
//也就是说npIndex[1] 所对应的值为npData[1]
int RadixCountSort(int* npIndex, int nMax, int* npData, int nLen)
{
//这里就不用说了,计数的排序。不过这里为了是排序稳定
//在标准的方法上做了小修改。
int* pnCount = (int*)malloc(sizeof(int)* nMax); //保存计数的个数
for (int i = 0; i < nMax; ++i)
{
pnCount[i] = 0;
}
for (int i = 0; i < nLen; ++i) //初始化计数个数
{
++pnCount[npIndex[i]];
}
for (int i = 1; i < 10; ++i) //确定不大于该位置的个数。
{
pnCount[i] += pnCount[i - 1];
}
int * pnSort = (int*)malloc(sizeof(int) * nLen); //存放零时的排序结果。
//注意:这里i是从nLen-1到0的顺序排序的,是为了使排序稳定。
for (int i = nLen - 1; i >= 0; --i)
{
--pnCount[npIndex[i]];
pnSort[pnCount[npIndex[i]]] = npData[i];
}
for (int i = 0; i < nLen; ++i) //把排序结构输入到返回的数据中。
{
npData[i] = pnSort[i];
}
free(pnSort); //记得释放资源。
free(pnCount);
return 1;
}
//基数排序
int RadixSort(int* nPData, int nLen)
{
//申请存放基数的空间
int* nDataRadix = (int*)malloc(sizeof(int) * nLen);
int nRadixBase = 1; //初始化倍数基数为1
bool nIsOk = false; //设置完成排序为false
//循环,知道排序完成
while (!nIsOk)
{
nIsOk = true;
nRadixBase *= 10;
for (int i = 0; i < nLen; ++i)
{
nDataRadix[i] = nPData[i] % nRadixBase;
nDataRadix[i] /= nRadixBase / 10;
if (nDataRadix[i] > 0)
{
nIsOk = false;
}
}
if (nIsOk) //如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。
{
break;
}
RadixCountSort(nDataRadix, 10, nPData, nLen);
}
free(nDataRadix);
return 1;
}
int main()
{
//测试基数排序。
int nData[10] = {123,5264,9513,854,9639,1985,159,3654,8521,8888};
RadixSort(nData, 10);
for (int i = 0; i < 10; ++i)
{
printf("%d ", nData[i]);
}
printf("\n");
system("pause");
return 0;
}
8 桶排序
void BucketSon(R)
{ //对R[0..n-1]做桶排序,其中0≤R[i].key<1(0≤i<n)
for(i=0,i<n;i++) //分配过程.
将R[i]插入到桶B[「n(R[i].key)」]中; //可插入表头上
for(i=0;i<n;i++) //排序过程
当B[i]非空时用插人排序将B[i]中的记录排序;
for(i=0,i<n;i++) //收集过程
若B[i]非空,则将B[i]中的记录依次输出到R中;
}
void BucketSon(R)
{ //对R[0..n-1]做桶排序,其中0≤R[i].key<1(0≤i<n)
for(i=0,i<n;i++) //分配过程.
将R[i]插入到桶B[「n(R[i].key)」]中; //可插入表头上
for(i=0;i<n;i++) //排序过程
当B[i]非空时用插人排序将B[i]中的记录排序;
for(i=0,i<n;i++) //收集过程
若B[i]非空,则将B[i]中的记录依次输出到R中;
}
稳定性的好处:
排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。
(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
(2)选择排序
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法。
综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
不同条件下,排序方法的选择
(1)若n较小(如n≤50),可采用直接插入或直接选择排序。
当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。
(2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
若要求排序稳定,则可选用归并排序。但本章介绍的从单个记录起进行两两归并的 排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。
(1)若n较小(如n≤50),可采用直接插入或直接选择排序。
当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。
(2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
若要求排序稳定,则可选用归并排序。但本章介绍的从单个记录起进行两两归并的 排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。