经典的三种排序方法

  • 经典的三种排序算法

  • 归并排序:
归并排序。可以说分治策略用在了排序问题上。
我们每次将数组分成两半。递归的排序这两半。然后用线性时间将其合并起来。变成一个完整的有序数组。
复杂度分析:T(n)=2T(n2)+O(n)

显然最多展开log2n层。所以总时间复杂度:O(nlogn)

  • 堆排序:
如果不知道堆这个数据结构的同学。可以自行学习。(百度一大把)
通过不停到调整堆来做到排序。
每次将堆顶最小元素与堆最中后一个元素交换。类似于把最后一个元素从新入堆。
这一步从新调整耗费O(log2n)
排序n个元素复杂度:O(nlogn)

  • 快速排序
正如其名。快速排序。当然是非常快的。
也是最重要。最需要学习的排序。
快速排序为何如此之快?

快速排序与归并排序类似。

不同的是:快速排序是先划分。不需要合并。归并排序最慢的部分。

就是需要把数组归并到一个辅助数组中。在把排序到辅助数组中的元素从新拷贝到原来数组对应位置。

快速排序不同:

最经典的快速排序是随机的选择一个数列中的元素a
然后将这n个元素的序列划分为:[不大于a的部分]-- a-- [不小于a的部分]


具体实现技巧在于:

我们随机的选择a=A[i].

将A[i] 与 A[0]交换位置。
令t=0,k=n−1
我们认为:A[0..t−1]所有元素小于等于a
我们认为:A[k+1..n−1]所有元素大于等于a
开始时, a在 A[t] 位置。
循环:检查A[k]是否小于A[t]。
如果不是k=k−1,继续检查。直到k等于t.此时划分完成。
如果是 : 将A[k]归入小于等于a的集合。即:交换A[t],A[k]。
检查A[k]是否小于A[t]
如果不是, t=t+1.直到k等于t,划分结束。
如果是。交换A[k],A[t],返回循环的位置。
通过这样的划分。我们将序列划分成了不大于a的部分和不小于a的部分。
记a现在的位置为mid.显然。a的位置不需要改变了。
我们只需要递归的排序:
sort(0,mid−1)和sort(mid+1,n−1)
快速排序的效率难免有些许不稳定。因为它的速度与它的划分是否得当有关。
但实践表明。总是出现坏的情况的划分是几乎不可能能的。快速排序的速度要比归并排序和堆排序都要快。
我们计算一下平均意义下的快速排序的效率:
T(n)=1n∑k=1n(T(n−k)+T(k−1))+cn=2n∑k=0n−1T(k)+cn
cn是划分n个元素时需要的时间。且a不需要排序。所以T(k−1)+T(n−k)
所以:
nT(n)=2∑k=0n−1T(n)+cn2
则n−1时:
(n−1)T(n−1)=2∑k=1n−2T(k)+c(n−1)2
两式子做差有:
nT(n)−(n−1)T(n−1)=2T(n−1)+2cn−1nT(n)=(n+1)T(n)+2cn−1
哇,两边除去n(n+1):
T(n)n+1=T(n−1)n+2cn+1−1n(n+1)
令:S(n)=T(n)n+1 , n>1
所以:S(n)=S(n−1)+2cn+1−1n(n+1)
所以:S(n)=∑k=1n2ck+1−∑k=1n1k(k+1)
啊哈。有经验的人必然会发现: 1k(k+1)=1k−1k+1
所以:S(n)=∑k=1n2ck+1−∑k=1n1k+∑k=1n1k+1=2c∑k=2n+11k−nn+1
也就是说: T(n)n+1=2c∑k=2n+11k−nn+1T(n)=2c(n+1)∑k=2n1k+1−n
即:T(n)=2cnHn+Hn−(2c+1)n−2c+1
其中Hn=11+12+13+...+1n
则Hn≤O(∫n01x dx)=O(logen)
所以:T(n)=O(nlogn)
因为排序思想都比较简单。所以也就不再给出关于这三种排序的代码实现了.
在很多复杂度分析和算法思想中都可以找到这三种算法的影子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值