排序算法分析(直插,折半,希尔)

一.排序分类
根据排序时数据所占用存储器的不同,可将排序分为两类。一类是整个排序过程完全在内存中进行,称为内部排序;另一类时由于待排序数据量太大,内存无法容纳全部数据,排序需要借助外部存储设备才能完成,成为外部排序。
二.插入类排序

插入排序的基本思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。

2.1直接插入排序
例:待排排序序列为{48,62,35,77,55,14,35 ,98}
完整的直接插入排序过程实现实例,大括号为当前已排好序的记录子集合
A) {48} 62 35 77 55 14 35 98
B) {48 62} 35 77 55 14 35 98
C) {35 48 62} 77 55 14 35 98
D) {35 48 62 77} 55 14 35 98
E) {35 48 55 62 77} 14 35 98
F) {14 35 35 48 55 62 77} 98
G) {14 35 35 48 55 62 77} 98
H) {14 35 35 48 55 62 77 98 }
假设待排序记录存放在r[1…length]中,为了提高效率设一个监视哨r[0],使得r[0]始终存放待插入的记录。监视哨的两个作用:①备份待插入的记录,方便前面关键字较大的记录后移;②防止越界
算法实现

void InsSort(RecordType r[],int length)//对记录数组r做直接插入排序,length为数组中待排序记录的数目

{
for(i=2;i<=length;i++)
{
r[0]=r[i];j=i-1;//将待插入记录存放到监视哨r[0]中
while(r[0].key<r[j].key)//寻找插入位置
{
r[j+1]=r[j];j=j-1;
}
r[j+1]=r[0];//将待插入记录插入到已排序的序列中
}
}

算法要点: ①设置监视哨r[0]临时保存待插入的记录②从后往前查找应插入的位置③查找与移动用同一循环完成
算法分析: ①时间复杂度O(n²)②最好情况O(n),n较小或元素基本有序③最坏情况O(n²)④空间复杂度O(1)⑤稳定 **while(r[0].key<r[j].key)**保证了相同的后面元素不会排到前面

2.2折半插入排序

对于有序表进行折半查找,性能优于顺序查找,可以将折半查找思想用于在有序记录 r[1…i-1] 中确定插入位置

算法实现:

void BinSort(RecordType r[],int length)
//对记录数组r进行折半插入排序,length为数组的长度
{
for(i=2;i<=length;i++)
{
x=r[i];
low=1;high=i-1;
while(low<=high)//确定插入位置
{
mid=(low+high)/2;
if(x.key<r[mid].key) 
high = mid-1;
else
low = mid+1;
}
for(j=i-1;j>=low;--j)  r[j+1]=r[j];//记录依次向后移动
r[low]=x; //插入记录
}
}

算法要点: 折半插入排序可以减少关键字的比较次数,每插入一个元素,需要比较的次数最大为折半判定树的深度
算法分析: ①时间复杂度为O(n²),比较时间复杂度为O(nlogn)②最好情况O(nlogn)③最坏情况O(n²)④空间复杂度O(1)

2.3希尔排序

希尔排序 又称缩小增量排序法,基于插入思想,拥有直接插入的最佳性质

例:待排序列为{46,55,13,42,94,17,05,70} 给出执行希尔排序算法执行的过程

算法实现:

void ShellInsert(RecordType r[],int length,int delta)
//对记录数组r做一趟希尔插入排序,length为数组的长度,delta为增量
{
for(i=1+delta;i<=length;i++)
//1+delta为第一个子序列的第二个元素的下标
if(r[i].key<r[i-delta].key)
{
r[0]=r[i];
for(j=i-delta;j>0 && r[0].key<r[j].key;j-=delta)
r[j+delta]=r[j];
r[j+delta]=r[0];
}
}

void ShellSort(RecordType r[],int length,int delta[],int n)
//对记录数组r做希尔排序,length为数组r的长度,delta为增量数组,n为delta[]的长度
{
for(i=0;i<=n-1;++i)
ShellInsert(r,Length,delta[i]);
}

算法要点: 当子序列的间隔为d时共有d个子序列,需对d个子序列分别进行插入排序,但是算法在具体实现时,不是先对一个子序列完成插排,再对另一个子序列插排,而是从第一个子序列的第二个记录开始,扫描整个待排序记录序列,当前记录属于哪一个子序列,就在哪一个子序列进行插排,所以算法会在每一个子序列中轮流进行插入排序

算法分析: ①时间复杂度O(n 1.5),空间复杂度O(1) ②不稳定 eg:{2 4 1 2 }

参考书籍:《数据结构》第二版————耿国华

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值