插入排序

插入排序

直接插入排序

直接插入排序是一个稳定的排序 算法时间复杂度$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
#include<iostream> 
#define MAXSIZE 100
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 排序完毕

End of reading! -- Thanks for your supporting