. o5 ^9 e( [( ?! s* Q# v; G free(tmp);3 C' W; B; ?$ C# p( c2 O9 [& T# ]
tmp = NULL;+ G+ b' H) n- d, H j; L
}0 B% L: P+ V1 U. K
5 E+ i: v# v# \2 x3 L
13 k' T! V9 T( o
2 ; O l" b, `0 E4 {4 ?/ x) X$ I7 ?3" W4 g& N! q: B- i
4 + z$ p7 H y- Q, h: W5 * P% z# s3 {- v4 M- S: H+ ?" y6 9 ?% ^# B+ H" }$ @7 o; P ^" p7 + R" C4 f& u" Y8 T0 p3 l, j8 & G8 d: s/ C2 Q$ K0 n% T& v9 1 [) V0 X8 Q: Z, ^/ @10 ) g: j+ ~- l9 f+ y! K11 # ]1 r0 o" _& l% ?12( o& Z! h8 @) v/ H" C3 i
13 : R7 E3 n. {6 x14 % }1 y+ E8 t0 j0 W; C; n% N# l) Y6 R157 b* p, ~" ]5 z5 @
168 \9 V3 ^$ ?( z ~ B. M1 M( ^$ d. ~
175 J4 a( }% P& g* d
18 + q( R1 ^4 B- W" g5 L+ h4 k* M19 8 b- {" ?; j" }6 w" m1 c' K20& C2 _& C' e' K, m* V! `
21 # x- H3 k/ C ~; d222 n7 D: w" C6 ~2 i
23 / {* X+ K( O8 v& n6 ?( F% N245 z" N# [" H7 n2 i" C" G
25# y/ [- l' t& T: U6 y9 S9 U" n& j+ p
26: B' k L# }- b, J$ _* j9 N
27 + i: u) E1 V) v: G2 w" X. r28 : A6 F% d# r9 J( S4 z& `( _$ r29" z1 \. h8 T5 z ~& w k! ^8 V
30 4 U. E" W2 `2 l/ k31; E2 q. e0 ^0 \4 i6 p8 F9 M6 W* T F
32$ ?! y- o( Z* k
33 5 z, l5 F+ {, Z% O0 F" F34 * C$ m: J4 U! Z" r& R' ~- y35 8 @4 S6 y( Q9 |/ E36) h3 U% u& D0 d' e2 y
37 & s$ d8 { K' q* H0 e2 E38- ^, t" j" [0 Q" ^4 M7 u( A1 H
39 $ b1 u- X G2 [# O7 m* u. k7 c404 v: J, n: F4 h" v5 m3 G
41 ; u' @# o1 r7 |; V42 ; y& p# V2 U5 o1 ?) i43 $ E# A' B; c1 k5 x+ ]44 / Q# T# ?) h+ c5 X455 N' S+ m% B+ N. `8 i
46 3 U$ E- u+ ~/ r47 ! o t1 Y* H# d48$ S$ W& e4 X G9 z9 A
49" s5 y& r7 A2 q3 X
50 8 O1 Q0 v3 h' W" r! V51& d& z' J2 L' e% S2 M* _
非递归实现) W8 _3 ?! u# f8 R- H
直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。 9 E* k }. ^9 X1 h* L7 c, n# l+ w; E3 D$ s" t* {% m5 v
n( u/ Z0 @4 y4 O9 [6 Y* l3 V. E! H8 Z# `
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。 & F7 f2 C4 o4 T5 J. y0 [ ) i6 ^5 |! s% K3 i 还要注意区间的取值,每个区间就是一组,就有gap个元素。 % X+ \5 T h9 \& C/ Z! M8 H. p1 U
整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。8 S7 C0 |* w0 a' A
) @ d3 B6 P1 H4 Y
代码实现7 p/ E( l. [0 e
% M# ^7 U* _5 f% E5 J8 P' j3 gvoid MergeSortNonR(int* arr, int sz)( {7 N& P6 G6 B4 h! W) B5 F) V1 H q
{7 p, p; f: {7 J: y5 O/ b
assert(arr); 6 J1 I5 [9 x* g% n2 M# E : m& X% O1 S g4 }9 O: D+ ` int* tmp = (int*)malloc(sz * sizeof(int));9 @! {5 L' C9 M2 T2 D
if (tmp == NULL) / p" E1 c, g+ i {# B2 D: a; o: { _& `: u1 n f
perror("malloc fail");2 m/ j A3 b$ A$ T# k
return; 1 C4 m. h1 Z' x/ N# i( p }( l1 K, C2 v4 w0 s* r9 S' N* W. w7 T" e0 {
( K$ e1 o0 ]4 A% ?9 m. m int gap = 1; 1 d6 `$ t4 \( w9 T3 G( P while (gap < sz)9 R7 Y m3 S+ F3 a0 Q
{3 a& `9 m A' M% e" S
for (int i = 0; i < sz; i += 2 * gap)1 F0 ?/ e+ W+ p- z
{ 3 R. i' G- U4 |' P int begin1 = i, end1 = begin1 + gap - 1;' g) ~* f6 E$ f% D; z
int begin2 = end1 + 1, end2 = begin2 + gap - 1;- I7 f7 Y" E1 X o
int j = begin1;" _' M& `1 u# G9 m% }0 @2 J! a
% u; w) ^( q$ M1 R //归并 7 u/ Y2 p1 c/ s7 z while (begin1 <= end1 && begin2 <= end2) 2 `" z5 P- W0 z, e4 v; K { ' c8 C& O% M8 D4 k2 m6 u; R4 L" o if (arr[begin1] < arr[begin2])1 P7 c" ` K# h, l9 {/ ?- H$ x$ N) |
tmp[j++] = arr[begin1++];; i# ~, e, d& s% z7 U! |& R) G n
else 3 B* C$ G) @4 U b' s* J& G* Y
tmp[j++] = arr[begin2++]; ! G( D2 w$ A+ P/ X } 4 f( g. D1 W8 V- O, L3 t# O: k, D $ u* i2 u @' ~% t5 s while (begin1 <= end1) / X2 |$ \ e k tmp[j++] = arr[begin1++]; & y. Z1 E; j! ^) L" p while (begin2 <= end2) " p9 F; p8 g: q tmp[j++] = arr[begin2++]; & @6 p( ~9 D: C5 }& S 6 d: l: q8 L: K7 t* }$ a. |6 v //拷贝回原数组——归并哪部分就拷贝哪部分回去& t# N5 m/ G. s; d$ T- K, d; Y
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));+ |. h$ w! l" P! h; z4 H/ C8 y
} $ W8 }# d a* x, D/ Y' P1 D4 d: S# J gap *= 2; 5 }- E+ _9 |8 n; Y( G } c# E1 E8 F8 o& n$ p
. D3 w0 ?' \2 H 拿两个数组试一下: / a" ?) q2 d( c4 w T: D, m2 _& Z 0 R6 H: [; f1 u. X& i + f; H' b5 W- t0 r& I9 G$ F# [# p" b* f
2 b0 A$ o5 d7 E( @3 D$ t ! f+ U5 @' [1 s代码实现% H, k4 r- F* f7 @
6 G( I9 ^" a: R" \, O
void MergeSortNonR(int* arr, int sz)8 {" O, O' G* b6 g; |
{ o2 _ x! t- J& Z$ W6 o assert(arr); b6 K( A2 `" O8 W" }
' p3 J& r6 a5 m0 y+ Q) K
int* tmp = (int*)malloc(sz * sizeof(int)); ' l$ s9 m: G: b! e" Z if (tmp == NULL) 7 @4 K4 v7 x' Z$ w+ s N {/ d0 Z1 r1 L1 k) V
perror("malloc fail");$ h/ D7 O: m! C9 x3 Q3 A
return;3 F3 l$ m) N) I2 n5 T( F1 F
} j' }6 s' r9 L
+ X( f i( q5 _
int gap = 1;$ @9 L" a6 `' w- c" k& A9 t
while (gap < sz) 0 V3 h3 M0 w' s8 v+ [) f" l+ G. m {( m% c9 R1 ^# n1 V# X, N7 q
for (int i = 0; i < sz; i += 2 * gap) % C2 `* U @$ i" f8 R' k* W {9 {; o, q8 s7 Y1 L. B! L) w7 V
int begin1 = i, end1 = begin1 + gap - 1; 5 I4 V% J$ O7 L# |- Y int begin2 = end1 + 1, end2 = begin2 + gap - 1;$ s3 a& O1 v% g6 |; W r9 M
int j = begin1;( z. f2 l/ F0 F/ x* k" J; n
//越界检测! F; X" u% r# N7 ~) K( d7 p5 ^& ^
if (begin2 >= sz && end2 >= sz) / u1 s; w7 s: S4 p break; 6 I! L( X! P9 V* @ if (end2 >= sz) / H. B# h' ?6 K+ i: [9 P end2 = sz - 1; ( c) u# X9 V3 I+ n2 Q/ |) H6 K //归并$ M y5 \$ Y2 q9 M" H8 g
while (begin1 <= end1 && begin2 <= end2)2 `) F" R% ^( `6 F& w
{ 8 K0 Y9 y3 h0 v3 ^ if (arr[begin1] < arr[begin2])# ?( ]- A4 p) O5 `3 L8 Y
tmp[j++] = arr[begin1++];' P& a _7 v3 L
else 1 E* x2 ~; x+ l; P. [8 E
tmp[j++] = arr[begin2++]; R6 i" T, U t+ C3 l; X# W
} : [4 T. y* c1 k2 ? - E' R8 r+ c+ L7 Y" P. n while (begin1 <= end1). w ?. k5 H: i0 ]' S2 s* _4 R/ C: @
tmp[j++] = arr[begin1++]; # Z4 E$ [" G9 f+ D while (begin2 <= end2)+ @3 N- A! C; P/ i+ i
tmp[j++] = arr[begin2++]; 4 z2 O2 Y4 h4 \) K% {: w - b# P# _, L/ G //拷贝回原数组——归并哪部分就拷贝哪部分回去' q% i; e. |: @" a9 T n
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1)); 8 j7 R5 K; p# t } 7 R9 K8 t* f2 g" ~! R' m7 a+ @ gap *= 2;. C5 y! I4 S4 ?9 @) k. B
}! u( U. N$ H& f3 c( N
! c! k: H, X: }2 k4 \7 |/ x
} 2 V/ T7 a7 x7 B; O2 Y5 H0 ] & [3 X* s! ?) _% S' V- w/ U13 k! V9 D; u6 o/ {7 @
25 k p: F) c [$ J8 G
3* d5 k# E9 s0 O
4: P: k& z9 t& e# X! c
5 5 ^4 Q2 l/ N' ]. ]" u68 R6 K* u4 v' ]
7 2 u" T- Z* z5 J7 y5 n! E8 : \& |1 A3 e" ^% ?9 m9$ l, }& X8 C" J1 [
10 ) c7 K0 y _" o- a7 Z3 |! v11 * m; S! R+ h5 F% o12 8 |. H$ U$ M6 A: W( S2 A3 M137 P5 {' O: b B2 G# _- f
14: ^, Y3 @3 C' b/ S; D$ |& D3 m& u& B
15 $ q; u% ` F# C9 C6 ?0 i0 m3 ?163 `" G' i! C" d Q6 ^6 M% u
17- }6 v4 p) ?% P
18 3 g3 {5 E, H2 G k4 j* x8 z& U19 + k$ t/ N3 J# u. |9 O" F9 _+ E20 , g5 n/ X7 o& W21 $ k: a" J: y2 S$ s22 $ w, @+ Q4 C" M. v/ }5 a" ?231 Q* x/ H7 X& B* X# ~" m3 P' Q
246 v9 M, I7 U# z' i
25# l9 j: J k0 f
267 E1 H: Q8 w9 G
27 7 N) a) l0 h$ i+ l0 Z6 g28 0 V$ n" d1 [2 p8 {. l0 O+ B29. q/ X- [, Z+ j" q3 t! v3 I
30 # z' d! o& Z1 K8 w, y2 h7 d0 J31 ) v# g4 K8 \# g+ v- L: Q32! S, e$ d$ f0 [( H8 i; m
33 - s: B1 X0 {( o' B34 # Q; n# t" U5 a: k: M% f; U0 a35, \1 n( X5 }* o! J/ G
36 ' V- K$ D3 q% k9 t M1 ^$ C. s$ N& L37 * E" U" e$ W* r9 s380 N d8 f4 y+ O
39% ]2 @' ?6 Z4 D# V) {$ u
40 J; x- _+ k( Z6 e9 I1 Q41 1 ]8 F* |% O( I2 R42$ S6 g& F0 A) F9 G
43+ m9 p9 p* L+ O
44 0 u M6 }- X2 G, r7 h. Q45 $ w" p9 m8 [2 n* H3 k5 \归并排序的特性总结:5 W; Q6 z5 D% [& ~
- n6 M3 A, O! @2 O, d: `$ X9 [: Y
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。; i7 C4 g6 T) k9 Y1 B. b
时间复杂度:O(N*logN)+ v, p8 p J7 d: k
空间复杂度:O(N)* C; O: r1 R! W
稳定性:稳定. Y$ S# _) x; L( I1 q
) Y, F, L4 @: @- e———————————————— 9 y/ K1 W: d+ t3 C) s' _版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, G+ x1 i: @1 G! s
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657 / @4 R0 V: j. P+ [8 Z ! P( g! |# E4 g+ q) ~3 b 9 g3 F8 g E8 M. A c! G