QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3410|回复: 0
打印 上一主题 下一主题

选择排序

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-4 05:17 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<>对于给定的n 个元素的数组a [ 0 : n - 1 ],要求从中找出第k小的元素。当a [ 0 : n - 1 ]被排序时,该元素就是a [ k - 1 ]。假设n = 8,每个元素有两个域k e y和I D,其中k e y是一个整数,I D是一个字符。假设这8个元素为[ ( 1 2 ,a),( 4 ,b),( 5 ,c),( 4 ,d),( 5 ,e),( 1 0 ,f),( 2 ,g),( 2 0 ,h)], 排序后得到数组[ ( 2 ,g),( 4 ,d),( 4 ,b),( 5 ,c),( 5 ,e),( 1 0 ,f),( 1 2 ,a),( 2 0 ,h) ]。如果k = 1,返回I D为g 的元素;如果k = 8,返回I D为h 的元素;如果k = 6,返回是I D为f 的元素;如果k = 2,返回I D为d 的元素。实际上,对最后一种情况,所得到的结果可能不唯一,因为排序过程中既可能将I D为d 的元素排在a [ 1 ],也可能将I D为b 的元素排在a [ 1 ],原因是它们具有相同大小的k e y,因而两个元素中的任何一个都有可能被返回。但是无论如何,如果一个元素在k = 2时被返回,另一个就必须在k = 3时被返回。
7 l2 u2 s' y; P. w' E( A+ s& T) p! h3 H4 W1 H
选择问题的一个应用就是寻找中值元素,此时k = [n / 2 ]。中值是一个很有用的统计量,例如中间工资,中间年龄,中间重量。其他k值也是有用的。例如,通过寻找第n / 4 , n / 2和3 n / 4这三个元素,可将人口划分为4份。% \; o% ?3 c+ A# h

; k' Q% v7 @, a/ A& G选择问题可在O ( n l o g n )时间内解决,方法是首先对这n个元素进行排序(如使用堆排序式或归并排序),然后取出a [ k - 1 ]中的元素。若使用快速排序(如图1 4 - 11所示),可以获得更好的平均性能,尽管该算法有一个比较差的渐近复杂性O( n2 )。! Z. O0 g/ {! X" W4 S
% h& j* J1 n8 Z5 i9 ?. v3 X
可以通过修写程序1 4 - 6来解决选择问题。如果在执行两个w h i l e循环后支点元素a [ l ]被交换到a [ j ] ,那么a [ l ]是a [ l : j ]中的第j - l + 1个元素。如果要寻找的第k 个元素在a [ l : r ]中,并且j - l + 1等于k,则答案就是a [ l ];如果j - l + 1 &lt; k,那么寻找的元素是r i g h t中的第k - j + l - 1个元素,否则要寻找的元素是left 中的第k个元素。因此,只需进行0次或1次递归调用。新代码见程序1 4 - 7。S e l e c t中的递归调用可用f o r或w h i l e循环来替代(练习2 5)。9 G, S6 T5 {6 x* @1 w& d/ ]; O
) ?% G/ [6 H1 W
程序14-7 寻找第k 个元素4 s- }# K" y! M# i1 F

( U) P* n9 R& p' O# f/ U& [+ etemplate<CLASS T>
# P! I9 X5 X7 ]% ~& y2 i. Q+ Q4 H  k3 q2 V% v
T Select(T a[], int n, int k)
  _# Y3 H! O! b" w  W1 ]8 N2 q0 o; w1 S; A1 m  |( ~
{// 返回a [ 0 : n - 1 ]中第k小的元素
. J! [6 l% T% P5 C' u7 q$ U+ R& e/ _8 D8 K6 B
// 假定a[n] 是一个伪最大元素
; F7 C9 x3 f/ Y% v; ^
7 a- _8 ~4 e' Z% n5 Uif (k &lt; 1 || k &gt; n) throw OutOfBounds();- R/ k2 J( {' a. I
1 a$ ~/ Q- b# r1 `2 l/ o
return select(a, 0, n-1, k);5 Y" U: T! j9 A8 `
5 G. P& I& F8 {: L8 N' A
}/ o$ |* _5 d! c" k; {: m) j

- z6 k# y+ z% f" Rtemplate<CLASS T>. T8 q" x$ ]2 k* K) Q5 t
! C6 H! R9 t0 g6 ^& M6 J
T select(T a[], int l, int r, int k)) H2 H1 v: _! N
: s  H( m, H/ N, v, X" f  q
{// 在a [ l : r ]中选择第k小的元素
5 G9 R) L# c8 y1 w2 z6 x0 L0 O6 O  r* `
if (l &gt;= r) return a[l];
' _: r8 d2 H0 e1 y
% X8 ^4 L0 d% V& ^+ Z6 }* b% `8 [1 F$ X! {int i = l, // 从左至右的游标3 |6 L2 G3 l( s* t) e9 W5 N5 w
9 d$ K  z; o. f/ P' ]9 L$ ~8 V
j = r + 1; // 从右到左的游标" m- N1 v- I/ c8 V+ D
- q8 P% h: R/ P: |# c* @, C
T pivot = a[l];$ f) ~6 v) {/ B: L# F- ]1 u' {

. f  _% c) q) a* q// 把左侧&gt;= pivot的元素与右侧&lt;= pivot 的元素进行交换4 }' g2 Z/ n1 j5 o  Z4 E

, ^4 t( ^) T0 w" Cwhile (true) {& U) C, @* U. o0 ^9 z1 w; }$ b

( F& r& X+ y* @$ H8 ]do {// 在左侧寻找&gt;= pivot 的元素
) o$ M; y8 t6 q* q( F3 j- r( L3 v4 e# v" r& G3 c
i = i + 1;
) q. r! J% x7 C: w" I" N5 f' ^8 R9 D, G) q5 C
} while (a &lt; pivot);" y& K( u/ x, i8 p% n% `

+ S. K3 I) F3 O/ q+ Y7 \+ pdo {// 在右侧寻找&lt;= pivot 的元素
9 i0 Q) x6 a# z$ z6 l$ v2 x
9 V- s0 a" F2 }. j( O, X& _+ mj = j - 1;9 I3 n; w0 C) K* \+ R7 p, Z/ v7 x
* ^" }$ l! h' Y6 l) O) K7 M
} while (a[j] &gt; pivot);
) y% X* f2 M8 t* e: Q: z
* N$ ~# {5 a3 h, lif (i &gt;= j) break; // 未发现交换对象
0 q) r5 M; h6 k. a* ]+ l; Q/ {) e- k  z' K9 r. x% H
Swap(a, a[j]);
1 m* L& f: Y* H8 i, y6 l" O8 T5 M) E/ ]8 w9 L3 p. X% h/ g
}
3 E+ g1 J8 Z) Q$ O4 a, X, |" A4 R: K' t- f- x( o" _/ P3 A8 p+ d
if (j - l + 1 == k) return pivot;- e; L8 d1 j9 o- q; @: G+ M, Y
* D% T" `2 M. L" d
// 设置p i v o t9 W. l# V5 R3 o: @
  d  ^# C& S# X- Z- ~% r$ D. D
a[l] = a[j];
3 c# E; y0 o3 f$ L9 T; E, L* V6 y' Z( [, b) Y8 q/ N  m4 Y
a[j] = pivot;
# ?# T" ~+ I0 O. ~1 G/ W- C
8 J+ [; Q- _9 f& A' z  b- @# m// 对一个段进行递归调用3 r9 p- t+ d1 ]: h
3 e1 T+ {1 i$ A7 a
if (j - l + 1 &lt; k)3 @  |7 L" b4 U  p$ Y7 |9 M0 \
# L) a0 e' ^8 R. x
return select(a, j+1, r, k-j+l-1);
4 l+ A1 z% T1 S# r5 i* `* {4 B5 n& D9 ?+ ~/ h
else return select(a, l, j-1, k);$ d: P& D: [4 s. A/ m! b6 b

3 E  U( ~! F6 G}
7 x: g6 ~& ^2 F8 |* h6 ^+ Y1 h
2 H  m9 t  ^5 n% u  W3 N程序1 4 - 7在最坏情况下的复杂性是( n2 ),此时left 总是为空,而且第k个元素总是位于r i g h t.
6 w6 i) u0 r! w2 w
) C  j% _% [4 }( C; W7 a- N如果假定n 是2的幂,则可以取消公式(2 - 1 0)中的向下取整操作符。通过使用迭代方法,可以得到t (n) = (n)。若仔细地选择支点元素,则最坏情况下的时间开销也可以变成(n)。一种选择支点元素的方法是使用“中间的中间( m e d i a n - o f - m e d i a n)”规则,该规则首先将数组a中的n 个元素分成n/r 组,r 为某一整常数,除了最后一组外,每组都有r 个元素。然后通过在每组中对r 个元素进行排序来寻找每组中位于中间位置的元素。最后根据所得到的n/r 个中间元素,递归使用选择算法,求得所需要的支点元素。
9 o9 D5 J2 f. d& l* q+ b" G9 ^) z6 X7 I& U0 ~7 [! q5 A
例2-6 [中间的中间] 考察如下情形:r=5, n=27, 并且a= [ 2,6,8,1,4,1 0,2 0,6,2 2,11,9,8,4,3,7,8,1 6,11,1 0,8,2,1 4,1 5,1,1 2,5,4 ]。这2 7个元素可以被分为6组[ 2 , 6 , 8 , 1 , 4 ],[ 1 0 , 2 0 , 6 , 2 2 , 11 ],[ 9 , 8 , 4 , 3 , 7 ],[ 8 , 1 6 , 11 , 1 0 , 8 ],[ 2 , 1 4 , 1 5 , 1 , 1 2 ]和[ 5 , 4 ],每组的中间元素分别为4 , 11 , 7 , 1 0 , 1 2和4。[ 4 , 11 , 7 , 1 0 , 1 2 , 4 ]的中间元素为7。这个中间元素7被取为支点元素。由此可以得到l e ft= [ 2 , 6 , 1 , 4 , 6 , 4 , 3 , 2 , 1 , 5 , 4 ],m i d d l e= [ 7 ] ,r i g h t= [ 8 , 1 0 , 2 0 , 2 2 , 11 , 9 , 8 , 8 , 1 6 , 11 , 1 0 , 8 , 1 4 , 1 5 , 1 2 ]。5 s7 y# O5 z% w" V& q8 U0 R/ {, r
' e( N' f$ i2 t' R1 U4 z4 E
如果要寻找第k个元素且k&lt; 1 2,则仅仅需要在l e f t中寻找;如果k= 1 2,则要找的元素就是支点元素;如果k&gt; 1 2,则需要检查r i g h t中的1 5个元素。在最后一种情况下,需在r i g h t中寻找第(k- 1 2 )个元素。
" D- v1 N! u0 Q1 W9 I
$ E3 P5 [! \! Z5 ^定理2-2 当按“中间的中间”规则选取支点元素时,以下结论为真:
$ h/ k! b4 D; T: G; \4 K6 c+ L$ h* M" _5 C
1) 若r=9, 那么当n≥9 0时,有m a x { |l e f e|, |r i g h t| }≤7n / 8。
1 B- o' @5 H$ u6 d* b; m3 u4 }& ?! G3 H, x7 ]- a5 b( W
2) 若r= 5,且a 中所有元素都不同,那么当n≥2 4时,有max{| left |, | right | }≤3n/ 4。6 q9 u( h0 z: D, e3 O

8 V4 ^1 K1 q' R1 g证明这个定理的证明留作练习2 3。5 m6 U# N& O: M% Y. }

, x4 ^1 I: ~# z8 i) `' d7 a# A根据定理2 - 2和程序1 4 - 7可知,如果采用“中间的中间”规则并取r= 9,则用于寻找第k个元素的时间t (n)可按如下递归公式来计算:/ T$ y- T* X+ c. R  [

3 {; [; P# A" }3 C: v) x+ H2 l在上述递归公式中,假设当n<9 0时使用复杂性为nl o gn的求解算法,当n≥9 0时,采用“中间的中间”规则进行分而治之求解。利用归纳法可以证明,当n≥1时有t (n)≤7 2cn (练习2 4 )。
/ c* A* Y6 Z! c0 n& {; f0 O/ D" t/ b
当元素互不相同时,可以使用r= 5来得到线性时间性能。</P>
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-7-21 05:12 , Processed in 0.253830 second(s), 52 queries .

回顶部