数据结构与算法----第四次分享(20181109)

今天我们学习小组进行了数据结构与算法的第四次分享讨论,主要内容是几类排序算法,包括:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。
其中,冒泡排序、插入排序、选择排序:时间复杂度O(n^2),适合小规模数据;归并排序、快速排序:时间复杂度O(nlogn),大规模数据的排序。
如何分析一个排序算法的好坏,主要考虑一下几个因素:
a.排序算法的执行效率

  1. 最好情况、最坏情况、平均情况时间复杂度
  2. 时间复杂度的系数、常数 、低阶
  3. 比较次数和交换(或移动)次数

b.排序算法的内存消耗
原地排序(Sorted in place)。原地排序算法,就是特指空间复杂度是 O(1) 的排序算法(冒泡,插入,选择)

c.排序算法的稳定性
稳定性。这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。
关于排序,提到几个概念,有序度,逆序度,满有序度,其中,有序度+逆序度=满有序度。
我们排序的过程就是一种增加有序度,减少逆序度的过程,最终达到满有序度,就说明排序完成。

概念:
1.冒泡排序:
冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换,一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
2.插入排序:
即动态地往有序集合中添加数据,我们可以通过这种方法保持集合中的数组一直有序
是原地排序,稳定的排序,最好时间复杂度O(n)
3.选择排序
也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中选择最小的元素放在已排序区间的末尾
选择排序空间复杂度为 O(1),是一种原地排序算法。选择排序的最好情况时间复杂度,最坏时间复杂度,平均时间复杂度都为O(n^2),
但是选择排序不是稳定的排序算法
选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性

4.归并排序:(不是原地排序算法)
如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后2部分分别排序,再将排序好的2部分合并到一起,这样整个数组就都有序了
归并排序用的是分治的思想,以递归代码来实现
// 递归调用函数
merge_sort_c(A, p, r) {
// 递归终止条件
if p >= r then return

// 取 p 到 r 之间的中间位置 q
q = (p+r) / 2
// 分治递归
merge_sort_c(A, p, q)
merge_sort_c(A, q+1, r)
// 将 A[p…q] 和 A[q+1…r] 合并为 A[p…r]
merge(A[p…r], A[p…q], A[q+1…r])
}
5.快速排序:
快排的思想是这样的:如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为 pivot(分区点)。
我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。经过这一步骤之后,数组 p 到 r之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于 pivot 的,中间是 pivot,后面的 q+1 到是大于 pivot 的。
根据分治、递归的处理思想,我们可以用递归排序下标从 p 到 q-1 之间的数据和下标从 q+1 到 r 之间的数据,
直到区间缩小为 1,就说明所有的数据都有序了

可以发现,归并排序的处理过程是由下到上的,先处理子问题,然后再合并。而快排正好相反,它的处理过程是由上到下的,先分区,然后再处理子问题。归并排序虽然是稳定的、时间复杂度为 O(nlogn) 的排序算法,但是它是非原地排序算法。我们前讲过,归并之所以是非原地排序算法,主要原因是合并函数无法在原地执行。快速排序通过设计巧妙的原地分区函数,可以实现原地排序,解决了归并排序占用太多内存的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值