极客讲堂 - 数据结构与算法之美 - 排序,线性排序,排序优化,二分查找,跳表,散列表

11 | 排序(上)

1. 三种排序法比较

是否原地排序

是否稳定

最好

最坏

平均

冒泡排序

O(n)

O(n平方)

O(n平方)

插入排序

O(n)

O(n平方)

O(n平方)

选择排序

O(n平方)

O(n平方)

O(n平方)

冒泡排序:从数组的头部开始,相邻两个元素做大小比较和左右互换,找出最大或最小的数,放到数组尾部。

插入排序:从数组的第二个元素开始作为目标元素,往前找自己应该处在的位置,找到后,该位置到目标元素之前的元素后移,然后目标元素插入。 (注意不是从0位置开始找,是从目标元素往前找)

选择排序:从数组的头部开始,往后遍历,找出最大或最小的元素,放在数组头部。

2. 插入排序只需要一个赋值操作,但冒泡排序需要三个赋值操作。所以插入排序更优。

3. 可以学习下排序的代码实现 https://mp.weixin.qq.com/s/v-evJ_3s787mjW43c7xrHQ,自己写着练习下。

4. 小规模数据可以使用这三种排序法,大规模数据还是使用O(nlogn) 的排序算法比较好。

12 | 排序(下)

1. 大规模的数据排序,需要归并排序和快速排序算法,它们的时间复杂度为 O(nlogn)

2. 归并排序

2.1 归并排序采取的思路是分治递归

(1) 将数组不断二分,分成n/2 组数据,最终每组只有2个数据

(2) 分别对每组的2个数据排序。

(3) 逐层合并各组数据。合并的方法是,两组数据进行按顺序KOF(游戏拳皇)制,放入另一个数组。

2.2 归并排序的性能分析:

(1) 是稳定的

(2) 时间复杂度都是 O(nlogn)

(3) 空间复杂度是 O(n)

3. 快速排序

3.1 快速排序采取的思路也是分治递归

(1) 取第一个数作为pivot,把数组里比它小的放它左边,比它大的放它右边。那么数组就被分成三组,一组pivot自己,一组比它的,一组比它大的。

(2) 分别对另外两组再做一遍(1)的过程,完成后即排序完成。

3.2 快速排序的性能分析:

(1) 是不稳定的

(2) 时间复杂度都是 O(nlogn)

(3) 原地排序,空间复杂度是 O(1)

3.3 快速排序的代码实现方式(本人的描述):

(1) 取第一个数作为pivot,那么第一个数就视为一个空白格。

(2) 从右往左查找比pivot小的数 a,放入(1)中的空白格。a 之前所在的格视为新的空白格。

(3) 从左往右查找比pivot大的数 b,放入(2)里新的空白格处。b之前所在的格视为新的空白格。

(4) 重复(2)和(3),起始位置继承上一次操作的位置,直至左右指标相遇,视为结束一轮。

(5) 此pivot的左右两边视为两个小组,每个小组重复(2)至(4),直至结束。

4. 这两种排序的对比:

4.1 归并排序的处理过程是由下到上的,先处理子问题,然后再合并。

    快排正好相反,它的处理过程是由上到下的,先分区,然后再处理子问题。

4.2 归并排序稳定,快排不稳定。

4.3 归并排序需要占用内存,快排原地排序。

5. 原帖地址 数据结构与算法之美_算法实战_算法面试-极客时间

13 | 线性排序

1. 如果大规模的数据符合某些要求的话,可以有几种更高效率的排序方法,时间复杂度为O(n)。分别是桶排序、计数排序、基数排序。 (时间复杂度是线性O(n),所以叫线性排序)

极客时间版权所有: https://time.geekbang.org/column/article/42038

2. 桶排序:

2.1 桶排序思想

(1) 将数据的值划分成N段,每段一个桶。

(2) 遍历数组,根据每个数的值,分到对应的桶里。

(3) 对每个桶里的数,使用快速排序法,排好序。

(4) 把所有桶的数,按顺序依次合并起来。

2.2 桶排序对数据的要求:

(1) 数据需要很容易就能划分成 N段

(2) 数据在每个桶里大致能均匀分布(否则就退化为O(N*logN))

2.3 优化: 可以动态对每个桶再进一步细分。

3. 记数排序

3.1 记数排序思想

(1) 大致上和 上面桶排序一样,也是要数据划分,但每个桶的范围不是一段,而是一个具体的数值,而且是整数。

(2) 遍历数组,根据每个数的值,分到对应的桶里。由于数值都是一样的,所以每个桶只记录一个次数就可以了。

(3) 再从后遍历数组,每个数,根据(2)中记录的次数,倒推排序时应该处在的位置。遍历完成后排序就完成了。

(4) 具体细节查看原帖地址。

3.2 记数排序对数据的要求:

(1) 只能用在数据范围不大的场景中

(2) 只能是非负整数。小数的话可以乘以10。

4. 基数排序

4.1 基数排序思想

(1) 基数排序是记数排序的进化版,处理数据范围大,不方便两数直接比较(比如字符串比较)的场景。

(2) 如果数据很大,可以把数据划分"位",比如万、千、百位。

(3) 先对"万"位进行排序(使用记数排序),再"千"位排序。必须使用稳定的排序法。

(4) 排完个位后,就完成排序了。

4.2 基数排序对数据的要求:

(1) 需要可以分割出独立的“位”来比较

(2) 位之间有递进的关系,比如"万"位比"千"位大,有递进的逻辑关系。

14 | 排序优化:如何实现一个通用的、高性能的排序函数?

1.  线性排序算法适用场景比较特殊,不能用。

2. 小规模数据,选择时间复杂度是 O(n2) 的算法.

3.  大规模数据进行排序,选择时间复杂度是 O(nlogn) 的算法.

4.  所以,选择O(nlogn)的排序算法作为通用排序函数.

15 | 二分查找(上)

1. 二分查找,时间复杂度O(logn) ,速度惊人

2. 局限性

(1) 必须是顺序表结构(即数组)

(2) 必须是有序数组(先排好序)

(3) 插入和删除操作不能太频繁

(4) 不能过于庞大,因为需要占用连续内存

16 | 二分查找(下)

1. 凡是用二分查找能解决的,大部分更倾向于用散列表或者二叉树。

    但 “近似”查找的时候,用二分查找更适合。

2. 二分查找可以实现以下“近似”查找的需求:

(1) 查找第一个等于给定值的元素

(2) 查找最后一个等于给定值的元素

(3) 查找第一个大于等于给定值的元素

(4) 查找最后一个小于等于给定值的元素

17 | 跳表

1. 为对链表数据进行二分查找,可以使用跳表(Skip list)。

2. 跳表就是一个多级索引结构.

如上图所示,查询时,从第五级索引开始,往下查找。

3. 跳表的插入

(1) 不需严格按照每级索引2个数据的格式,可以直接插入成3个数据。

(2) 为避免某级索引数据过多使跳表退化成单向链表,可以使用 随机选择在第几级索引插入的方式。

4. 跳表的删除

(1) 必须要同时删除前驱结点。

(2) 使用双向链表(指向前驱结点),就比较方便

5. 跳表对比红黑树的优势

   按照区间查找数据(比如查找值在 [100, 356] 之间的数据),并输出有序序列。跳表更方便。

18 | 散列表(上)

1. 把标识号转化为数组下标的方法,就叫作散列函数。

2. 散列函数计算出来的值,叫散列值。

3. 散列函数设计的好坏决定了散列冲突的概率,也就决定散列表的性能。

4. 解决散列冲突的方法:

(1) 开放寻址法:  冲突的话就拿下一个来代替。

(2) 链表法:冲突时建立一个链接,根据链表做二次查找。

19 | 散列表(中)如何打造一个工业级水平的散列表?

1.  设计一个合适的散列函数:  不能太复杂,生成的值要尽可能随机并且均匀分布

2.  定义装载因子阈值,并且设计动态扩容策略。(负载因子:装载数据数目除以总容量)

(1) 内存空间不紧张,执行效率要求高,可以降低负载因子的阈值

(2) 内存空间紧张,执行效率要求不高,可以增加负载因子的值,甚至可以大于 1

(3) 为避免扩容操作时间长影响单次插入时间,可以将扩容操作分步进行。即:

     每插入一个新数据,就从旧表搬移一个数据到新表。查询时,先查新表再查旧表。

3.  选择合适的散列冲突解决方法

(1) 数据量比较小、装载因子小的时候,适合采用开放寻址法.

     数据放在连续数组中,能利用CPU缓存

(2) 数据量比较大、装载因子大的时候的散列表,适合采用链表法。

     这时采用开放寻址法的话,因为装载因子大,容易导致大量的散列冲突。

     链表法为解决优化散列冲突,可以采用红黑树。

20 | 散列表(下):为什么散列表和链表经常会一起使用? 

 答: 为了同时支持下面两个需求:

1. 高效的数据插入、删除、查找操作

2. 按照某种顺序快速地遍历数据(比如插入顺序)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值