插入排序
直接插入排序
直接插入排序是一个稳定的排序 算法时间复杂度$O(n^2)$
适用于顺序存储和链式存储
前提环境条件
在顺序表中对表内元素进行直接插入排序
对线性表·1描述的顺序表做了几处修改
顺序表创建从L.data[1]
开始存储元素 L.data[0]
不存储元素
顺序表遍历从L.data[1]
到L.data[n]
n为L.length
表长
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
using namespace std; typedef int ElemType;//排序必须是数字 typedef struct{ ElemType *data; int length; }SqList; bool Initlist_Sq(SqList &L){//初始化顺序表L L.data = new ElemType[MAXSIZE]; L.length = 0; return 1; } bool ListInsert_Sq(SqList &L,int i,ElemType e){//插入表L if((i<1)||(i>L.length+1)) return 0; if(L.length==MAXSIZE) return 0; for(int j=L.length;j>=i;j--){ L.data[j] = L.data[j-1]; } L.data[i] = e;//从L.data[1]开始存储元素 L.length++; return 1; } int GetLength(SqList L){//求表长 return (L.length); } int ShowList(SqList L){//遍历整个线性表的元素并输出 for(int i=1;i<=L.length;i++){ cout<<L.data[i]<<" "; } cout<<endl; }
|
直接插入排序代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool InsertSort(SqList &L,int n){//n为表长 int i,j; for(i=2;i<=n;i++){ if(L.data[i]<L.data[i-1]){//第i个元素小于它前驱的元素 L.data[0]=L.data[i];//哨兵暂存i元素 for(j=i-1;L.data[0]<L.data[j];j--)//从后向前查找待插入的位置 L.data[j+1]=L.data[j];//将比L.data[0]大的元素都向后移位 L.data[j+1]=L.data[0]; //复制到插入位置 //L.data[0]比L.data[j]大 跳出循环 在L.data[j+1]插入L.data[0] } } return 1; }
|
折半插入算法
针对顺序存储的线性表 可以使用折半查找来确定待插入位置
折半插入排序是一种稳定的排序方法
折半插入排序相较于直接插入排序减少了比较元素的次数 约为$O(nlog_{2}n)$
比较元素次数取决于表中元素个数n
元素移动次数未改变 因此时间复杂度仍为$O(n^2)$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| bool InsertSort(SqList &L,int n){//从小到大的递增顺序排序 int i,j,low,high,mid; for(i=2;i<=n;i++){ L.data[0]=L.data[i];//L.data[0]暂存i位置的元素 low=1;high=i-1;//设置折半查找的范围 while(low<=high){ mid=(low+high)/2; if(L.data[mid]>L.data[0]) high=mid-1;//查找左半区 else low=mid+1;//查找右半区 } for(j=i-1;j>=high+1;j--) L.data[j+1]=L.data[j];//后移元素 空出插入位置 L.data[high+1]=L.data[0]; } return 1; }
|
希尔排序
希尔排序又称为缩小增量排序 只适用于顺序存储的线性表
设置一个增量 增量为区间长度 一般选择表长的一半 一直减半到1
在这个增量下的所有元素进行排序 然后缩小增量 再对这个增量下的所有元素进行排序 直到增量为1 进行最后的排序
n在某个特定范围时 希尔排序的时间复杂度为$O(n^{1.3})$
最坏情况下 希尔排序的时间复杂度为$O(n^2)$
希尔排序可能会改变元素的相对次序 因此是一种不稳定的排序方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| bool ShellSort(SqList &L,int n){//希尔排序 int i,j,dk; for(dk=n/2;dk>=1;dk=dk/2){//dk为区间大小 初值为表长的一半 dk可以自己设置 for(i=dk+1;i<=n;i++){ if(L.data[i]<L.data[i-dk]){ L.data[0]=L.data[i]; for(j=i-dk;j>0&&L.data[0]<L.data[j];j-=dk)//同一区间大小下的一组元素完全排序 L.data[j+dk]=L.data[j]; L.data[j+dk]=L.data[0]; } } for(int k=1;k<=L.length;k++){//一次dk排序后遍历表 观察元素排序变化 cout<<L.data[k]<<" "; } cout<<endl; } return 1; }
|
For instance:
L表内元素为 96 36 -9 0 47 23 1 8 10 7
表长n为10 增量dk为5
第一次排序 L[1]与L[6]比较排序 L[2]与L[7]比较排序 L[3]与L[8]比较排序 L[4]与L[9]比较排序 L[5]与L[10]比较排序
L表内元素为 23 1 -9 0 7 98 36 8 10 47
增量dk为5/2=2
第二次排序 L[1] L[3] L[5] L[7] L[9]比较排序 L[2] L[4] L[6] L[8] L[10]比较排序
L表内元素为 -9 0 7 1 10 8 23 47 36 98
增量dk为2/2=1
第三次排序 十个元素同时比较排序
L表内元素为 -9 0 1 7 8 10 23 36 47 98
排序完毕