- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564444 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174556
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序
& h2 O! S" Z4 a% a6 {8 W" B) l8 B6 B9 d7 X S: I$ i
前言- T& |1 }5 q9 y% U; T2 h f8 I
本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。% C! [! O* M# e9 M8 O5 [9 f
0 ]; q. h, N+ N$ C @归并排序* q! J5 |$ t/ W: B* o
基本思想
0 e \& l1 W- z; k" e 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
" F: y* n5 |/ n, _
3 l* f) F1 I8 F! R# \
8 w3 O1 _5 h! v5 j
* _# T/ e: i Z& L 合并的思想其实和有道题目的思想如出一辙:
& C$ u& |/ O& O4 p
. X9 v' P9 v- r, m3 Q2 ?
( c% ?, z: G5 J& }8 p! l( z
* }/ P- c; u5 G$ p1 K; j 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。% @% w6 f1 ~: O x K
( Z4 O5 E; z: V( |7 q$ w& l[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
2 @; M0 q* C+ f" P) |) K+ U- e
: p9 n, \8 C2 a4 g: eint* merge(int* nums1, int m, int* nums2, int n)+ \/ J# C4 J, `9 z& A+ i
{) `4 t& E& b% s" B) Q! a
int* arr = (int*)malloc((m + n));% p- t( O6 |! h2 Y0 y
if(arr == NULL) E7 ]4 G9 W+ \
{
/ L* P; d; w% i7 b8 }0 p1 ~- C perror("malloc fail");
' i; @& x# d( K% A0 N0 i' F return;5 d+ t* g" B0 c" R! i) J" W
}
% p$ l! t" F6 i" {% R6 @( g) b w! ?5 f0 `& E! N9 X
int p1 = 0;0 ^' D2 M% I4 r( I+ a) y8 P
int p2 = 0;$ u j3 x2 Q+ v/ b7 G
int cnt = 0;
4 X$ z/ H- s# v+ I9 g/ |: R while(p1 < m && p2 < n)
. A1 X! \$ V5 \9 ~' m+ v {) P: z" R+ D- @ H
if(nums1[p1] < nums2[p2])
7 w5 O4 i0 j+ V, X: [) B {* ~- w r) F* w% V
arr[cnt++] = nums1[p1++];( x' m; U) w& E; G* F; h
}
2 h9 P: [4 m, ~3 _+ x else
1 b& u) G# Y% Q( }; N {7 Q% E1 v% y* ~$ ` u1 q
arr[cnt++] = nums2[p2++];
& r0 [$ I8 h5 }3 k9 x }
% @: [$ Y8 {( n% m# b3 } }- {" }2 g1 ]; r( \! ~% B. _
while(p1 < m)
1 y% K" K/ D- _0 }; T1 q arr[cnt++] = nums1[p1++];
3 W Y( Y: p8 V( X" [8 J
" T; A. ^$ d/ T" `$ m8 B9 L' s while(p2 < n)
3 i# \2 `& S9 c, k& o7 D. G. m arr[cnt++] = nums2[p2++];
) r0 U9 H- z! t: [3 K0 a3 T7 k. _) w! i( _
return arr;
1 Z. m* p& e5 y7 R1 ]}
! y7 ~; u+ G# z, W# v( R- u( C# g6 T6 v! o% V D1 j+ b6 ^& y
1
7 x7 U# y' H F/ P2
- ~& F1 @! o5 M2 `1 \3
8 E8 n, e# J, h/ z4
- M$ R- h% u+ z: ^+ p5
$ _+ U, ]4 e! ?) O8 p8 R3 u6! [" U# J' b4 F7 t
7) x% r5 _+ I o) c
8
4 D. w! N6 k% \2 \" A, k& ?9" I* z m" r0 z' @7 [/ ]
10
. B% w9 p/ S0 e11
5 W! z" Z* T1 p3 w: ]; C5 O9 u: m12& _0 e* o/ X; f5 E% H: V
130 h2 F5 ^5 x x, I
14
+ J( j# {! y( Y/ y' N15* [8 {' `8 ?& N$ M) z- w3 s! a" B, l$ ]
16
# R( V1 t1 k; f% k7 j6 l17- Y; {4 o5 u$ v2 Y
18
, j3 O" x7 P5 T+ K+ @- n19
( U' O! k V: w$ \+ @20
1 I7 X- T2 s( G# @3 m21
0 d7 \% p$ g1 q; h1 G* g; D22
8 P/ g) `6 c5 k0 w23" D, F) u+ {0 h: d
24
' U; f5 U2 O3 N. V7 v25
) O( T6 |/ k* a8 E, S& t% \+ l26
0 }$ k/ K( q) @. @' Y27- g- p; w; t% g
28# o' e3 i6 F/ R7 k
29
0 W* ?! \. v9 d# S30# J& _$ N, y8 p' N
31. h3 Y9 B, x: M! Q; Q
所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
4 r- i7 ^/ u: _6 L6 a( K0 {. _
. Z& }) n( M0 |递归实现! K3 s* q3 U0 w1 J5 ^* o6 `
通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。9 A% s) k/ R% i) y/ W
. M, b4 t' |) L* c' R# U j% U9 K
" c r5 R* k/ [8 r8 K' d+ M; a& D( j! [* b- n7 t8 [5 G) \
7 O1 j9 Q8 T/ G4 ^- I( x+ \% K
void _MergeSort(int* arr, int* tmp, int left, int right)
0 G# M% y$ J4 a% W/ D) Q5 a0 A{
9 A# J5 Q. D7 x% B assert(arr);
* f% p2 d" @/ S$ c; z
4 Y! w+ l) v) @: r' C/ H7 O if (left >= right)//递归结束条件不要漏了2 u8 Y4 U- S# p" h7 D
return;0 Z3 G0 K, D2 C3 R$ y4 B# i& N% L
. t% `) ]/ W- [
int mid = (right - left) / 2 + left;
' }/ |! K- m7 }
4 Q8 _- q: }0 j- m- Q //划分左右子区间[left, mid]和[mid + 1, right]% v7 N6 G) t1 o2 Q
_MergeSort(arr, tmp, left, mid);0 }+ L. \1 e/ J# v* d
_MergeSort(arr, tmp, mid + 1, right);
# p; R$ \3 H3 Y" T2 h6 |0 Z( `" v" \
//归并7 q, O3 T; e2 A3 s5 S" C3 ]
int begin1 = left, end1 = mid;
; k$ X# f+ E; N% G# O int begin2 = mid + 1, end2 = right;
* h) @' N( U+ M& e+ s int i = left;
- d/ Z, i9 E. F6 Y; U( g: l while (begin1 <= end1 && begin2 <= end2)
: L" Z, ?( r0 S2 [5 u {0 O; }( g8 x& Q: h. w! v) Z
if (arr[begin1] < arr[begin2])
; c+ L8 l. K: H. l& a" e! E( s tmp[i++] = arr[begin1++];
2 {6 I$ }; i; r7 ^ else
% j4 Y* I; A0 v$ Z. i tmp[i++] = arr[begin2++];: e, l& a0 `. B- [6 V7 }7 Y
}9 {8 p" s2 {( q8 z
- w; k4 B& P( w% `! [' h6 M, q while (begin1 <= end1)
) K+ U, S0 \; ~3 P" R9 G tmp[i++] = arr[begin1++];( l V: P4 X, H- R) U& Z* B( g
while (begin2 <= end2)
" K$ n G6 i+ ?/ t5 _ tmp[i++] = arr[begin2++];& K$ Y `' T% b, r; c F
6 v9 H7 E) u" u& a* ^3 |3 ? //拷贝回原数组——归并哪部分就拷贝哪部分回去) r# T! E6 O) e
//而不是拷贝整个数组回去
& E; i7 Q& L+ ]2 N d% z memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1)); m5 v# m) ]5 I0 s
}$ _9 w" g$ D2 ^ L+ Z9 v
$ _! _( {+ v. P1 a3 |# G
void MergeSort(int* arr, int left, int right)3 F* b+ a5 X( w$ O$ V3 A( t
{: Z$ s2 [" W6 d
assert(arr);
' Z3 ~9 {6 l- ]% | _1 d. _+ P
& v% j2 m: d1 ~4 X( v int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
1 q4 _" l! Y* a if (tmp == NULL)* F/ }( v" K6 P' M
{
`6 L+ O3 U& H9 ^: I8 s& O perror("malloc fail");9 P7 K2 p; l Z2 G+ n3 v* o
return;
- p! c5 a, B% ]/ [; t6 d3 L& ~ q }+ U! B! F Y/ T
5 l- `/ C) M* V# b5 g* } _MergeSort(arr, tmp, left, right);. H2 w% n3 O( [4 B! u
- G6 p4 D( B# j% t free(tmp);+ z2 r3 Y8 X3 P! F
tmp = NULL;! @; s1 y) `% s. l$ X7 {* }. D/ l8 l
}
' Q5 t+ @7 b3 P$ `3 k
& V7 j. T; \3 T1 S4 B7 N, V1
" x5 M( u) I7 E5 l6 \& c1 m0 _/ g$ ~2
0 @8 A/ \2 G" i3 H1 I* V1 d3
1 a+ u' s+ T% q* _; Y4
" K- Y% h; r- i* D$ ]2 ?* v5
0 T' L y3 A7 C# B8 P- z6
( V3 X8 M e T7
" l- W3 v$ y- e! E8
0 A4 |4 H) H, R! \3 @0 t' _: x( w9
% q% C; }, d* B4 n3 ~* t10
' z, r/ g5 h6 B4 x+ ]+ s11) @) s2 M# `0 h, a5 G$ L" T" p% @
12
/ m( M2 r6 |/ R: r& y13: y& N. A5 E. {* _* W$ Q2 Q
14
1 n7 G" Q5 H G `) M- h15
' A0 X/ f: k7 {6 |16- ~: l6 i u7 a
17
, h1 w6 p/ h# ?189 J' j, E$ b+ y1 {1 p: P
19% x$ A5 V$ f. {' Y& e
204 Q7 F S" Q3 [. P
217 A [- j7 ^ c: R. X F% \
22$ r4 e; c, x- `& {6 N/ y
234 _0 u9 g! Y$ X4 f" O; |3 W
249 S( q# K' a- |% N7 D/ j
258 e+ \ ?! B% D, C+ ~
26
- K' t2 v8 G# e# G! p. z27) I$ d: K2 ^" Y5 L2 N
28: ~1 D+ _; Q4 `. q$ `; M+ {
291 s x' U/ @; X+ i' s' f+ S
30, [4 p0 |- s. P+ e
31
& g0 V0 O7 V& _$ K! b320 [) o+ P: U7 q! S! M/ ^) n
333 \. E& ~1 Z& c
34
+ s1 ?6 _; y$ f- U! h5 E35
; {1 s- c% z- W! [5 R3 M36
6 E/ n, B0 q. S1 b% i2 h379 @( k. W4 {2 Z8 g& |/ t {
38
) l) f, I* }( X* F x0 {39% U* D( E6 L2 x" e* d; X: j l
40
$ L4 x# V! G' L( I% n419 l9 c+ ^5 j+ ^1 U( p
42# Y" m6 w& z5 L7 _
431 B; E' q) u$ k3 g$ G0 Y& s8 `5 ?5 n/ E
44
1 r) J. N( f' ?# s2 p45( m0 w0 L' b4 |/ w/ A2 K
46" z2 p$ S* n6 j) m$ C! B) G( D
47
6 G9 v( ]9 S# f; Z; W, |; |48
& v" e0 r2 U" d. [493 l& A9 V7 X, @ |) _# x
50
; g* Q6 u( u- Y! }! v4 r7 t* R51' R7 Q' W: B) v' p$ p5 I( q% ~! }2 _" n
非递归实现$ [! x" _: o$ g6 q4 P5 e
直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
/ M8 K+ g* ]2 S7 \: e. n
) [( S5 o* d9 Y, \. y" ^7 I( s2 i- V9 J) v" l' E, F
/ I5 `9 ^5 A$ c& _9 a
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
" F9 Y- b: M5 B, M; B/ |; E' X7 M. Z! K
5 {1 E5 y7 `) c$ f: r9 U% z 还要注意区间的取值,每个区间就是一组,就有gap个元素。/ X2 D" \2 l' c0 b& c
& F9 [& _, f% i! I 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。5 y5 R2 d+ C6 g4 d: y3 J# i
' ~$ N' }: F7 F9 A* H代码实现
9 p. @9 @- L% X: k* {& U5 F
( C# u" p& f- j' X9 wvoid MergeSortNonR(int* arr, int sz)
! [' A" w+ d. Z& X{
% J5 j% {, g3 r) [; `+ q assert(arr);* d% l& p# X* h9 Q: j
3 k+ O( i/ m2 f/ i; i
int* tmp = (int*)malloc(sz * sizeof(int));
0 p1 w* p: B) \2 `- B6 L- c, y& h% ~ if (tmp == NULL)
3 s9 n8 u+ C" z( q: ?; K4 B$ W {! O0 {% j7 ? ^# l
perror("malloc fail");) Z# R. f3 l) }0 D$ d, @: }
return;
9 q4 z5 g, U6 S5 j% J' P }* ^) X- z: N/ ^- h
7 L' Y Q4 }7 ?" l
int gap = 1;# Z/ N4 l: a2 z
while (gap < sz)
1 T7 m) d* S5 M0 i {* l* W( b2 y. |7 u3 K+ d0 ]
for (int i = 0; i < sz; i += 2 * gap)
9 I% W, G* P" N4 D {: A7 G g: @' z( a, N7 I
int begin1 = i, end1 = begin1 + gap - 1;
# D2 e, ?% Z; J: z- y; p int begin2 = end1 + 1, end2 = begin2 + gap - 1;
4 X# N: V0 k1 ?5 C int j = begin1;( E9 [- m1 L& J( g
- V2 U; g. T" Q
//归并
6 W `( J5 e6 N+ q while (begin1 <= end1 && begin2 <= end2)0 {5 W/ G7 G! y; @# I$ }
{) W5 y/ u/ X9 U2 X& g+ X) [! ~
if (arr[begin1] < arr[begin2]): Y3 h0 w5 k% }' ]
tmp[j++] = arr[begin1++];' r- N5 X$ _( e7 y/ A
else $ \0 N! p0 {( ~& G0 _% r
tmp[j++] = arr[begin2++];
9 g2 }2 C# C' K$ ~1 [- f* _ }3 S0 J8 ^ _7 u. y+ t
$ O% m$ t3 r+ v5 D% S+ c% ` while (begin1 <= end1)
( v! K0 r5 Q3 E( N& r tmp[j++] = arr[begin1++];! g+ F! ]% z1 ?, B8 M; j' J* I
while (begin2 <= end2)! C3 A: `+ S+ r/ s. n6 v) k" Y: \
tmp[j++] = arr[begin2++];
& p) j- G/ g' v+ b$ ~. z9 T
' V) T' R1 u1 r# I# Q: }. f+ c' [ //拷贝回原数组——归并哪部分就拷贝哪部分回去
3 I& z1 m9 D7 _ memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));1 P$ G" p: ^/ H: I7 u) p% I
}
' T; H5 _7 _& n+ B, ?$ B" y/ W gap *= 2;! B% e9 O1 A! \- i
}
4 m: J; t! j2 a! ~% Z; y2 h( a1 _. V' M! a! j5 p
}
" v6 _! L. ] \. P
0 b; r8 f1 @/ k1 @1
6 {3 z; z- @" z) d/ Y9 [: ~. I2
. m/ a. N; M! M& o& C0 F* T3
9 s7 e0 K, t( W' Z0 G4
9 L: ?; H% f: l5
2 [9 q% W% q( J$ J6! \) Y1 q# |/ o' z
7! r/ Y3 }. o3 }$ ~7 F9 D
8
' K9 p" c8 i. W4 Q+ |) o8 K6 w9
) v1 _( I* e* K( U10
1 n6 u5 d& Z. a. e11
# {2 k3 C+ t- t6 K12) b# t. D4 i6 p& N
13; X3 s6 h+ G. f5 Q
14+ F3 f! O' q& `
15
3 M( z0 n' G+ Z3 U9 L# d16! z9 U! g9 b R& o1 A
17
* T+ `! r. z7 E18
& O2 `# t9 I' r190 s) _' \! K3 y, c$ D4 _
20
& j7 [! v1 U- P3 P210 ? ?& A: ]& K3 @! `
22& S( i" V0 m4 c/ ~5 m7 J3 A
23# \% _" x8 ?/ h
24
* G, }- O7 z; |25% D: n3 S ]+ ~. L
26/ Q3 g+ s+ C3 t
271 _% k! |# @" w7 Q+ n5 _# T' \
28
! A5 \, n* o5 I' D( k29
1 V6 b$ X1 h. R( J& k303 g+ O* h% a d
31
5 w( I- J0 C2 ^7 R, V& x8 c' ^32; w y7 N, Z% c& O
33
) F# d5 Y3 A2 C* M34
% @1 i4 W7 V6 I: Q4 A: }3 V35
2 H0 b- w) U3 v) H! U7 q K36% H' G t8 U: q0 W
37! {8 i' `5 a' i. _
380 I |: X4 P q; K& Z. D' V' O
39
4 j2 ?: ^, E4 V2 O1 C40, t. U8 }& I, W+ L3 {3 n7 ?
41
, _3 I! L$ R: \; J+ C, S2 }. i边界问题# {# q$ ^6 Z" j r) w4 i
实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。9 @6 ]+ T, j2 i6 U
# J/ \7 b# m0 U! I7 s8 W3 c/ O
举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:+ t: A) z% n' U4 l
5 g9 y C3 w' a: X
) H2 a' }/ O8 J* S# K. M
% u8 W {' }7 D( S4 N由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)5 d$ e8 T' m1 P6 v* T' h- G0 R' m3 ~
9 D3 v) Q# Z8 {, B
第一组越界(即end1越界)
, O( T( |# F8 N4 C5 n1 a; ?' G$ A1 N# Y$ t) ~5 x9 N% D; J
应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
. U) r7 E* Z1 k' j% U+ F
& q Q& ], _1 u* U6 P6 `第二组全部越界(即begin2和end2越界)' V. l& i3 T( D$ O+ ?# T6 I
( q6 Q4 }0 T* R& r) Q X
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。: I- `' r! w; m: O0 T, R' J* v3 y ^
& u4 ?5 j5 [+ f7 y3 ?0 z. `' `
第二组部分越界(即end2越界) Q# P, p1 u# w9 z- [6 H
z* N) H/ B, w; @7 l4 |2 Y' l应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。6 \' H: Q, t7 M' v' w1 X Q
G4 W e& G% c
其实第一种情况和第二种情况可以合并为一种情况,原因:) d+ x) `9 A( Z2 A' i: |$ x1 f( h
6 [/ ~8 Z9 G6 D0 f) z% c end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。+ x5 V* A( J( e$ T9 y+ q; g
& D+ e h5 Q9 r1 Q' V5 n5 o4 f ` 拿两个数组试一下:
! e1 z# m; V' }: K+ ~
3 _6 H+ y2 R. n8 ^) v* W! _7 W, n) d9 k9 w
" q0 \* W" R8 I& K2 ~
, }& Z ?+ m, g. ^% S/ j
+ L+ g; s2 K7 {% x, E' l代码实现: N4 r; J; Q* G) Y6 ?9 a
& g$ C, Y( \6 \1 ]7 p g# [3 n
void MergeSortNonR(int* arr, int sz); A1 r) T9 p1 t8 k# ^
{' D: ]7 k1 v ~. x7 Z
assert(arr);+ h# M2 H! b1 P. C
" m5 Y0 I- o/ S4 i u J" W
int* tmp = (int*)malloc(sz * sizeof(int));: f" V K! n3 J6 ~5 p% a' e# U" k" g
if (tmp == NULL)/ {1 F$ p7 b( y. G. {6 |( o
{
1 j o7 e" n' D+ l+ e perror("malloc fail");' ?8 h/ i* K- ]$ a, a9 r! `: {% n
return;
! x7 n; y5 k3 }1 }/ l4 w }
' A- y( ^- C9 t9 i7 ~ L" F8 r8 Q' ] Y1 B' @! L' F
int gap = 1;: c- I/ n- l) V6 n
while (gap < sz)! P' E' l2 q" r9 ~3 ~
{" Z* J1 o$ q- \0 b) w4 j, T
for (int i = 0; i < sz; i += 2 * gap)6 w- ~! ]+ h7 a
{; C# b$ o; G( T0 E( \% l0 `* ]
int begin1 = i, end1 = begin1 + gap - 1;
& t7 h t+ _2 u# i; g% y- L9 N int begin2 = end1 + 1, end2 = begin2 + gap - 1;
' v. R0 i" D3 \ y' S5 w5 j int j = begin1;
) C! N' E; S) }. a //越界检测# F' F/ Y+ J9 d& b) E* K) t' G- P
if (begin2 >= sz && end2 >= sz)
3 S ]$ f. I" ]/ | break;6 y) b) b! R( W2 x/ _4 }- x+ f
if (end2 >= sz)$ E7 g0 b) p& o1 s% C# Z5 W, x
end2 = sz - 1;
' G: O. k6 j* _ //归并
; } ~. S5 q' ^- Q$ P3 \& P( ` while (begin1 <= end1 && begin2 <= end2)
7 L4 A. W% M; F0 }& P {, p* c; o# L2 M- i* t! Z
if (arr[begin1] < arr[begin2])! N0 a+ @5 @$ P: Q
tmp[j++] = arr[begin1++];
5 v. H* R u" u- E# V7 g else
$ d0 f, p6 o4 M' H( R" u4 W7 L tmp[j++] = arr[begin2++];+ m/ E3 R6 Q( ^/ t, P
}
7 @ M3 q R% Q: T" w
4 g$ G# X; x/ w while (begin1 <= end1)0 a* x& t! |- }8 N# \3 c
tmp[j++] = arr[begin1++];
# o. O2 G( U# ^4 l while (begin2 <= end2)
) b5 ?" |( Q+ b3 a! i8 e+ ` tmp[j++] = arr[begin2++];
1 [- o# C9 ]7 n& ~8 L( @
6 g* D* S1 D) I& P, q# ^ //拷贝回原数组——归并哪部分就拷贝哪部分回去. U/ Y3 T2 E7 e- E' G# R
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
4 q, p" h& L- s! u( x4 P! f* S }
. c" s* G4 Y2 r! Q/ y8 o# E: r gap *= 2;
) z% d# O/ f( v% ^! ~" |& q5 x M: E0 y }0 @6 x7 H% o+ {9 m1 K5 L2 g" F9 M
9 a" q0 @8 R6 X" \& w
}
1 h. ?! R& @ y4 i' m( j# \
) M% G, N# c2 z. @/ Y1
; t6 {0 d& U' }" N7 W24 w2 R/ X; f0 A3 G4 g$ n2 I* e
3
( _; ?! {; x4 m- T3 q2 z$ V4 s" S4
3 p+ r: A' g. ^5 C, w4 C0 d3 o5
* Y; X- S k, d1 {. s6
$ J- C; f5 c; D7
7 v+ k; e0 v/ N: S& {8
1 K5 n: X2 p; o( |, x9
- G6 G. E' ^. z2 t$ M10: P* T& h' f" K' b' Z5 u$ P: o
114 D$ _8 X" o/ y& r
12. {5 w2 H6 @% w" {
130 S6 |' _/ K1 y& B
14
8 L. W& U ^1 {# E159 ?& J: F8 }1 \) v0 I2 ~
16
8 c9 R8 P/ t9 B6 w! x% i0 D. m7 G17) t0 L) E, Z- a+ ~) N: A( E: v% e) r
18
7 z5 s2 j2 Z7 X6 l19% l" d! F; _7 K: T V
20
0 c+ _/ a" t+ j) }21' O- X; X# w3 I- t y3 \8 t* J
228 F. t9 B* Q/ x6 u: C9 g
23
. z6 Q! Z) f A" m240 I4 s8 ^. f/ U
25* L: S; n3 r9 m8 l' f
26
, _. h T6 _+ `$ Q# h1 d4 L27! P9 q: [3 l [' k
288 s8 h V9 D) {: {8 T4 q, K5 W, i+ H7 z
29
& g# {8 }) \) v3 s30
( r; b. v* e- v. W2 [0 T31
$ D! S9 T/ R# R6 G% C& z5 L32
- b" K! N6 e i! _/ i/ ]$ d33
" F" U4 W0 f+ Z! S34
2 ]$ s, R! X4 ?1 k35/ U, \$ w$ ^, a% H' c
36
# R+ ]9 p$ f. H. y8 C$ x37- v' t* `# P; v
38* ]) r* Y0 [, C; e. U: [& D9 t
39: [( V3 A$ v* Y9 Q- Q0 t
40
4 H' Y6 K l2 ?% E4 ]0 @( Y41! y7 P, }) A3 E* ]; a) Q
42
$ T7 h8 ^7 h7 R' t' y$ `* Y! w2 l2 K43
7 {3 _; g) j- I& z44
' ]6 [ S# e; T4 O' ^45
/ ?# R- O; W1 z归并排序的特性总结:
2 ~8 S. g. O+ B7 U( v7 y
# ~! j. T0 [- n) ?2 t% H7 m& w; U7 y3 _! Q归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
$ K b( S2 A9 o# H# F+ G! U2 m" F时间复杂度:O(N*logN)
2 p# s# _% F, ]8 K空间复杂度:O(N)5 ~' b }0 H ^! }
稳定性:稳定
8 n5 X6 r, g7 X# `7 A1 v$ J8 h; c; {$ Y
————————————————
0 ^- M- w+ N5 E) B- J1 m d K版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。. {- Z6 _( c# s) E1 d+ q) D% A# ?, U
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
. d. D$ I, l1 H: w( i0 V8 |: j% G6 E+ h$ k) m9 ^9 g
& a& K( p8 _* u% Q8 ?2 g |
zan
|