直接插入排序
流程:若待处理序列为【9,8,7,6,5,4,3,2,1】,则:
- 设置哨兵:将序列放入大小为10的数组A中,其中A[0]作为哨兵,A[1]=9,A[2]=8依次类推
- 是否移动:A[1]不动,从A[2]开始处理,然后前者比较,若小于前者说明需要移动,将待处理数x存入哨兵
- 移动:从后往前,依次将x之前的元素向后移动,直至碰到小于x的元素为止,再将x从哨兵中取出,放入指定位置
运行结果:
知识点:
- 空间复杂度为o(1),因为只使用了哨兵这个辅助空间
- 总移动次数=将x放入哨兵(1) + 元素后移(i=2/3/4/...n,最多移动1次/2次/3次/...n-1次)+从哨兵取出(1次) =
- 比较总次数=
,因为每个2号元素会跟1号比一次,再跟哨兵比一次然后跳出循环,依次类推
二分查找
流程:若待处理序列为【1,2,3,4,5,6,7,8,9】,待查找数为x,则:
- 将序列放入大小为9的数组A中,A[0]=1,A[1]=2依次类推
- 设low指针指向A[0],high指针指向A[8]
- 当low<high时,mid=(low+high)/2,若A[mid]=x,命中,返回x所在位置为mid;若A[mid]>x,high=mid-1;若A[mid]<x,low=mid+1;直至low>high
运行结果:
知识点:
二分插入排序
流程:若待处理序列为【9,8,7,6,5,4,3,2,1】,则:
- 哨兵,将序列存入大小为10的数组中,A[0]用作哨兵(存储被操作数),A[1]=9,A[2]=8...依次类推
- 从A[2]开始操作,将A[2]存入A[0],设置low=1,high=操作数下标-1,适用二分查找查找操作数应该存放的位置
- 将待操作数之前,哨兵之后的数挨个后移,从哨兵取出待操作数存入指定位置
运行结果:
知识点:
- 由于折半查找只适用于线性表,所以折半插入排序也只适用于线性表
- 查找的平均效率是o(log2n),高于直接插入排序的o(n2),后移的平均效率是不变,依然是o(n2),所以折半插入排序的平均时间复杂度是o(n2)
- 折半插入排序的空间复杂度为o(1)
- 折半插入排序是稳定的插入排序
希尔排序
流程:若待处理序列为【9,8,7,6,5,4,3,2,1】,则:
- 设置哨兵,将序列存入大小为10的数组中,A[0]用作哨兵(存储被操作数),A[1]=9,A[2]=8...依次类推
- 设置步长,初始步长为数组长度的一半,间隔相同步长的元素成为1组,上图步长为5,所以1-5为一组,2-7为一组,如果步长为4,则1-3-8为一组,2-5-6为一组
- 分别为每一组进行插入排序,和直接插入排序不同,后者是后移1位,前者是后移一个步长
- 令步长减半,如此往复直到步长为1,即最后一次步长为1,此时整个数组都在一个分组中,相当于直接插入排序
运行结果:
知识点:
- 空间复杂度为o(1),因为使用了哨兵为辅助单元
- 平均时间复杂度o(n1.3),最坏为o(n2)
- 由于需要使用随机存取的特性,所以仅适用于线性表
- 是不稳定的排序