-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
106 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
""" | ||
最坏时间:O(n²) | ||
平均时间:O(nlgn) | ||
@任何一种常数比例的划分都会产生深度为Θ(lgn)的递归树,其中每一层的时间代价都是O(n),因此,只要划分是常数比例的,算法的运行时间都是O(nlgn) | ||
三步分治过程: | ||
分解:数组A[p..r]被划分为两个(可以空)子数组,A[p..q-1]和A[q+1..r],使得前一部分元素都不大于A[q],后一部分元素都不小于A[q],计算下标q也是划分过程的一部分 | ||
解决:通过递归调用快速排序,对数组A[p..q-1]和A[q+1..r]进行排序 | ||
合并:子数组都是原址的所以不需要合并操作,数组A[p..r]已经是有序 | ||
""" | ||
# 快速排序 | ||
quick_sort(A, p, r) # 排序数组A时p=1, r=len(A),这里假设数组下标从1开始 | ||
if p < r | ||
q = partition(A, p, r) | ||
quick_sort(A,p,q-1) | ||
quick_sort(A, q+1, r) | ||
|
||
|
||
# 数组的划分(快速排序的关键步骤),它实现了对数组A的原址重排 | ||
@将数组划分为四块(可以为空):A--不大于枢纽的地盘(部分),B--大于枢纽的地盘(部分),C--待(未)划分地盘(未知领域),D--枢纽的地盘 | ||
partition(A, p, r) | ||
x = A[r] # 把最后一个元素当枢纽 | ||
i = p-1 # 刚开始还未划分,所以只能给不大于枢纽部分一个空地盘(不存在的) | ||
for j=p to r-1 # <=i部分为不大于枢纽的地盘,i+1到j-1为大于枢纽的地盘,j为正在划分的地盘。r为枢纽的地盘 | ||
if A[j] <= x # 如果此值不大于枢纽,就把小于枢纽的部分增大单位1,于是i=i+1 | ||
i = i+1 # 就是说把之前的未知领域(为划分的部分)划分1给不大于枢纽部分 | ||
exchange A[i] with A[j] | ||
exchange A[i+1] with A[r] # 最后把枢纽放到中间地带(i+1处),把原枢纽的地盘分给大于枢纽的部分(互换)。 | ||
# 到这里地盘划分已完成,结果是:A为p到i,B为i+2到r,D为i+1(枢纽),C为空(都被瓜分了) | ||
return i+1 # 返回枢纽位置 | ||
|
||
|
||
# 数组的划分(数据结构书中) | ||
partition(A, low, high) | ||
p = low | ||
q = high | ||
x = A[low] | ||
while p < q | ||
while p < q and x <= A[q] | ||
q-- | ||
A[p] = A[q] # 把小的移到低位 | ||
whi p < q and x >= A[p] | ||
p++ | ||
A[q] = A[p] # 把大的移到高位 | ||
A[p] = x | ||
return p | ||
|
||
|
||
# 练习7.1-2:修改PARTITION,使得当数组A[p..r]中所有元素的值都相同时,q=int((p+r)/2). | ||
@解答博客地址:https://blog.csdn.net/z84616995z/article/details/18046845 | ||
partition(A, p, r) | ||
x = A[r] | ||
i = p-1 | ||
flag = 1 | ||
for j=p to r-1 | ||
if x >= A[j] and flag > 0 | ||
i = i+1 | ||
exchange A[i] with A[j] | ||
if A[i] == x | ||
flag = -flag # 这样使i++次数减半 | ||
exchange A[i+1] with A[r] | ||
return i+1 | ||
|
||
# 思考:上面的只能针对所以值相同时这类,所以用于其他的必然排序失败于是改为如下 | ||
partition(A, p, r) | ||
x = A[r] | ||
i = p-1 | ||
flag = 1 | ||
for j=p to r-1 | ||
if x > A[j] | ||
i = i+1 | ||
exchange A[i] with A[j] | ||
elif x == A[j] and flag % 2 == 0 | ||
i = i+1 | ||
exchange A[i] with A[j] | ||
else | ||
continue | ||
flag = flag+1 | ||
exchange A[i+1] with A[r] | ||
return i+1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# 采用随机抽样的随机化技术, | ||
# 与始终采用A[r]作为主元不同,随机抽烟是从子数组A[p..r]中随机选择一个元素作为主元 | ||
# 为达到此目的,首先将A[r]与从A[p..r]中随机抽选出的一个元素交换 | ||
# 通过对序列p..r的随机抽样,可以保证主元素x=A[r]是等概率地从子数组的r-p+1个元素中选取的 | ||
random_partition(A, q, r) | ||
i = random(q, r) | ||
exchange A[i] with A[r] | ||
return partition(A, q, r) | ||
|
||
random_quick_sort(A, p, r) | ||
if p < r | ||
q = random_partition(A, q, r) | ||
random_quick_sort(A, p, q-1) | ||
random_quick_sort(A, q+1, r) | ||
|
||
|
||
# 使用循环来代替quick_sort中的第二个递归:尾递归技术 | ||
tail_recursive_quick_sort(A, p, r) | ||
while p < r | ||
q = partition(A, p, r) | ||
tail_recursive_quick_sort(A, p, q-1) | ||
p = q+1 | ||
|
||
|
||
# 三数取中划分:一种改进的random_quick_sort的方法是在划分时,从子数组中更细致地选择作为主元的元素 | ||
# 常用做法是三数取中法:从数组中随机取出三个元素,取其中位数作为主元 |