8.2.3希尔排序
希尔排序:
一个叫希尔的人发明的排序所以叫希尔排序。是插入排序的优化,插入排序的时间复杂度主要来自于比较+移动的次数,假如开始是一个有序/基本有序的序列,则移动的次数会减少,则插入排序的时间复杂度会降低,所以希尔排序是先追求表中元素部分有序,再逐渐逼近全局有序的过程
把表里的元素拆分成一个个子表,每一趟处理中设置增量d,相距距离为d的元素会被看成是一个子表,把子表里的元素会进行直接插入排序
第一趟排序。设置d1=元素总数/2=8/2=4,相距距离为d1的元素都是子表元素,如1号位的49相距距离为4的元素是1+4=5号位的76-子表1,2号位38相距距离为4的元素是2+4=6号位13-子表2,3号位65相距距离为4的元素是3+4=7号位27-子表3,4号位97相距距离为4的元素是8号位49-子表4,对各个子表直接插入排序。49-76本来有序无需移动,38-13直接插入排序调换位置,65-27直接插入排序调换位置,97-49调换位置,最后再按照子表顺序上的元素放到数组中,形成第一趟排序后的序列
第2趟排序。缩小增量d的值,在第一趟d1基础上/2,设置d2=d1/2=4/2=2,相距距离为d2的元素都是子表元素 .如1号位的49相距距离为2的是1+2=3号位的元素27,3号位27相距距离为2的元素是3+2=5号位76,5号位76相距距离为2的元素是5+2=7号位65,1、3、5、7号位构成子表1(因为这几个相距距离相同放在一个子表上),2号位13相距距离为2的元素是2+2=4号位49,4号位49相距距离为2的元素是4+2=6号位38,6号位38相距距离为2的元素是6+2=8号位97,2、4、6、8号位构成子表2,对各个子表直接插入排序。最后再按照子表顺序上的元素放到数组中,形成第一趟排序后的序列
第3趟排序。缩小增量d的值,在第2趟d2基础上/2,设置d3=d2/2=2/2=1,相距距离为d2的元素都是子表元素 .则因为d是1,所以所有的元素都会在一个子表里,则就是对前2趟已经基本有序的序列进行直接排序,最终得到完整的排序序列
如下增量序列,每趟规定增量d的值如下:
第一趟,规定d=3,1、4、7号为子表1,对子表1进行插入排序得到27、49、97(注意各个位置不变,只是位置上的值发生更改),2,5,8号为子表2,对子表2进行插入排序。3,6为子表3,对子表3进行插入排序。
第2趟,规定d=1,则对所有元素进行直接插入排序,最终得到整体的序列。
考试中考法:每趟规定一个增量d,考每趟经过增量d得到的序列,听说代码考的不是太多
算法实现:
辅助变量d:当前趟中的增量
如下所示:
第一趟,第一层for循环d=n/2=8/2=4,第2层内层for循环开始i=d+1=5,很明显是1号位对应的d增量5号位,是因为在处理第一个子表时,按照插入排序只需判断第2个元素是否需要插入到前面,所以让i开始=d+1=5,则要判断A[i]和A[i-d]的大小关系看A[i]是否需要移动到A[i-d]位置,A[i]=A[5]=76>A[i-d]=A[i-5]=A[4]=49,则不需要移动,开始第2轮内层for循环++i,i=6,判断A[6]=13>A[6-d]即A[6-4]=A[2]=38,13>38则A[0]=A[i]=A[6]=13,即把当前要移到前边的元素放在A[0]最前边位置,第3层for循环检查当前这个元素的前边的元素j是否要比当前的处理更大,如果更大则要把j所指元素后移,不是移动到j+1而是移动到j+d当前元素的位置,j=i-d=6-4=2,A[2]>A[0]即38>13,则38移动到A[i]位置,即A[j+d]=A[j]=A[6]=38,j-=d=2-4=-2即判断当前跟j的2号位位置有没有相关的子表元素,有的话继续右移,j=-1<0不满足第3层for循环跳出A[j+d]=A[0]=A[-2+4]=A[0]=A[2]=A[0]=13即把13从A[0]移动到A[2]位置,开始下一轮第2层for循环++i,i=7,然后从前往后推7的子表元素7-4=3号位,7号位27<3号位65,则27要移到前边,让A[0]=27,第3层for循环看,j=3号位65>A[0]=27,让j移动到j+4位置,即65移到到开始这一趟i所在的7号位,第二轮3层for循环,j-=d为-1<0跳出for循环,A[-1+4]=A[3]=A[0]=27,让这一轮最开始那一趟的小元素移动到前边,开始下一轮第2层for循环++i,i=8,然后从前往后推8的子表元素8-4=4号位,8号位49<4号位97,则49要移到前边,让A[0]=49,第3层for循环看,j=4号位97>A[0]=49,让j移动到j+4位置,即97移到到开始这一趟i所在的8号位,第二轮3层for循环,j-=d为0>0不成立跳出for循环,A[0+4]=A[4]=A[0]=49,让这一轮最开始那一趟的小元素49移动到前边,开始下一轮第2层for循环++i,i=9,9<=n=8不成立,第一趟第一层for循环结束
第2趟,第2轮第一层for循环d=d/2=4/2=2,第2层for循环i=2+1=3,看这个第2趟的是否需要调整的第2个元素,然后从前往后推3的子表元素3-2=1号位,3和1号位在1个子表中,3号位27<1号位49,则27要移到前边,让A[0]=27,第3层for循环看,j=1号位(j一直开始都是i的前一个d增量的子表元素也就是第2层for循环和i做了判断大小的元素)49>A[0]=27,让j移动到j+2位置,即49移到到开始这一趟i所在的3号位,第二轮3层for循环,j-=d为1-2=-1<0跳出for循环,A[-1+2]=A[1]=A[0]=27,让这一轮最开始那一趟的小元素27移动到前边A[1]位置,1和3做了交换,开始下一轮第2层for循环++i,i=4,然后从前往后推4的子表元素4-2=2号位,4号位带下划线49>2号位13,if条件不满足无需处理,开始下一轮第2层for循环++i,i=5,然后从前往后推5的子表元素5-2=3号位,5号位76>3号位49,if条件不满足无需处理,开始下一轮第2层for循环++i,i=6,然后从前往后推7的子表元素6-2=4号位,6号位38<4号位49,则38要移到前边,让A[0]=38,第3层for循环看,j=4号位49>A[0]=38,让j移动到j+2位置,即49移到到开始这一趟i所在的6号位,第二轮3层for循环,j-=d为2号位13,13<38=A[0]不满足条件跳出第3层for循环,A[2+4]=A[6]=A[0]=38,让这一轮最开始那一趟的小元素38移动到前边,开始下一轮第2层for循环++i,i=7,然后从前往后推7的子表元素7-2=5号位,7号位65<5号位76,则65要移到前边,让A[0]=65,第3层for循环看,j=5号位76>A[0]=65,让j移动到j+2位置,即76移到到开始这一趟i所在的7号位,第二轮3层for循环,j-=d为3号位49,49<65=A[0]不满足条件跳出第3层for循环,A[3+2]=A[5]=A[0]=65,让这一轮最开始那一趟的小元素65移动到前边,开始下一轮第2层for循环++i,i=8,然后从前往后推8的子表元素8-2=6号位,8号位97<6号位49,if条件不满足无需处理,开始下一轮第2层for循环++i,i=9>n=8,第2趟第1层for循环结束
第3趟,第3轮第一层for循环d=d/2=2/2=1,第2层for循环i=1+1=2,看这个第2趟的是否需要调整的第2个元素,然后从前往后推2的子表元素2-1=1号位,2和1号位在1个子表中,2号位13<1号位27,则13要移到前边,让A[0]=13,第3层for循环看,j=1号位27>A[0]=13,让j移动到j+1位置,即27移到到开始这一趟i所在的1号位,第二轮3层for循环,j-=d为1-1=0<0跳出for循环,A[0+1]=A[1]=A[0]=13,让这一轮最开始那一趟的小元素13移动到前边A[1]位置,1和2做了交换,开始下一轮第2层for循环++i,i=3,然后从前往后推3的子表元素3-1=2号位,3号位49<2号位13不成立不成立,开始下一轮第2层for循环++i,i=4,然后从前往后推4的子表元素4-1=3号位,4号位38<3号位49则38要移到前边,让A[0]=38,第3层for循环看,j=3号位49>A[0]=38,让j移动到j+1位置,即38移到到开始这一趟i所在的4号位,第二轮3层for循环,j-=d为2号位27,27<38=A[0]不满足条件跳出第3层for循环,A[2+1]=A[3]=A[0]=38,让这一轮最开始那一趟的小元素38移动到前边,开始下一轮第2层for循环++i,i=5,然后从前往后推4的子表元素5-1=4号位,5号位65<4号位49不满足条件不处理,开始下一轮第2层for循环++i,i=6,然后从前往后推6的子表元素6-1=5号位,6号位带下划线49<5号位65则49要移到前边,让A[0]=49,第3层for循环看,j=5号位65>A[0]=49,让j移动到j+1位置,即65移到到开始这一趟i所在的6号位,第二轮3层for循环,j-=d为4号位38,38<49=A[0]不满足条件跳出第3层for循环,A[4+1]=A[5]=A[0]=49,让这一轮最开始那一趟的小元素49移动到前边。。。。。。。。。。。。。以上同,其实听不懂。。。。。。。。
算法性能分析:
空间复杂度:O(1)。因为只需要一些辅助变量,这些辅助变量只需要常数级的空间。
时间复杂度:
最坏情况下我直接d=1,此时希尔排序直接是直接插入排序,则时间复杂度为O(n²),当在某个范围时,时间复杂为O(n的1.3次方)
稳定性:不稳定。仅适用于顺序表,因为需要用顺序表的索引的随机访问来快速找到增量d的同属于同一个子表的元素,链表实现不了随机访问。
知识回顾:
听不懂。。。。。。。。。。。。。