数据结构与算法(五)

排序算法

1、直接插入排序

  • 对于一个带排序数组来说,其初始有序数组元素个数为1,然后从第二个元素,插入到有序数组中。
  • 对于每一次插入操作,从后往前遍历当前有序数组,如果当前元素大于要插入的元素,则后移一位;如果当前元素小于或等于要插入的元素,则将要插入的元素插入到当前元素的下一位中。

2、希尔排序

  • 先将整个待排序记录分割成若干子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,在对全体记录进行一次直接插入排序。
  • 其子序列的构成不是简单的逐段分割,而是将每隔某个增量的记录组成一个子序列。希尔排序时间复杂度与增量序列的选取有关,其最后一个值必须为1.

3、归并排序

  • 该算法采用分治法;对于包含m个元素的待排序序列,将其看成m个长度为1的子序列。
  • 然后两两合归并,得到n/2个长度为2或者1的有序子序列;然后再两两归并,直到得到1个长度为m的有序序列。(归并排序就是个⼆叉树的后序遍历)

4、冒泡排序

  • 对于包含n个元素的带排序数组,重复遍历数组,首先比较第一个和第二个元素,若为逆序,则交换元素位置;然后比较第二个和第三个元素,重复上述过程。
  • 每次遍历会把当前前n-i个元素中的最大的元素移到n-i位置。遍历n次,完成排序。

5、快速排序

  • 快速排序的核心思想是分治:选择数组中某个数作为基数,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数都比基数小,另外一部分的所有数都都比基数大,然后再按此方法对这两部分数据分别进行快速排序,循环递归,最终使整个数组变成有序。(快速排序就是个⼆叉树的前序遍历)
  • **实现:**双指针,一个找大于基数的,一个找小于基数的;找到后将两个数字进行交换。继续循环交换直到i>=j结束循环;最终指针i=j,此时交换基数和i(j)指向的数字即可将数组划分为小于基数/基数/大于基数的三部分,即完成一趟快排;
  • 快排算法是不稳定的排序算法。例如:待排序数组:int a[] ={1, 2, 2, 3, 4, 5, 6};若选择a[2](即数组中的第二个2)为枢轴,而把大于等于比较子的数均放置在大数数组中,则a[1](即数组中的第一个2)会到pivot的右边, 那么数组中的两个2非原序。若选择a[1]为比较子,而把小于等于比较子的数均放置在小数数组中,则数组中的两个2顺序也非原序。
  • 快排最差情况推倒。在快速排序的早期版本中呢,最左面或者是最右面的那个元素被选为枢轴,那最坏的情况就会在下面的情况下发生啦:1)数组已经是正序排过序的。 (每次最右边的那个元素被选为枢轴)2)数组已经是倒序排过序的。 (每次最左边的那个元素被选为枢轴)3)所有的元素都相同(1、2的特殊情况)。快速排序,在最坏情况退化为冒泡排序,需要比较O(n2)次(n(n - 1)/2次)。
  • 如何避免最差情况、因为这些案例在用例中十分常见,所以这个问题可以通过要么选择一个随机的枢轴,或者选择一个分区中间的下标作为枢轴,或者(特别是对于相比更长的分区)选择分区的第一个、中间、最后一个元素的中值作为枢轴。有了这些修改,那快排的最差的情况就不那么容易出现了,但是如果输入的数组最大(或者最小元素)被选为枢轴,那最坏的情况就又来了。

6、选择排序

  • 每次循环,选择当前无序数组中最小的那个元素,然后将其与无序数组的第一个元素交换位置,从而使有序数组元素加1,无序数组元素减1
  • 初始时无序数组为空。

7、堆排序

  • 堆排序是一种选择排序,利用堆这种数据结构来完成选择。其算法思想是将带排序数据构造一个最大堆(升序)/最小堆(降序),然后将堆顶元素与待排序数组的最后一个元素交换位置,此时末尾元素就是最大/最小的值。
  • 然后将剩余n-1个元素重新构造成最大堆/最小堆。

8、计数排序

  • 如果比元素x小的元素个数有n个,则排序后,元素x的位置为n+1。
  • 步骤:
    • 1)找出待排序的数组中最大的元素;
    • 2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
    • 3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
    • 4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。稳定性:稳定。时间复杂度:O(n+k),k是待排序数的范围。

9、桶排序

  • 步骤:
    • 1)设置一个定量的数组当作空桶子;
    • 2)寻访序列,并且把记录一个一个放到对应的桶子去;
    • 3)对每个不是空的桶子进行排序;
    • 4)从不是空的桶子里把项目再放回原来的序列中。时间复杂度:O(n+C) ,C为桶内排序时间。

时间复杂度

1、 定义

- 时间复杂度就是用来方便开发者估算出程序的运行时间
- 我们通常会估计**算法的操作单元数量**,来代表程序消耗的时间, 这里我们默认CPU的每个单元运行消耗的时间都是相同的。
- 假设算法的问题规模为n,那么操作单元数量便用函数f(n)来表示
-  随着数据规模n的增大,算法执行时间的增长率和f(n)的增长率相同,这称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n))
- 大O用来表示上界的

2、比较

在这里插入图片描述

什么是稳定性排序

  • 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;
  • 否则称为不稳定的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值