数据结构 第十二章排序(快速排序 希尔排序)

快速排序

基础快速排序算法

思想:和归并排序类似,将序列分为两个子序列,彼此独立且其中一个子序列的所有元素都大于另一个序列,划分为子序列后分别排序再组合
归并排序的难点在于,快速排序的难点在于

轴点:左/右侧元素均不比它更大/小,相当于序列的中值,所以快速排序的重点是找到轴点即完成快速划分算法partition

构造轴点pivot:初始情况设置序列的首元素为轴点,设立lo和hi两个标点,lo之前的元素L不大于轴点pivot,hi之后的元素G不小于pivot,lo和hi之前的元素U大小不确定。每一步尝试将L或者G中的元素加入U,直到最后hi和lo重合即得到轴点pivot
在这里插入图片描述
流程:将U中的首尾标签[lo]空闲(视为空节点),尝试延长G:将候选pivot与hi比较,如果hi不小于pivot,则将hi归入G中,并继续比较hi[–];如果hi小于pivot,则将hi调换至空闲的lo位置并加入L中,并将原hi位置空闲,然后开始尝试延长L:将候选pivot与lo[–]开始比较…以此循环
在这里插入图片描述
实例:
在这里插入图片描述
Step1:刚开始L和G均为空,U即为整个序列,将序列的首元素[6]视为轴点pivot,并将[6]所在的位置置为空闲的lo,将数组末元素[7]视为hi
Step2:开始尝试延长G:比较轴点元素[6]和hi元素[7],hi元素[7]不小于轴点元素[6],所以将[7]加入G中
Step3:继续尝试延长G:比较hi–元素[1],[1]小于轴点元素[6],所以将[1]与空闲的lo元素调换并加入L中,将1原来的位置hi[–]空闲,并转而尝试延长L
Step4:开始尝试延长L:比较lo++元素[3]与轴点元素[6],[3]严格小于[6],所以将[3]加入L中并继续尝试延长L
Step5:继续尝试延长L:比较lo++元素[8]与轴点…以此循环

快速排序变种

查看U的首元素,如果不小于轴点,则直接令G向后拓展一个单位;如果小于轴点,则G向后滚动即交换U的首元素与G的首元素,L拓展一个单位
在这里插入图片描述

template<typename T>void Vector<T>::quickSort(Rank lo,Rank hi){
if(hi-lo<2)return;
Rank mi= patition(lo,hi-1);
quickSort(lo,mi);
quickSort(mi+1,hi);
}

template <typename T> Rank Vector<T>::partition(Rank lo,Rank hi){
swap(_elem[lo],_elem[lo+rand()%(hi-lo+1)]);//随机选择一个元素与首元素互换,降低出现最坏情况的概率
T pivot = _elem[lo];int mi=lo;
for(int k=lo+1;k<=hi;k++)//自左向右考察每个k
	if(_elem[k]<pivot)//如果[k]小于其轴点则,如果不小于的那个else分支中只需要k+1故可以省略
		swap(_elem[++mi],_elem[k]);//与[mi]交换
swap(_elem[lo],_elemp[mi]);//候选轴点归位到L与G中间
return mi;
}

实例
在这里插入图片描述

希尔排序

在这里插入图片描述
实例:
Step1:以宽度8将原序列划分为两行,然后在每一列上排序,再将这两行串联组合成新的一行**(只是逻辑上转化为两行,实际上只需要原数组一维就可以)**
在这里插入图片描述
Step2:以宽度5将原序列划分为两行,然后在每一列上排序,再将这两行串联组合成新的一行
在这里插入图片描述
Step3:以宽度3将原序列划分为两行,然后在每一列上排序,再将这两行串联组合成新的一行
在这里插入图片描述
Step4:以宽度2将原序列划分为两行,然后在每一列上排序,再将这两行串联组合成新的一行
Step1:对这行做插入排序
希尔排序的复杂度取决于希尔序列的大小,即每次划分的宽度

邮资问题

在这里插入图片描述
4元和13元的面值可以凑齐50,但无法凑齐35,怎么判断是否能凑成某个值称为邮资问题
在这里插入图片描述
对于面值为m和n的纸币,不能凑齐的最大数值为max(x)=m*n-m-n
定理:在希尔排序中,如果一开始序列是g-ordered(每隔g隔元素有序),经过h-ordered后g-ordered的有序性仍然保持
定理:如果一个序列有g-ordered和h-ordered,则序列也有(mg+nh)-ordered有序性
无序元素只有可能出现在[0,(mg+nh)]范围,希尔排序会不短降低[0,(mg+nh)]的范围

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值