" [" |6 F3 E( T" s2 S/ y第一组越界(即end1越界), D9 l o+ A$ O* t9 r6 p4 G" |: A
+ B; c' j. G7 y3 A" y, J应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。 / K4 H2 S$ g; w$ ~! v# U; I& i: J . ^. E ]8 y7 g: Q第二组全部越界(即begin2和end2越界)$ _ G; Z" `0 r* @
8 P$ J" R6 t' W+ J$ L& G
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。/ b# c+ Q- t+ r( Q' n% t7 n' ~; d
5 ~0 @5 g. ]: I; f8 T$ t- ], g
第二组部分越界(即end2越界) % [8 C0 j- _/ Y! T9 {9 ?7 s8 E2 L+ D' w$ \ {
应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。 : c K! u& Z$ S7 W9 X1 _3 U 6 s( `+ l# C9 M) k/ [5 Q 其实第一种情况和第二种情况可以合并为一种情况,原因: 7 Y- ?% h2 t' _8 e, R% |# D: E' d/ f0 n
end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。5 L) a8 z4 p3 [( p8 `( o
! j4 p( L& |+ B& V. @8 `
拿两个数组试一下: 4 T2 C/ I# A; v4 t G9 }2 N6 v5 F, Y- F
# ]* d0 c8 p8 s) z6 q+ s
7 W- F0 {; \+ S" n; J3 H' C- B F! @ w- V5 N5 K9 {3 u
) J' E% m/ k/ X; Q
代码实现 7 ]; t+ l x& r1 }! g2 G) T9 h$ J: Z7 B$ E G4 S Q% }$ N, W
void MergeSortNonR(int* arr, int sz) - j, O# O6 R! Z0 P$ ^{ " x2 X- t& u5 R1 j# p assert(arr);# ^" A1 n; p$ X/ D7 Y
q- O! f/ M, X& Q# {
int* tmp = (int*)malloc(sz * sizeof(int)); 8 C4 I+ ?: t- C$ s/ ~% `& ? if (tmp == NULL)! V% h" X p7 Q& Y6 q, t" j
{' u( l; I- B6 B' l
perror("malloc fail");) R2 s6 E/ N" N
return;9 Z. Y2 o Y2 o% m6 E4 m. S" p
} + n! i9 w+ C; l( X, v* C# ]% z * J; @! w, P- L) b# d/ d" u int gap = 1;' o" ?' q( }6 c$ h$ q, }& I
while (gap < sz) * i& L7 K! f+ q8 ]8 Z1 k {( H7 B3 ~# l* i
for (int i = 0; i < sz; i += 2 * gap) ' w8 T' d. A" z1 P# u { 9 i2 {- |" [1 P. p int begin1 = i, end1 = begin1 + gap - 1;. D; i L$ `, {& U% [
int begin2 = end1 + 1, end2 = begin2 + gap - 1; 6 I/ j' @, V6 @$ K3 \% { int j = begin1; $ v1 q; }: l" K {8 ]9 p //越界检测, v# t8 d$ z/ {/ j! X# i* v
if (begin2 >= sz && end2 >= sz) 2 \0 ?! Z0 Q2 m9 {9 n- h6 i5 v break;' v% ^# L; t. Z! D$ p
if (end2 >= sz) O$ v, b0 v$ o8 s1 J. y
end2 = sz - 1;5 F: m/ ~7 ~+ T9 z9 g" h( x5 R4 V" o
//归并6 B" v/ a2 v5 u3 @$ q7 B. h! h
while (begin1 <= end1 && begin2 <= end2)+ ~6 T. s* K! {! A0 ?
{ 6 S' u) y' Z# a' l, f; Q; X1 O/ y if (arr[begin1] < arr[begin2]) + K0 h/ ~$ F2 E tmp[j++] = arr[begin1++]; 1 N( ^# J8 ]3 n" D else * B0 I! }* b2 A/ \% d( O
tmp[j++] = arr[begin2++];6 [3 g C& `7 R K5 @* P, ^+ m
}) d" y8 @9 F) s6 r
0 p8 f6 c3 G' _) B0 ]+ b- N while (begin1 <= end1) $ Z1 X: L0 ]- m0 {& ?9 L. X* Q' t' r tmp[j++] = arr[begin1++];/ @3 `" u8 S5 }# o, M, A. j
while (begin2 <= end2), [# N( m8 O( U) m L& a
tmp[j++] = arr[begin2++];: A Y* R q! [# X0 D6 Q' d
/ [# o8 }- i: A: }: |$ D# L6 | //拷贝回原数组——归并哪部分就拷贝哪部分回去 f+ w, s9 P. n- W( W7 d
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1)); 7 f: C' F+ t& ^* q } ; }- d' J5 z Z2 w gap *= 2;# W: g. f' \* B3 k: _
} + \. z R6 F3 _- Y% A% _4 ? $ b* K! b8 q E( O}8 z* Y3 J$ z4 U/ w
9 s# H6 Z- P" ^) [8 q* O% K( z1 $ v, M9 D7 N2 l/ m% ^2 2 f8 K2 F8 O. W5 g% _7 R! U% C3 p3 0 s8 Q7 M4 ?% L& P47 b/ x( ]3 d+ n9 \/ H, F/ s
5 7 w; a' g! ~& \9 `$ \- X6 / t: q- t" E1 M7 W4 N$ u- Z7& B5 Z* X0 m, l
8. ^( T. z; h% v% f' w7 G
9" g! i' E1 e7 @
10 ) f% q$ O4 I" X& Q0 j( G2 r11 + k9 Z$ q( k$ n: P120 T2 r" x* s3 r9 D$ e, h# @
13& f* }& k+ q5 g/ b2 ~8 p8 H
14; [5 s, y- t H3 x. ~: P' m, |; A0 R& [
15! s" i) u/ x9 h" h/ l
160 \1 U4 O2 @- q @
17/ c! n8 X7 C8 [! t8 j+ T! L
18) p# ^( {+ p9 [ l; j0 n% m
19: l& G) ^; e0 N6 c
20 . t, W# ?. v. r. }7 \21 % O. i% h$ b4 }5 a220 H9 X( N1 ]* h2 z1 {/ H% N3 K s K3 I
23$ K9 j/ W. K, ?7 e
24( V, ]% Q N+ x$ I# d; ?* l! h
25 & F8 H$ P* O" s4 J2 [/ U265 b# x; d' t9 b0 r2 h
27 & Q+ ` |- }, K# e7 {* B28! A( E$ W- y5 T
29 & L2 P2 a& v* H30 2 x$ F+ M0 o' \7 L4 p, y31; M5 ^4 ]$ s' b# \$ N
32/ K" J0 L* }9 z1 C5 U
33, ]) k% q6 L+ g) u9 s) i
34 9 Y, R, n2 A7 q. h35" c0 i, Z7 B/ ^- s$ J
36; G4 C( O, {5 b( Z
37: i! b0 l x/ j$ {% ^' b
38 3 O0 n9 P5 g' G# T! c. f3 i395 i7 Y& w6 z* R; O( M0 F
40 7 @- [5 S2 _& h3 B; E& @41 3 [2 w( {% a3 d( M" _% G6 s1 K5 T42' t4 s1 b& b; @0 M/ S
43! m; y6 S) G4 {! ] @
44 ( W. _; I" l) Z% d/ y$ D1 y2 n45 7 [. E$ |/ B1 U; m& I归并排序的特性总结:' `$ X, P3 N& s _6 n
- K, D' X$ u7 m8 _: E归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。 ( j9 I% q9 r0 p( p/ L时间复杂度:O(N*logN) T4 W' S+ b+ l7 l+ z) H% h- O7 E# r# x空间复杂度:O(N) " E! _5 | A0 n: s/ A, K. u稳定性:稳定+ d3 u- ~2 x7 e. ]! |- E9 e J