• 关于排序


    为所有算法提供了保证稳定的解决方案

    迭代与递归转换

    数组与链表

    排序的性质

    在位:使用的额外内存,是否分配了新数组

    稳定:相同元素不改变原有相对位置。可以把原下标作为第二关键字,先按key(第一关键字),再按index(第二关键字)排序,最终结果稳定(但是存在相同元素错位的中间过程)

    从算法结果判断算法是否为稳定:与稳定排序算法的排序结果与数组比较,也需要额外标记,不如直接遍历一次,检查相同元素的第二关键字是否有序。

    输入数据的特征对算法的影响

    插入排序

    分解一次插入动作:

    A[i]=temp

    1.在左方已排序数组(0,i-1)中搜索刚好大于A[i]的元素A[k]

    2.向右移动数组(k,i-1)

    3.插入元素A[k-1]=temp

    优化:用二分搜索替代遍历搜索,但是会影响最优情况(已排序数组)的复杂度

    很多算法会把搜索与移动元素的动作耦合在一起,

    从后向前遍历搜索,这样对数组成员只需要访问一次,但是不能用二分加快搜索

    从后向前遍历搜索也保证了算法稳定

    优点:自适应已排序的情况,便利一次结束算法

    在位:不需要额外数组

    稳定:保证插入位置——插入元素的右方元素大于它(如果等于,则不稳定)

    插排:考察元素间的相对次序,而不试图找到绝对位置

    选择排序

    1.选择剩余未排序数组中的最大/最小统计量

    2.交换(不稳定)

    另一种思路(保持稳定性)

    2.移动数组

    3.插入

    冒泡排序

    与选择算法原理思路2是一致的,每次找到的是第k统计量

    冒泡动作其实是移动数组动作的分解

    算法提前结束标志:一次遍历没发生交换动作

    归并排序

    递归,最终从小数组到大数组依次合并

    稳定:对于相同元素,定义左边数组的元素优先级高

    在位:合并动作需要额外的数组

    子问题:合并数组

    优化:不需要两个数组都复制,复制左边的就可以了。如果进一步优化空间,可以分配两者短长者的数组长度,但会造成移动数组的开销

    所以空间复杂度为n

    快速排序

    子问题:分割(可用于找到前k统计量(无序))

    分割交换:

    方案1:交换(选排中也出现):不稳定

    方案2:移动数组:稳定

    避免移动数组造成的复杂度:使用额外数组,保留大于划分的数,划分结束时赋值回原数组

    空间复杂度nlogn

    如果维护后段数组的偏移量,并在算法结束时计算绝对位置,每个数最多一次赋值回原数组

    一次迭代完成,左部分偏移量+0,右部分偏移量+1

    随迭代进行偏移量增加

    绝对位置=相对位置+总偏移量

    计数排序

    B[value]=num

    其他优化:快排中小数组利用插排减少函数调用开销,合并排序亦可做此优化。

    基于比较的算法复杂度下界为nlogn

    构造一个算法,数组从1个元素开始

    每加入一个元素,在数组中二分查找插入位置

    则最后一个元素插入的比较次数为logn-1

    比较次数之和all(logn)

  • 相关阅读:
    家庭问题(family)
    BFS简单题记
    【例2-3】围圈报数
    【例8.3】最少步数
    【例3-5】扩展二叉树
    股票买卖
    小球(drop)
    用循环单链表实现约瑟夫环
    二叉树的3种遍历6种实现
    const与#define宏常量 , inline与#define
  • 原文地址:https://www.cnblogs.com/qmcj/p/9140844.html
Copyright © 2020-2023  润新知