排序目的-便于查找
内部排序:排序记录都在内存中
外部排序:排序记录一部分在内存,一部分在外存
排序算法的衡量-时间效率(排序速度-比较次数和移动次数)、空间效率(占内存辅助空间大小)、稳定性(A,B关键字相等,排序后,A,B的先后次序不变)
分类:
(规则不同)插入排序、交换排序、选择排序,归并排序
(时间复杂度不同)O(n^2) ,O(nlog2 n)
1.插入排序-边插入边排序
直接插入排序(基于顺序查找)-稳定
时间复杂度:O(n^2)
空间复杂度:O(1)
<span style="font-size:14px;">//直接插入排序
void InsertSort(SqList &L)
{
int i,j;
for(int i=2;i<j<L.length;i++)
{
if(L.r[i].key<L.r[i-1].key)
{
L.r[0]=L.r[i];
L.r[i]=L.r[i-1];
for(int j=i-2;L.r[0].key<L.r[j].key;--j)
{
L.r[i+1]=L.r[i];
}
L.r[i+1]=L.r[0];
}
}
}
</span>
折半插入排序(基于折半查找)-减少了比较次数,但未能减少移动次数-稳定
时间复杂度:O(n^2)
空间复杂度:O(1)
<span style="font-size:14px;">//折半插入排序
void BInsertSort(SqList &L)
{
for(int i=2;i<=L.length;i++)
{
L.r[0]=L.r[i];
low=1;
high=i-1;
while(low<=high)
{
m=(low+high)/2;
if(L.r[0].key<L.r[i].key)
high=m-1;
else
low=m+1;
}
for(j=i-1;j>=high+1;--j)
L.r[j+1]=L.r[j];
L.r[high+1]=L.r[0];
}
}
</span>
希尔排序(基于逐趟减小增量)-不稳定
时间复杂度:O(n^1.25)~O(1.6n^1.25)
空间复杂度:O(1)
如何选择最佳d序列,目前尚未解决
最后一个增量值必须为1,无除1以外的公因子
不宜在链式存储结构上实现
2.交换排序-两两比较,发生逆序则交换
冒泡排序--每趟两两比较,“前小后大”规则交换
时间复杂度:O(n^2)空间复杂度:O(1),稳定
以十个数排序为例,
for(i=1;i<=9;i++)
{
for(j=1;j<=10-i;j++)
{
if(a[i]>a[i+1])
{
t=a[i];
a[i]=a[i+1];
a[i+1]=t;
}
}
}
转载:具体实现参考
http://www.cnblogs.com/iuices/archive/2011/11/13/2247193.html
快速排序O(nlog2 n)
任取一个元素 (如第一个) 为中心
所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表;
对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个
时间复杂度O(nlog2 n)-每趟确定的元素呈指数增加;
空间复杂度O(log2 n)-递归要用到栈空间
不稳定-可选择任意元素为支点
转载:具体实现代码参考:
http://blog.csdn.net/liuchen1206/article/details/6954074
3.选择排序
每一趟在后面n-i+1中选出关键吗最小的对象,作为有序序列的第i个记录
时间复杂度O(n^2);空间复杂度:O(1),不稳定
4.堆排序
大根堆,小根堆
时间复杂度:O(log2 n)
空间复杂度:O(1)
不稳定,适用于n较大的情况
5.归并排序-稳定
时间复杂度:O(nlog2 n)
空间复杂度:O(n)
初始序列看成n个有序子序列,每个子序列长度为1
两两合并,得到n/2个长度为2或1的有序子序列
再两两合并,重复直至得到一个长度为n的有序序列为止
6.基数排序-不需要比较关键字