插入排序
基本思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到插入完成。
----直接插入排序
在有序子列里找到第i个的位置k,将L[k.....i-1]中元素向后移动一个位置
void InsertSort(ElemType A[],int n){
int i,j;
for(i=2;i<=n;i++){
if(A[i].key<A[i-1].key){
A[0]=A[i];
for(j=i-1;A[0].key<A[j].key;--j){
A[j+1]=A[j];
}
A[j+1]=A[0];
}
}
}
空间复杂度O(1);时间复杂度O(n^2);适合于顺序存储和链式存储的线性表。
------折半插入排序
先折半查找出元素的待插入位置,再统一移动插入
顺序存储的线性表的有序子表可以用折半查找来实现;比较次数与元素个数有关,时间复杂度O(n^2)
------希尔排序
将待排序表分成若干个子表,分别进行直接插入排序,再对全表进行一次直接插入排序。
void ShellSort(ElemType A[],int n){
for(dk=n/2;dk>=1;dk=dk/2)
for(i=dk+1;i<=n;++i){
if(A[i].key<A[i-dk].key){
A[0]=A[i];
for(j=i-dk;j>0&&A[0]<A[j];k-=dk){
A[j+dk]=A[j];
}
A[j+dk]=A[0];
}
}
}
时间复杂度O(n^2),不稳定;适用于顺序存储
交换排序
-----冒泡排序
基本思想:待排序表长n,从后往前两两比较相邻元素的值,若为逆序,交换。
void BubbleSort(ElemType A[],int n){
for(i=0;i<n-1;i++){
flag=false;
for(j=n-1;j>i;j--){
if(A[j-1].A[j]){
swap(A[j-1],A[j]);
flag=true;
}
}
if(flag==false)
return;
}
}
时间复杂:最好O(n),最坏O(n^2)
------快速排序
基本思想:基于分治法,任取一个元素作为基准pivot,通过一趟排序划分两边部分,一边小于pivot,一遍大于等于pivot。pivot放在最终位置,然后分别递归的对俩子表重复上述排序。
int partion(int data[],int low,int high)
{
int t=data[low];
while(low<high)
{
while(low<high&&data[high]>=t)
{
high--;
}
data[low]=data[high];
while(low<high&&data[low]<=t)
{
low++;
}
data[high]=data[low];
}
data[low]=t;
return low;
}
void quicksort(int data[],int low,int high)
{
int part;
if(low<high)
{
part=partion(data,low,high);
// printf("%d\n",part);
quicksort(data,low,part-1);
quicksort(data,part+1,high);
}
}
---------------------
作者:xulu_258
来源:CSDN
原文:https://blog.csdn.net/xulu_258/article/details/51319047
版权声明:本文为博主原创文章,转载请附上博文链接!
空间复杂度:最坏情况O(n^2)
不稳定算法
选择排序
基本思想:每一趟i在后面n-i+1个待排序元素中选取关键字最小的元素,作为有序子序的第i个元素,直到第n-1趟完成。
------简单选择排序
时间效率:n(n-1)/2次,O(n^2);不稳定
比较次数与初始状态无关
------堆排序
树形选择排序,特点:将L[n] 看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区选择最大(小)关键字;
小根堆:L(i)<=L(2i) 且L(i)<=L(2i+1)
大根堆:L(i)>=L(2i+1) (1<=i<=n/2);最大元素存放在根结点中
建堆时间:O(n) 时间复杂度:O(nlog2 n) 不稳定
归并排序和基数排序
--------归并排序
基本思想:归并的含义将两个或两个以上的有序表组合成一个新的有序表;调用n/2h次算法 ;整个归并需进行log2 n趟
空间复杂度:O(n) 时间复杂度O(nlog2 n);稳定排序;排序次数与初始状态无关
--------基数排序
基本思想:基于关键字各位的大小进行排序
性能:空间O(r) r个队列; 时间O(d(n+r)) 与初始状态无关;稳定
内部排序算法得比较及应用
------时空复杂度
平均情况下时间复杂度O(n^2):简单选择排序,直接插入排序,冒泡排序
空间复杂度:简单选择排序,插入排序冒泡排序,希尔排序,堆排序借助常数个辅助空间
快速排序使用小的辅助栈O(log2 n);二路归并O(n)
稳定:插入排序,冒泡排序,归并排序,基数排序
小结:
- 若n较小,可以采用直接插入或简单选择排序;直接插入排序的移动操作较多,记录信息本身量大时,用简单排序
- 若文件的初始状态已按关键字基本有序,选择直接插入或冒泡排序
- 若n较大,采用时间复杂度O(nlog2 n)快速排序,堆排序,递归排序;快速排序被认为目前内部排序中最好的方法;堆排序所需的辅助空间少于快速排序,这俩是不稳定排序;
- 若n很大,并记录的关键字位数较少且可分解采用基数排序
- 记录本身信息量较大,避免耗费大量时间移动记录,可用链表作为存储结构
外部排序
归并排序
归并趟数S=logm r(向上取整)
归并路数m个元素中关键字最小比较m-1次,每趟归并n个元素需要(n-1)*(m-1)
S趟归并比较总数:S(n-1)*(m-1)
----置换-选择算法
初始待排文件F1,初始归并段文件FO,内存工作区为WA,内存工作区可容纳W个记录;
步骤:
- 从待排文件F1输入W个记录到工作区WA
- 从内存工作区WA中选出关键字最小的记录MIN
- 将MIN记录输出到FO中
- 若F1未读完,则从F1输入下一个记录到WA
- 从WA中所有关键字比MIN大的记录中选出最小的,作为新的MIN
- 重复3-5