- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564700 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174633
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序
# |1 d/ E( w9 M! J, {8 Q) R4 D2 p1 h1 J/ \
前言
9 V$ V4 @) S1 @本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。# L/ X: ]: D7 E, b: y5 G2 e
* g3 m/ m0 W9 b9 H: Y; ]! @归并排序
, r* q/ }( u# F7 [+ ]( I$ z, e基本思想3 P) r. y4 Y: @. L7 S* y
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。) q/ `6 Y# g5 t5 m
9 v% N4 K/ A* ]9 G; ^; j6 l/ u! S# m8 i% F- a& |* V
1 o' s4 J8 N1 D `& Q
合并的思想其实和有道题目的思想如出一辙:3 L' a4 a5 ^5 i/ K: S3 `) T/ P! S4 B
( Z( P: t2 t3 E" u, Y% {1 K' g+ A. c4 G6 A' ~5 _, \
( I4 ~1 P: f6 n; H3 @; Z
我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。 D9 h; t" s' l/ P, D
# K4 N* n1 N8 Q. z z! M5 q
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]7 B8 m+ P2 i9 e
4 i/ O, g6 F* \/ `3 F }! y
int* merge(int* nums1, int m, int* nums2, int n)
& m2 b( x' M: |- H8 g" i$ ^4 d2 V0 J{
( M% j( }5 {6 f int* arr = (int*)malloc((m + n));
2 E) E7 _( P* g: |/ E if(arr == NULL)$ y5 k) B- f: [' w* e: c: V
{) O' A; P( T6 j5 y2 `" o1 F/ v
perror("malloc fail");: ~* _- ^6 W) d& O
return;7 f' y: o6 A0 a- a
}
/ [% L9 R. i2 K% Y- i, S( C) h5 A! h( h& s
int p1 = 0;
& o, p, {! `( V1 A9 g3 G3 _, U int p2 = 0;
( M9 I, I% ~4 _) x int cnt = 0;6 G$ J' m |, D% o' _
while(p1 < m && p2 < n)/ o- c. f1 C( [: J& H3 Z( y
{
4 p) w- e- X: {2 }/ t: ~) c4 g if(nums1[p1] < nums2[p2])
1 Y- e9 d, }. m- }7 ^2 x) z' y {
0 N1 v6 \# v0 f+ r3 R# } arr[cnt++] = nums1[p1++];2 d8 X+ V$ k! E' d9 b4 R
}
4 [: G8 j; P0 w1 U" F! x. ]% Z else
: M1 \2 A2 ?& ?7 B8 E6 _7 b {
* e' Q: G3 c% d' M0 v6 N arr[cnt++] = nums2[p2++];
( e, @1 G' ?7 A6 u4 k# @5 E6 K }5 e0 l5 y4 ^; I, c8 b& U
}
1 l4 n2 |1 c+ x. X" U7 c while(p1 < m); Z$ h" E1 ?+ I" y
arr[cnt++] = nums1[p1++];1 Q7 l( G. W6 \+ Y- b
$ P" u- Y' P2 g while(p2 < n)
7 X, ]! K+ u5 @ arr[cnt++] = nums2[p2++];% b% w/ Z- D' c
1 v4 d& }' U/ j( p4 M6 w# i6 |
return arr;
9 h) J0 a$ I0 Y1 ]/ L* H4 X/ a+ g0 a}
/ z. E) u0 J+ g% ^) G) I: F9 K& w5 G! E+ D9 D# u6 u
1
* q o n% E8 D2 M; I/ T, n2
4 N- b6 [% _/ s5 k9 K/ p( t! q3
' \2 I1 e, Z" ]) D4 W: \4
+ M. Q/ F. o8 o5
d! N4 U( p( ^8 {7 x* c9 l6
! z, L. T& ]8 B1 w5 d7 e7 O; R2 J- g R! G+ b
8+ f ?, c5 E% v9 G8 B8 y
93 m8 C* `/ l+ b: Z
10
& v+ \; U' L) y3 u }- c2 {+ K11
, C6 Y O# F6 [( c3 F! e0 H& d12+ K* {. T9 B9 H" Y3 Y
13
% ?% @1 C; M* ?5 h( f14
5 P) p+ C: @+ u' K: Y3 w+ X15
$ S0 y" j+ m4 V7 y/ S16
7 k: d; {' c+ [) R! W6 G17
! l% y0 U$ V' u" P1 g3 {1 p% P7 h18* t2 B8 K# m# o3 E
19
& R6 D3 T2 I" O* U8 r& G" h* m20
2 _; A* n, S8 p21
. P( x& {/ @# H- x, X# S22, W; e- h$ |. U5 E, N b
23
2 K/ j% R! Q' i* |, w24/ h! ~) O5 s- b1 A: H" u
25
* V( }- g8 u) c! P& p t) V264 W+ A2 w8 J4 Q5 h+ q
27
1 Q* ~% {# u, [/ h0 a- q28. N, T3 K: {& k. P- E
29* V$ A7 E! l3 E7 l9 F( I: [
30( K" f% R: P- ^* j' F
312 j' k# J0 d" `# U- S
所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
3 D% G" o4 p8 d: b, p: Z6 T0 ?! O* Z$ k- i) A+ d
递归实现
5 t; v0 \! O5 U% J9 O O 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
0 q9 U3 e9 Z5 ^: A& W8 @4 Q( V; w( n8 V q( I& b b0 L5 g
1 i0 o' ~9 d/ H$ @/ z- y1 \, v8 v! C
' N) G* m; h( w) j" s1 Q
. O% t/ p+ E6 F" C) x- N; U0 L5 w4 Y/ x# g# _) p2 n
void _MergeSort(int* arr, int* tmp, int left, int right)
h- X9 F( H6 c2 \( g1 W: i{
" p- \/ B2 Q& }- u3 F assert(arr);
6 U4 n7 _7 F) F& c
# a$ w0 N0 _; f7 e- [. W l* h9 b if (left >= right)//递归结束条件不要漏了( S. l$ f- o. Q2 Y
return;6 U1 [3 j( w: N5 @% l6 M5 b$ Q
: t4 s D( R. k. p# g5 T. b% U. f int mid = (right - left) / 2 + left;" _, ?4 c* s N; G+ E9 v3 w' X4 y( o
5 i$ ~/ {. T, m+ K1 x0 G
//划分左右子区间[left, mid]和[mid + 1, right]
+ m: Y J. s# [( E: E) B4 }$ B _MergeSort(arr, tmp, left, mid);% ^: C3 s/ X0 y1 n( j, s+ _
_MergeSort(arr, tmp, mid + 1, right);
( M. P5 |7 v' |6 C4 z2 P1 o* r) X1 S4 C3 ^; S
//归并7 V6 F7 D3 X8 D/ ]& y$ C; T
int begin1 = left, end1 = mid;
4 a4 Z5 v. K# a; X3 { int begin2 = mid + 1, end2 = right;8 W2 t! f6 D8 K$ b
int i = left;( G9 h& L* b) T/ T) r8 _
while (begin1 <= end1 && begin2 <= end2)
% D! k. _& r6 t4 c/ ?/ U% @6 K" T {
" d6 e- q5 ]+ [3 _: X y, c if (arr[begin1] < arr[begin2])3 h2 y3 d1 F7 u% h* p' Y2 [
tmp[i++] = arr[begin1++];
# w6 ?& l/ S3 S9 C, u else
+ U+ e$ T0 W6 T8 ]3 i! A tmp[i++] = arr[begin2++];
" X h, O: T! d: C' b; s3 e4 ] }- ]# P! z) _) D ]/ C
' L: I3 X3 V! y4 l while (begin1 <= end1), J2 _ L" c9 d* i4 x2 a
tmp[i++] = arr[begin1++];
! p+ p3 m+ D$ Q/ }4 {" e c while (begin2 <= end2)
6 a& u. U1 p) }8 o! s. @ tmp[i++] = arr[begin2++];
( E1 |9 ]3 }- Z2 @$ S . I- u2 W! W, P6 F9 L
//拷贝回原数组——归并哪部分就拷贝哪部分回去
! m2 b* V( o; a/ s$ Q% o //而不是拷贝整个数组回去 |/ _8 u+ {! r' u4 _! i
memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
& b' u- J! I8 G9 X5 u7 A9 ]+ ~}" V+ K- n5 P2 Q7 C% s
+ v/ Q$ h+ ^* X; G2 y S, }
void MergeSort(int* arr, int left, int right)
8 `3 t% E' X! M c{- C1 U5 S4 R* \4 k
assert(arr);
2 M6 P6 W, h) n; o0 y$ G' d" a
* G. L4 E; v: `2 E% x* e int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
# x+ l/ q! L, ~, B: j% B2 k5 M if (tmp == NULL)6 ^- b% s- X' v2 M5 a. ]
{
1 }. i& i4 k G$ Z% K" ] perror("malloc fail");1 M8 u$ R6 w, [5 Y- ? j
return;
' v. p" E$ [7 e }/ r" W& I' X% l# j$ Z" ^) P& A7 a
; @$ f4 C- R- d" L9 [* L _MergeSort(arr, tmp, left, right);: [/ j0 S2 Q! ~2 K, C
. y( c4 x$ X( ~3 A! d1 B( u8 M free(tmp);4 x! z Q- D, I9 L1 N
tmp = NULL;
+ h$ v! L M! G% f}
& ~; M1 v& t( s& o
5 K+ {- t' e; p1 U0 {$ Z1- a. T# O; H% z
2
6 I- ?) P! y* h# c8 U7 c E* R3
- a6 q* q: o2 ^. @4$ p$ ]2 z9 `+ c
5# X+ y) ^8 |- W8 |+ B2 n- E
6
6 U g% ]1 X- L! N) Q; N7
/ r1 V* q/ e, e" p" B! p8
* i- _# N; ~0 Y i# T; ^$ A9& H0 x$ Q7 A+ N" b
10
2 G5 ^: G- {, i11) W# r# X% V0 G, g) S; y, C7 Q
12
5 C h& K( s3 e. P7 H9 f6 O/ H% r13
7 s4 ]4 S d7 ?1 _14
3 a B% ~2 c1 J! u" X" }15 v. y: P) V3 T. q
16
" v! G' u" x! y6 h; m1 W3 R17
W) P- A4 P M7 }1 c) u187 [* Y3 i$ s& Z' Y4 ]# b7 b2 ]
19, d# f5 ]4 t+ E( V
20' p8 f, n0 e* N7 _
21
; y1 b A" j: X0 C, R* H, ?# U22
5 X$ N; N( F. k/ C6 j+ V* @( X4 K6 B23
3 \" _1 p- Q; I9 W24 A! a D3 S( [ R% `- Z/ _
25
0 j$ r4 i+ h4 _26
, X, u% e! ]3 }# t1 K5 v27& s$ q, C( X8 U8 E4 T9 R
28/ @4 f, w. h$ N7 r ~& x
299 ~6 l0 F( V E! \" q- o$ L
30
0 A2 a q* `5 k: n31
0 r+ p1 E1 H% S' H$ j32
$ d" W1 p! T$ K/ V9 f- u% |33/ C" Y' G" c% P1 ]4 z6 p0 R' N: U
34
# k7 H( J N3 ?6 g/ L7 {35
. b* K! N! Q$ a+ k36
+ D: R. w0 i/ v4 T37
# m3 E% x4 ]4 S: w38- E) t3 M) s# A
392 p% d- X* K& B$ g; H6 w
40
1 w1 ]: N; c7 u! s41/ g9 q7 w/ i& ~" Q2 G7 c
42% T/ |/ c% l0 G! M9 E! }
43. b' h( }% l# l6 I& m8 \. y
44# T" @2 A1 Z7 f2 T6 V- @
45
5 e7 }% [1 J9 h2 p4 R; j46; D _5 C, k2 E3 J2 a
47
2 u% \3 B5 m2 x9 T48
- s& v( G3 |( W3 E( }& t7 z49) r% O$ I; D- P5 J
506 [2 B6 w" ~! M% T: O8 Z
518 n1 g, h; k* o9 F6 V% i
非递归实现
4 e, Z2 Y9 |0 s4 q 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。" |! k- U8 E- N! _9 n) @" m3 q
* P7 u6 r+ e# E
9 z+ h, L4 K- M& @$ T5 d% E6 P3 I3 c; A, A/ V' x+ b" f
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
( X) f6 F3 Q/ H( n' A, ?. G
" f; N: ^& w# _! |. u+ m7 D' g 还要注意区间的取值,每个区间就是一组,就有gap个元素。9 F& e6 r# ^" V6 z
. i* M& P, H7 v& Z
整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。* [5 {: t: D- p9 v1 I2 C5 ]
, ]% N% s( o. f5 t1 m" r# {8 r6 F
代码实现
" s5 R' e, g0 k! P) |* X5 |: m2 a/ _* ]& Q
void MergeSortNonR(int* arr, int sz)! K* s; l q$ Y& a: K6 w F s
{$ p7 K5 o( s' Y; k) Z5 K2 ^
assert(arr);
- G7 B2 D" W; x& | u. O/ Y6 ^, R/ z0 o" r. _
int* tmp = (int*)malloc(sz * sizeof(int));
& I' N* S$ C$ m if (tmp == NULL)
( C+ _% W# Z$ x {" H' p: p7 T# h7 s# `! Q) b
perror("malloc fail");# l, {: V: l' z- q
return;
, s }& R7 {5 s! O, A4 K }5 ?" n% B2 e5 a; ]0 r% Z
% T- ~ U6 K0 |; @ int gap = 1;
0 T" v( `- k. j+ L$ X: J9 R$ ? P while (gap < sz)2 ]1 b: r) e! {( N/ f& d- d& a
{
, ]$ M! R& x" D" {+ [# S/ @ for (int i = 0; i < sz; i += 2 * gap)
: T* {5 c. b& a1 ]- G4 v {9 s! v# N+ Y! L! p q/ ], u
int begin1 = i, end1 = begin1 + gap - 1;3 `. }* Y3 P4 P
int begin2 = end1 + 1, end2 = begin2 + gap - 1;8 S* G& }" t. C0 b/ m
int j = begin1;
; Y5 W9 b5 G4 S) b+ ]# E9 S" d3 b R" T* m% }# o% Z
//归并
7 E6 c6 B" h0 A while (begin1 <= end1 && begin2 <= end2)
8 V) z: x h) \9 A% ]$ L4 W/ H {3 F% Z" p0 Q$ k& }1 u) h) P; a
if (arr[begin1] < arr[begin2])
$ U# J" s4 [4 D, t3 x m7 c tmp[j++] = arr[begin1++];
0 g9 F1 Q' `9 a( T' Y( o$ U else
/ j& l/ F4 M( R+ x/ z6 f tmp[j++] = arr[begin2++];2 d( z. W! _2 b5 p. j
}6 c, T" J: S/ H/ a- W
4 j$ v+ Z: e$ P+ x% _
while (begin1 <= end1)6 P. h# f" a2 ?
tmp[j++] = arr[begin1++];% h/ q' ?' ^# `! n( O7 s
while (begin2 <= end2)6 f( ^7 C2 h& E2 j
tmp[j++] = arr[begin2++]; i8 R& G: ?+ \! W; y) w
3 d( `/ d& a; F9 c* Z7 a" ]8 Q8 B //拷贝回原数组——归并哪部分就拷贝哪部分回去4 q# F. C6 m. G) V0 w
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));+ j( `, J* V ^' P
}, ?# {' J+ K$ Y! A7 k/ M3 m
gap *= 2;6 @: F+ N; J/ {0 ~" `
}" j" ]' m8 ? G4 q1 r4 `
7 A+ } M M9 _
}
; D, Y! X' J9 K- G
4 k. N! ?# \8 e: ^1 j1' {. C+ Z' s7 r: r
2
. g: S5 S5 K$ B* O2 L6 @3 |3
* M! e0 c4 S' K) ]4, {% V6 k+ U( q0 \5 [5 Y
5+ l4 K/ Q% G1 k
69 n0 T( D+ C' J/ K( }6 H
74 Z( O7 u g% H# i o$ M; q
8+ i- T' k. }0 m& Q S; ~$ m
97 S& |% R/ x. c- t. v9 n+ D9 T
10. {6 J+ ]7 N) B
11) p' o. q1 G% e
12
# O# R* ~% E4 z+ g6 o& N N13
( D2 F& L* J% u- |4 h0 J+ e14
9 a+ ~; K, |- W4 `' r8 _7 v. Y15
+ H3 c' N: q. j2 o; |5 M) H16; K5 E$ Y- E" \& F7 H
17
% f6 P. `) n1 L+ i, v, {' t3 m18% r) Q* s. O0 N* J/ I5 E3 O
19( x W a. z. x. G0 ~1 r
20
) k1 N5 E8 l8 m0 A0 X. z! U21
0 R8 b0 x4 M k8 {22
7 S( K7 g s& M6 Q/ J23* {+ p! @$ a+ I( G
24
. E8 [2 Z" X; Q25
. j. O: m+ y) w' s26. |3 ]$ F" H( a# \) y& x$ B) _6 ~
27
5 j5 d2 p5 ~; d0 @/ G9 a B7 Q28% S; Q% W+ x) C
29- Q6 e. q+ k' }% U8 |
30
1 u2 l" Y; @+ E, N318 H. ~: A* n& x$ L
32
, O8 h# G) _# L/ n! S33/ g4 v, }. \9 `4 n9 D9 P& R' H" r+ W
34
! C4 }# J5 B5 \, \( G35# W4 L ]7 S$ C, \1 }+ t: O
36
6 c6 K* z: a% H+ l373 k1 A1 a+ {3 t6 B
384 y |1 n8 P' E3 i
39
+ U! M2 l' b( E7 `( r40
3 c- z8 R3 v) N# [41
# U& p9 X2 n$ a; h. R% E边界问题6 b9 k/ e4 F0 ^
实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
: J: y, P. l% x6 f2 d) D/ ?# U
, R% C/ b: k2 v" Y+ b1 `- n& A举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
4 Q" C$ _9 f7 u0 q) T4 ^ D8 T
: o; v" ]( y; g- a
6 ^2 `3 J% n& Y8 T3 e8 ~: m0 o; F' L$ Z# B: M
由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
9 K4 Z) F6 F4 L7 C; Y) O
! q& R" W+ r; m9 G9 K0 q第一组越界(即end1越界)9 G9 f. B& M4 n \, B
$ y. p4 ^ k) Y( _" f4 ~) j% Y应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。( ^9 q5 g9 s, O7 [
6 M9 F9 _& r7 o/ f! {8 G
第二组全部越界(即begin2和end2越界)& V7 D {8 S* ]9 ]( r5 N' Q
( L" g6 d2 t% S, @' G7 ?应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。- H7 \! ]- @9 J, F
% m1 F) Z+ y E5 H
第二组部分越界(即end2越界)
% R" g' ]6 S% G
: c/ ^ e' H; }" r3 D/ l; f6 z+ A! d应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
4 c3 B- n, e4 x5 t1 o E& u; Z- }" T* ^8 p4 z
其实第一种情况和第二种情况可以合并为一种情况,原因:* {: Z( _' X6 g% A8 J. \( p1 |
a/ }! o) r" z* j0 v
end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
. S' R b1 W. ^8 u! E
! y8 K G2 N$ ?0 f6 F9 i 拿两个数组试一下:
2 n% |# E3 y' e4 u3 [2 W+ o/ E( Q2 k6 H& L) y1 j: W8 ?- r" F8 M E+ d) ~
" {+ N. F- ]' z' h- d# r) s8 {8 V* [8 Z# h* K: z+ X4 s+ R
, S! c% j2 P: r6 q
2 }! d7 Y) _$ C. B代码实现- r) t3 ~" L4 b$ w
: Y$ D, `. H9 X! F1 ?void MergeSortNonR(int* arr, int sz)
' n7 n! Q* c& E1 R5 E{
* W3 S0 P$ n$ H" t+ p/ t7 w+ {/ d8 D assert(arr);
3 ^" Y6 I% i- s% z
$ C- c0 P* x. H) r$ @, L8 T int* tmp = (int*)malloc(sz * sizeof(int));
/ X4 K, h* H- g' d5 I if (tmp == NULL). G/ n- Z+ J0 t4 B
{. g+ c+ k+ c' ^- R2 P% q
perror("malloc fail");8 ]8 G9 i% r% A; ]& H
return;
* l. n3 Y3 I3 \2 ^# I. k }
1 }. G5 Z$ l, s' n, @' ~' V& y' N0 \8 K0 j+ c9 }; |
int gap = 1;
$ J$ j3 o6 I5 q1 U6 q. e! m/ O while (gap < sz)
2 J6 }8 R( l* n1 `+ }. C {
$ r9 ^2 M; f7 C; L; R+ e. v for (int i = 0; i < sz; i += 2 * gap)
0 F9 C6 s. k/ n" G; V {
' Q" P3 i+ k# k# j- K% p int begin1 = i, end1 = begin1 + gap - 1;
1 H4 r( l# n) P; m int begin2 = end1 + 1, end2 = begin2 + gap - 1;
: e9 s& O2 h- L) R$ | int j = begin1;
' V* i$ `5 |9 A8 b+ f N) `& ^ //越界检测6 t3 q: k6 I. ~+ q; t
if (begin2 >= sz && end2 >= sz)
( c, r/ E( h7 J% ]. U break;
- F. d- Z; G- j! A# r. E if (end2 >= sz)
z: [1 ` K$ y7 c" b end2 = sz - 1;
2 u$ _- u1 @* N2 J //归并
, l1 E& R& o3 R. G1 V4 H0 Z while (begin1 <= end1 && begin2 <= end2)
/ m/ r; h' m" r! B- n {
( r2 i( H* X) J6 C y if (arr[begin1] < arr[begin2])
% F) ]9 q. W$ ^, c. F0 G, K tmp[j++] = arr[begin1++];
4 D& A e9 k; A else
. G0 p0 S+ O% k7 G2 @ tmp[j++] = arr[begin2++];- C2 O- d6 g/ Z3 x& Z+ H
}
Y, R: u; ?/ P3 q" K
- y8 N- O9 v7 O while (begin1 <= end1)9 P% C( g: s0 z5 L8 l8 p) w
tmp[j++] = arr[begin1++];
& ^5 |( s+ \7 z5 q4 Y F% ` while (begin2 <= end2). B2 o! r, M4 e2 |& z( l. _1 Z
tmp[j++] = arr[begin2++];
! y9 s/ T8 N3 \. A5 Z& i' r, y" q2 k
//拷贝回原数组——归并哪部分就拷贝哪部分回去2 K. s# G8 D4 z7 E3 X* d2 Y+ O" o2 o
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));1 A' Y; M8 w! w- ~3 T* w9 v
}
5 f/ i% I' y# }, E3 U gap *= 2;5 H8 c. x0 Y( H, ^' v$ l
}
" _) b3 \% _ L4 t+ u! l# Z1 G7 ]0 W: t; n) T- X# T
}
' ~9 @6 G0 H" D) f% U
3 G: j! B j! V ~' F- \1 t1
& }- j8 G( t+ u( ^/ H: p7 a6 I+ \2
8 l: n5 O' C1 b! s" Y. a4 `33 T6 p* W7 f9 |
43 T; a% k2 I, O) O; J5 |, z
5" n3 p ]4 t' U, K9 ~
6
2 E7 }: H! d0 ?1 ~! G$ ^7
/ n% l0 r* i9 j: `& c7 Y3 o8 j2 [6 l1 L9 \. ^, k9 i
9
: C) S, ?" P+ z101 @& o7 |+ \5 {8 ^* T- a, T* o
11; p1 w7 u' O7 p3 O' |+ z* k9 _
12& N( j: y+ X, R
13: {2 Y& r e* e" k. T
14
$ o# f8 b! F, K15
' J/ [, p" Y& }( b' q8 L16
g# F7 _% A# F) b/ p# `17
2 i) n4 I8 x! s18+ d* t, q! I9 p2 g) e
19+ Q2 Y' o/ {4 ^- L Z* }: h
20& N6 Q: S3 a4 m4 z9 A. `
21& ^1 v& n5 X" x! }" c0 s1 S& ^2 w( j
22
& k4 g `- A, x, q23
+ A3 @; u- M& }7 |; ]6 ]0 P' r- f24
* S, M& O* z- R- Y25
! Q6 E/ g# x8 Y) e+ Y: K26/ O! e% d7 a) b) x8 h% D( ~
27
4 n3 y$ Q" k, i+ g3 Z28
: m4 ]2 n9 K) Y29
0 K$ C' ~9 z7 B* M/ Z# _$ V30
2 J% d5 f6 h, J: E7 r3 i$ N1 T31
^- S3 Q e/ D32
/ X, T/ N/ M* R& E2 @( c h33' V7 [. [/ {' y7 b: ]
34
2 `8 T& J: p) N: P1 S35! C1 w2 }# \3 z# H4 V2 ?* E2 J
369 x5 s# f, F, C9 x! n
37
3 q. T$ O9 l6 z& [% r$ V, b38$ I% M! i; N$ w: `
39
! L9 R& o: @* j. {40
6 [4 j- h9 k% P- S* X9 A, X41
4 O5 J2 r7 q; Y; \42) f. \8 a4 V% m8 u9 N1 E, h
43; ]* R) a$ d8 [& h! K
44+ ]7 l, W8 i5 q/ v
45
7 `/ F! Z, q1 P& K7 ]) ~4 c! q6 |" e归并排序的特性总结:
) d" ?1 T* S0 h; r; L# Y0 Z+ r* Y# i- r$ S! t- h
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。' B* s) o6 _! b2 F+ d7 Q5 F! U: l
时间复杂度:O(N*logN)
! d8 S0 K( [+ j( h空间复杂度:O(N)
* u0 n* K5 A/ A w- F, `! h8 f稳定性:稳定
2 a( ]7 s$ Z/ v( n
5 P4 z! z5 x# j( K. ~————————————————! l; \$ P) [3 }: I$ s! T$ j
版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
$ ?. o# L; p% O. _7 z原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657+ Z( r) ~8 L0 A4 |: e, |
7 s, m0 E+ h0 E6 \" m( D0 V5 |( Q
: U& u6 h$ w8 G' g! {, J |
zan
|