玩转算法与数据结构(一)

背景

学习算法,才能掌握编码的美,让自己始终保持良好的逻辑思维中。
课程地址:实战地址
我的码云地址:码云地址

开始

1.选择排序(O(n^2))

在整个数组中找到最小的元素,把它交换到第一个位置,遍历剩下的数组,再找到剩下数组中最小的元素,交换到后一位,即从 i 的位置开始遍历数组,选取其中最小的元素放在跟 i 位置的元素交换。

2.插入排序(O(n^2))

默认第一个元素有序,从第二个元素开始对前面数组排序,每次跟前面的元素比较,如果比前面的小,则与前面交换,继续向前比较,直到比前面大或遍历到第一个元素时才停止。每次往后偏移一位与前面的元素比较。

优化:

  • .先把待排序元素提取出来,跟前面元素比较,如果需要交换,直接前面元素后移,直到找到比前面大或第一个元素,直接将该位置赋值为待排序元素。

特点:
在近乎有序的数组中,插入排序的时间复杂度近乎O(n)

3.归并排序(O(nlogn))

首先将数组分成一半,在对左右两边数组分半,直到剩下一个元素,此时每一个部分都是有序的,此时往上合并,并进行排序,直到完全合并。需要用到辅助空间来对数组进行归并,比较两个数组,依次将当前数组比较最小的放到辅助空间中。

优化:

  • 当前半部分数组的最后一个元素小于后半数组的第一个元素,此时不需要进行合并操作。
  • 当递归到某一个层级时,可以选择使用插入排序对数组进行排序。

递归实现的是自顶向下的归并排序,我们可以用迭代实现自底向上的归并排序

4.快速排序(O(nlogn))

选定一个基准,将小于基准的放左边,大于基准的放右边,此时基准已经处于正确的位置上。此时在对基准左右两边的数组分别重新选取基准对其进行快速排序,直到最后一个元素。

优化:

  • 当递归到某一个层级时,可以选择使用插入排序对数组进行排序。
  • 随机选择基准,避免在几乎有序的数组中导致左右分区畸形
  • 双指针交换遇到左边大于基准,右边小于基准的数,直到两者交叉或相等,然后交换基准位置(优化具有大量重复键值的数组)
  • 三路快速排序,将数组分为三部分:小于基准,等于基准,大于基准(如果有大量重复键值的数组,那么排序性能将远比其他的排序算法好)

思路:–>随机数组–>近乎有序数组–>大量重复键值数组
还有其他的优化方法,但是思路很重要。

5.堆排序

适用于优先队列,出队顺序和入队顺序无关,与优先级有关。用数组存储二叉堆。

如果第一个元素位置为1,则:parent(i)= i / 2;left child (i) = 2 * i,right child (i) = 2 * i + 1。

如果第一个元素位置为0,则:parent(i)= ( i - 1 ) / 2;left child (i) = 2 * i + 1,right child (i) = 2 * i + 2。

入队:把新元素放在树最后的位置,然后进行shiftUp操作,比较将最大的数交换到父结点。

出队:把第一个元素出队,并把树最后一个元素放到第一个位置,然后进行shiftDown操作,左右孩子比较并把大的和自己比较,将大的交换到父结点。如果自己大,则结束操作。

优化:

  • 先把整个数组赋值到堆中,并且对每个非叶子结点进行shiftDown操作,此时可形成最大堆,第一个非叶子结点的位置为 树的结点数除以2。(注意这是第一个元素在1位置的情况)
  • 原地堆排序,对n个元素对第一个元素进行shiftDown操作,此时最大值已经在第一个位置,此时将第一个元素跟最后一个元素交换,然后对n-1个元素对第一个元素进行shiftDown操作,依次类推。

扩展:索引最大堆(实现)。

  • 多路归并排序
  • 优先队列:二项堆,斐波那契堆,Pairing 堆
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值