- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 554677 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 171776
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序 f" U7 r1 U s7 N$ X
: j4 E( H$ o( P- \
前言4 g5 e3 U* m! o- E3 |! A; O
本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
2 P( {3 `( n5 p/ e4 o) d7 m
7 x: H( c0 j/ ^) m5 t归并排序1 ^9 ^. b I8 {" F- B# _* X
基本思想
" R1 e0 ^; h9 t& y4 g 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。8 u! \# F* W8 w
! T6 D8 [0 ~" K8 C, y8 K# [7 ^$ V9 B
0 ^1 E+ `0 O* i2 P) ~3 O
: U8 @9 m# p' z! s" L ?' Q 合并的思想其实和有道题目的思想如出一辙:9 C5 r9 X! I# X5 ~( z- a$ i: {
7 S" v* } {- Z$ D8 t, S
& _2 j+ Y& e! v9 `" u4 J
5 T: E' o) B! A5 ]( c 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。, Z( F5 j0 W) S* b7 ?1 C
8 K# \% y7 e1 j- V6 O$ S O! V
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]8 q" e3 U) g6 j8 S) J: ]/ O
3 h, w0 v0 J z5 d
int* merge(int* nums1, int m, int* nums2, int n)- o |: r, [4 q) F& O1 s9 h
{" j% `/ ]$ h" e0 x9 b. u3 P! i
int* arr = (int*)malloc((m + n));
% m9 }! H& _9 S# Z; J if(arr == NULL)' s. b3 _0 r* C; I6 Y; ]
{
: O' V {, h5 D9 Q perror("malloc fail");
0 S3 l+ }2 A3 K. z# ? return;
3 R9 ^: p, }. }, P( I; F N }
( ?9 ^3 O& D6 b5 n8 C4 ?0 X" d! P
2 H0 g. @# }3 X& d, D6 H; L g: j int p1 = 0;3 ^& _6 c, j1 b! J- y; b
int p2 = 0;
6 T& Y2 s S# u. @7 {) q int cnt = 0;: J7 i# z2 j& i. R# T( P& I' ~
while(p1 < m && p2 < n)6 A* @4 f/ P9 f8 w9 @/ z
{2 a7 t ^! V& N# F# v
if(nums1[p1] < nums2[p2])8 _, @4 B8 B4 `7 F
{
% `- u0 W0 S1 T arr[cnt++] = nums1[p1++];' r. D+ \/ c/ I+ G B6 }
}
0 s6 b) l$ A; G6 W* A0 F else: [4 L5 j( q0 g7 r3 ~1 q7 M
{# o) V4 k! |' f9 }# _+ c) a
arr[cnt++] = nums2[p2++]; e: H: R. F% t5 R
}" e1 g2 L9 g+ w# J
}& u+ v& ]" l f; k6 v
while(p1 < m)* J0 E0 n; k/ A4 r8 K2 P+ S2 z
arr[cnt++] = nums1[p1++];
- R }* D: _. _9 X! S
; A! {) J7 j6 Q a6 [) O/ V while(p2 < n)
7 C1 X" L4 N6 b9 J arr[cnt++] = nums2[p2++];7 ^' d( k* [& F8 ~/ W( |& A
j x+ L& R# N$ H. Q& y return arr;3 Y' B! Q+ C( u: h1 {
}
* K- u2 ~" F3 o7 r; F( z2 C( ^8 h1 h* }" G
1$ t) t4 t4 O4 V3 j* W+ k
2: f9 @- ^! o& B% k: H% h! l( L+ p
3
5 e+ v1 N2 ^: R4 P! p" ~: J( L& G4
: {) @$ ^' s' j6 p59 | i+ |% j( @5 p3 }
6
8 E) u$ {( _6 b" j- @7
) d: W% B; B, ?9 h+ R87 G+ N" A/ _' [- r
9) l7 ]4 j" T; J
10
( S2 Y, k0 S/ j0 t" V: `* f" _11
7 k: D. |3 z+ o3 w12
( _+ f! Q) r" A0 T$ W13
% |0 T( q8 B* D. t. h14, {# R6 `% A" W) x- i3 u
15: l" r k# A7 _$ ~* U* f4 E
16" n& I. U, ]% J7 z, ^5 k* A
170 ~$ Q. b+ ]' A. p! R6 [& C' I
18+ T0 b8 w' j' T) E& ?. {
197 ^' h- S, \8 T+ q
20
& V' E7 m- f* Y3 Z. X% Y3 R4 j21. P3 t- B7 @- q7 o% t2 F0 C
226 q6 N( A3 Q" B2 m
230 _( p, A, R9 n) c& ?/ m
24
9 j* D! W6 { ~2 k253 A2 z$ h1 ^6 w0 A
263 h* U9 l+ S& M% m* S
27
$ T/ a' B5 Y$ } p, [: Q28
" f$ U3 E! N( q: y29
. v3 W6 ]4 F) ^" y7 H( e30
3 r& G$ f/ N7 q1 c, f8 _ {) c31
; ^$ D% v& R/ J S0 |4 ~ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
; i6 I1 l3 e5 Z
1 a1 }( B+ m8 c* \, V! o8 K递归实现
) F: `' r) P' R- V 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
4 p z" H9 j- l0 n ?' g6 b. V# Q* U# ^2 {1 u0 K& W' N
0 I$ m6 c' R/ V; S) D
2 n& D2 D: b3 q' \! Q6 q
- Z7 \4 L1 j b
' {/ b7 a* J5 g6 Yvoid _MergeSort(int* arr, int* tmp, int left, int right)9 w5 I* [7 O! Z* d$ v; i+ f9 @
{
" E4 h3 k5 I* e% c1 W2 R6 U assert(arr);
* J: Z, I$ N% L }2 Q: z3 D' h& p2 P
if (left >= right)//递归结束条件不要漏了
6 u N# q8 N# j return;
1 U$ O1 o; M' S6 H: {8 \) @+ |: s4 D3 P: T/ \- [
int mid = (right - left) / 2 + left;
4 S l7 i# S' Q! N4 T2 x0 K& }- H. P1 S5 q) O: M: S9 j
//划分左右子区间[left, mid]和[mid + 1, right]
/ u4 W# ~" Q# g _MergeSort(arr, tmp, left, mid);6 m; i* r) A% S, W" G7 H
_MergeSort(arr, tmp, mid + 1, right);
: d. @: c: B6 @" |4 _' S, x( P! \+ G
" q% ]! P F( Y. U //归并# @9 T" E$ g5 w7 P" ]; w4 U, w( A
int begin1 = left, end1 = mid;
8 V' i R, d! O7 ^ int begin2 = mid + 1, end2 = right;" D& ]$ Z' N r
int i = left;2 D; Q* t8 P6 C+ x6 _
while (begin1 <= end1 && begin2 <= end2)' h$ D9 D9 K$ R" i3 |* X
{
0 [( l* R7 e+ c7 h* c$ B6 Z# F if (arr[begin1] < arr[begin2])
: Y8 P* L+ o9 e; \ tmp[i++] = arr[begin1++];
- m1 Z0 h4 T9 l else
( X' j D6 {" W: r7 A( A tmp[i++] = arr[begin2++];
$ F5 ^6 }' `1 ?% p }
/ ^' \' u& ~& j% m" J9 i4 c5 Y' ]
: H7 ^( C9 j# N; ?" f; t+ r while (begin1 <= end1)' N5 x/ J! h: w5 \- v5 I9 Z/ Z/ r
tmp[i++] = arr[begin1++];
2 U& a* B5 `6 M/ y A& o5 n. {8 d while (begin2 <= end2)
+ n8 l# I2 e& t, Y& q3 ]6 ]4 I tmp[i++] = arr[begin2++];
# M, V! r4 B5 o6 t' ]& [5 D
; U; I/ s7 N- A+ Y8 t5 E4 x //拷贝回原数组——归并哪部分就拷贝哪部分回去
7 J0 \% E# I x" G. q& B" D! l //而不是拷贝整个数组回去
( @5 t% v6 \- ]8 V2 y memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));+ W, t- W2 W9 V8 s* h* S! Z
}
1 O v6 T5 B8 Y* \
5 X0 s+ c C) Wvoid MergeSort(int* arr, int left, int right)1 i d9 o: x: S" s
{
- h& i$ p2 P7 G" D assert(arr);
. C+ x/ W8 [& {, X/ ` b
m7 O B, P k int* tmp = (int*)malloc((right - left + 1) * sizeof(int));! b+ | @; {6 _2 V- v
if (tmp == NULL)
' N/ F5 f, d# ?- [ {1 }) G% C- l9 T, `9 @
perror("malloc fail");, W0 p( ?1 u7 W% s# J+ j# \; ?! M
return;
! Z3 s: S% _& `7 o! b& d: u5 ~ }
* r {4 { @# ^; R% |3 t
' W) W7 ~. z) X _MergeSort(arr, tmp, left, right);! v' q N3 X$ X1 k
" |2 i4 Q3 \5 t free(tmp);
9 l' s3 U; g: ?& n7 @ tmp = NULL;
( G2 g! R; c2 s}
$ k. z; Q2 Q0 L A/ c8 v6 C) S' b$ @1 a3 v9 o' h
1
3 R: E- B0 v5 t4 S* ]+ [, O2( {* t' j2 Q. N" r1 T
31 e$ n' a! C. L3 [0 P
4
/ E6 y* K/ Q1 V+ B5' G `. p8 x+ j
6% k M2 X' E2 A3 L' ~ C
7! ] U* G+ I( ?' ]
80 I* x( B5 t4 D3 q# k0 G
9% g3 s2 `5 Y2 K! C! i9 ?
10: F1 k" S) l( W. p) P
117 S0 v+ ~. ?. D' r4 a$ y
125 `- k$ x1 X6 b5 A# t) G0 R: f3 z
131 r# P# @; F4 U6 j) _
14# Q8 b4 s3 F9 Y3 c. A! X$ R
15+ G; `6 z: H ]% U2 i# Q5 ^
167 a; _& t$ K7 P7 I5 N
17
( k' T6 H9 o% ?3 c$ M18$ | s2 X- Y, e& s- x
19
' }6 u; R: h8 e6 U' z5 w2 M( `+ r202 [7 q d. N, m' `, ]- F! m
21
1 A1 {+ @3 }* q' t- H22
3 S; D) W t2 @5 a234 W' N* W9 A$ j
24
5 \# [' y& u1 s5 i, n251 l% @' z" @) P R
26, ~1 o" o7 P0 K* m
27' c% U) u. u+ X$ S6 l: f; I0 o1 t9 S
281 V0 {8 z4 |5 X9 z' E! U9 L
29. ~+ U1 t6 F) ^4 p9 \1 Y3 X* v" ?5 R
30
* h; j9 q9 u8 v+ O1 Y k/ T31
! t) }) H% M% }2 v. N* t32
* ^( n( t: w9 f3 G6 W" u1 D336 G/ T/ @: E8 D+ H- f
34- j& z S7 g6 S& Y6 c$ U6 {5 E2 _
35
4 D2 ^8 {; \( [- d' n36
; z" Z( V( R' \9 q/ ~0 n2 R37% d/ L* G5 w( A% E5 G! s5 c
38
1 g# _1 z- ^! h* z+ D4 U! J# X39% i* m% n( I5 J" O$ \3 x7 l
40
) Q. Q, i- L7 m- V: `, F5 a41
" m# G- u1 H/ l) i5 x8 c9 Z9 N3 s0 m" K42
3 F9 O& }4 o- x! R+ i8 B3 L$ r' O" W, e43
& ~) b( ]& l" a, z/ E& i: G44! G: z% a; I+ B3 }/ g) i
45
( u0 p% \- W# D46: J B! m h" r
47
& j" {# ^: ?( V2 y0 q, ]48
/ e* X5 k3 B8 v c* g4 o49
- k2 m5 k ?- B7 A1 m( w50( Z' Q* d- i1 r! U, ?
51) _5 l: V0 h6 S% t
非递归实现
5 v) S# h- E& k h( x 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。3 m) [9 q% M e
2 m% R9 Y. M: a0 F1 H; ~, x! G3 w
4 M& P9 g) Y, E* t9 V9 e$ z3 \( W# a- f V3 g, z- ^7 _+ f
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。, J x8 E$ z2 _7 C
# ~+ ~6 _& O' x9 c$ ^, Y 还要注意区间的取值,每个区间就是一组,就有gap个元素。
+ @8 T+ m+ o4 ^$ u" ]! O. P( Y2 ?( N# L" L7 E# y- p6 E
整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。5 P4 @/ F" z1 G3 J- V5 q9 a
, }& S( }0 E# l3 s5 K8 Q! ~4 B
代码实现
) I3 L1 @. b& p4 q# T" l6 ]/ @ E/ v* i1 E0 w6 W9 w
void MergeSortNonR(int* arr, int sz)
7 m8 e: P) k& ?* V. r: F: M{
# F. l% }0 b/ n3 N% W2 _ assert(arr);3 u u! ?5 D7 F. }, o( a& w* A. O
! `+ k6 R4 @- x) m- y int* tmp = (int*)malloc(sz * sizeof(int));
/ V2 o( d3 w( |5 l' p) R5 G$ v if (tmp == NULL); x2 x1 k4 N) D$ B
{' j: m4 y8 X9 M+ m9 D
perror("malloc fail");
6 {. X% o* e6 d- J return;" T! m5 B5 S- ?$ Z
}
) u) L, W% D3 n8 U+ [
6 y9 y& @8 o. i l4 R5 H int gap = 1;
* w# ?1 a8 R2 X: k ~ while (gap < sz)
! h2 d/ z" L* C7 a {
0 r# Y4 G# Z f. e for (int i = 0; i < sz; i += 2 * gap): w+ G9 b7 E5 t. X
{; h, V+ B; P/ B+ Q
int begin1 = i, end1 = begin1 + gap - 1;% ?8 O" r, g3 c; J- p' h5 P
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
" ]. ?- ~9 r; u0 y int j = begin1;$ t% K4 U4 s) d9 E C
* v& s; Q& L+ o0 A9 ?4 P) o: m
//归并0 l1 N1 V8 {; J+ p
while (begin1 <= end1 && begin2 <= end2)
& C+ J3 I3 T0 f }" l {" T; \1 q0 }5 {: `% f! e
if (arr[begin1] < arr[begin2])/ N7 g9 i, {6 j) i3 r2 G
tmp[j++] = arr[begin1++];
( Q4 k6 J) K1 S7 a else : x. p3 D. o. L) G
tmp[j++] = arr[begin2++];% F9 r6 ?* x0 l: U
}
' ~# W8 @# J! X& i- P; K* z5 ^( G) M# o! w: @, ^2 p$ ?' h
while (begin1 <= end1)9 v& a( T% w8 T: e2 S5 [
tmp[j++] = arr[begin1++];
) f! n# x0 E3 ?- m. r4 i# k while (begin2 <= end2)
% m" y8 B2 D2 Z& e3 E) q: q tmp[j++] = arr[begin2++];5 P1 b- r* W% c/ E
! _9 v5 k! V# A* s n& N //拷贝回原数组——归并哪部分就拷贝哪部分回去
, [9 Q& @4 S: e memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
5 l8 c6 ^; `$ X: g' O, v+ m }( ~/ a) F5 E, @( K
gap *= 2;
1 |) c. k; \/ Q R- M6 X }
/ D* W3 {. k) J' I* s! U
0 T5 R, u) A, l; i$ E}5 X+ p1 V+ S% G2 G- n7 M5 _4 Y
8 c) @* N) N) I, `# Z; m
1
) {& R) Z1 {2 d* @# V2 {' I% { v3 M2 d6 P$ S; p
37 ~& `; D; A5 W: a" {9 f& e
4
; V: p; d+ R$ a$ t* u' Y2 M5% ^. w+ i9 H) _
6
% C) t _( p$ x! s. a; v; {7$ F+ b8 E) B) n: D
85 B' `: k3 Q8 J: m, ` f$ y
9# m, N/ @" X& `6 h4 P" a" }
10
' O4 r# n J& a& P5 f; g$ I11
, ^5 q0 O+ D& M1 z+ J% f- U12" I" P, e, p v( T
13
& m d5 q2 t6 S! V9 V Y4 c14- [' t3 q/ r6 ?
157 @: u- Q: D6 }% q
16, ]+ @6 Q3 A/ F: G
17
0 r0 z! L3 P6 A. C2 G181 s9 H8 g" ]$ W
19
* w7 r8 `: ~$ ~+ u0 ]4 n20
0 a! k P: N* M1 b; {219 q2 |5 U, Z* t; D f
22
; j0 X9 _9 Y2 {9 t23* r1 X- e5 q7 R+ w5 \
245 t0 X7 B; d7 U2 ^2 v
25& U+ x2 l0 ?1 K! E0 s
26
$ `3 a- F1 f0 V& U4 [! {27$ |7 t+ Q2 n5 ^0 ^
28
# G0 V% z) r$ Z- H. h) k29
L8 v: C+ p. i! Z' S6 e9 D30
2 @7 g g3 d r. O. \9 a# _- c9 Z31
2 \2 q5 p- c9 \( d* L32! a7 H7 m0 f, x
33
; a& E" H: [% e5 j34
6 L! |5 s5 g3 n. |2 {2 r8 o+ U9 h3 }35) m; P7 X* e/ s+ U. V+ E& V2 Q9 q* b
36" c$ t; \( K0 q2 f: m& ~" }
37
/ \+ g! ~; f7 _/ H38. |) q! b4 A9 I. a
398 l3 }1 m) c( y1 j8 [
40& _5 ?2 |/ j- J! S- r6 P- w
417 F2 Z2 E( [6 q3 z0 f5 Z$ u
边界问题$ i) P, ?/ j6 D
实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。$ Y; u% x7 K- R, I; }! ?# ^
1 {( d3 i# F5 A; b8 U举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
7 C5 g* ~3 }' ]0 o( k, u e. k* h; d$ f+ x2 L
$ E( @" h. }5 Q+ P; a
; q$ }! s2 {/ g8 x; x, F2 Q
由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
/ [/ V# \# f/ h: p& [8 x3 x2 t2 A, e0 _, i0 K1 }, Q3 C8 _
第一组越界(即end1越界) R5 e; t8 N, w
( {# h' e. L$ F/ @3 I, }
应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
9 u1 G7 U7 g* u: Y
- R8 X) G- M) ~5 W第二组全部越界(即begin2和end2越界)
$ h: z( N* B" K9 Z5 [/ b$ D) b$ I$ f4 C3 i. C
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。0 g& l) b! G: \
+ U/ g1 x1 z |0 Q. b第二组部分越界(即end2越界)
" g6 z0 d) N$ R* J2 Z# y7 X
- r7 i {3 p1 |$ r3 ~应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
3 q, ?/ s2 k, ?( {6 P; u
# v0 ?- u4 K* u 其实第一种情况和第二种情况可以合并为一种情况,原因:$ | R# w/ |8 n' M. G ^; U
, G7 j: T6 C- M2 X+ K end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。2 I0 Z9 A7 v# a* I5 ?- \$ a" K
0 r3 }6 k- q7 p" R6 f 拿两个数组试一下:. @2 N, y I& }& ~
% h* ?( I( Y$ F) e$ w
! B3 {# q/ @2 P' ?1 r# o
; ^5 s& F, f; B) R7 b1 r( \
+ W/ p6 R& b& l8 [: x; ~. U. `- y0 M6 [9 D
代码实现- u! l5 w) K$ a. |" M( X8 K( Q
6 Y8 |4 r% V/ g: b) Y
void MergeSortNonR(int* arr, int sz)
0 E" _# C* _$ T G4 x{
# s* b/ w" p- ^8 | assert(arr);, m2 T. e' @: O0 [$ h- k
; n H! B: i- |' D; I+ h int* tmp = (int*)malloc(sz * sizeof(int));
+ j- m( X! o$ j1 J2 R9 \& c1 _ if (tmp == NULL)5 b) }7 D# w" z
{- k/ p4 X4 @ @; S* M- W
perror("malloc fail");6 T3 S0 _ R8 d# n, O
return;9 B9 t( }5 s# Z u* r
}
9 I! Y# d1 ]9 Q; [. b6 o) Q# c( N
int gap = 1;: C" g9 ]0 k9 S2 Q7 n
while (gap < sz)
9 V5 U! ^" j) j$ f4 H- u {
7 D' B$ n# e& G6 Q for (int i = 0; i < sz; i += 2 * gap)
: Z) O5 s# h+ U$ E! Y {( g* Y0 D' G8 O: T+ S) U4 F
int begin1 = i, end1 = begin1 + gap - 1;
/ W$ ~1 m. V O) E int begin2 = end1 + 1, end2 = begin2 + gap - 1;4 e8 S4 w, |& ]: O/ ^; [! h
int j = begin1;# M0 m$ u/ q$ r
//越界检测
7 ]8 T V8 O' ~0 ^! K+ } if (begin2 >= sz && end2 >= sz)% n0 v9 Z1 c( G, H) J# v6 R
break;9 e0 Y! Q9 T2 Y
if (end2 >= sz)9 A# z' l5 |0 @ V
end2 = sz - 1;1 y! V* f' h3 b. q9 y' d
//归并$ ^( E. F' U# i
while (begin1 <= end1 && begin2 <= end2)7 d8 p7 L/ U" Q# a/ ^0 J
{
- M9 w. o( M; U, H( [ if (arr[begin1] < arr[begin2])* }$ C1 U7 }1 I! A1 r+ |, {
tmp[j++] = arr[begin1++];
+ M1 T6 t+ [* y8 m$ `) W else
/ Z- ]& _" I% P5 X, {1 @ tmp[j++] = arr[begin2++];. i$ N( r* \8 T- U2 e
}
$ s' k; j7 P, r u/ B$ F; T& f0 q$ g+ Q: m2 `3 v! n9 B
while (begin1 <= end1)
1 @8 a! d5 I9 F tmp[j++] = arr[begin1++];5 V8 A. x/ a& `, w7 s2 V
while (begin2 <= end2)
Z/ b& ~, t% i; E4 k5 }) N9 K tmp[j++] = arr[begin2++];
' V/ f1 S! f* R
! O6 e" _) s8 @ //拷贝回原数组——归并哪部分就拷贝哪部分回去4 P; X& e& m; w! \% z
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
/ U% N1 K1 ] I9 z' c( o0 i/ B }
1 Q% s r$ v6 ~4 f gap *= 2;* v6 u3 C- \7 I1 r# s9 f1 @
}
4 L9 V! g8 c' `; O5 ]
/ M, P: g0 ?4 b; j6 A$ ]}
7 k# d; N ~, V, G. C! d: C. { \6 ~
12 D* \* Z7 w' V* g# c8 |- G
23 H# x* D/ m* k* f, F# Q
3* t& J, N J% F* E& E# C
4
! s' V( k" F, V5
$ W- d4 r$ `" d P1 t; t% e60 ?4 B3 b7 k1 e) w
73 e: E [3 K6 i: j' L# G
8
6 R# p: ?7 ]5 o6 Z- i5 h9
$ m( x! D, z; f7 _( v4 k10/ F- @ P/ t( o! v' w6 I4 S7 K3 o
11) l0 H+ Z3 P) N% q ~/ d% q
12
6 [/ M5 S8 j2 t3 @3 v13
) t$ L) Q- o0 t# [' `. g; b14: X6 g. v- I; |% k7 W/ f
15
( A1 T3 f& o+ U8 f% Q16
; }8 {3 T6 N0 Z) r( R17
8 s' L: M- x/ L( Y2 Z* A18
" z3 Z+ V- F& r193 Q6 r# @+ ?8 h( A; `1 @
20/ B: K1 `, Y5 v' O
21! J# U9 ~( m. v7 ^1 _4 y
22
& g# m7 _* G- q4 z5 t2 g: }, J2 i; ?' S: U23
* U# O/ `0 D6 V; a+ j8 |9 z& [2 w24
2 l- a0 \) x: `25
* r+ C) r1 N! E9 H6 F& v8 Y6 a26/ m4 z; h) ?, s( S/ Q$ |3 Y
27
" w7 s- \, W# _5 ?- L282 A. ^. _" H3 E
29; A& P" F2 s3 P
307 Y+ s. t) z; _6 `: h2 F+ J
31: U C7 A( T) c: V7 |! [; x
32
- u! V Z- c, Z0 N- H8 F331 Q. q+ o% l7 B; P
34
) S3 ]; V. ]* S7 a354 Z# R3 W/ M1 I3 b# g& Y! X
36
5 A% g3 w, D8 x, O37 P0 z8 {. g3 d1 P4 J# S! [
38, A$ H7 _. D% X- P. e9 S
397 s+ m7 M( x }/ `- ]1 Q, M" }9 Y4 \
40: s$ c9 q7 A# b4 N
417 B$ N2 j& h; ]+ H0 `8 ^; l8 c
42% `& ^* }/ n1 U# W" B& x
43
% d7 |1 j+ M4 }8 k* d' J( D44
! o4 m( O6 M6 x: S8 s* t& U8 P45 F% x3 X, h0 u
归并排序的特性总结:$ g, J, F$ t7 A* y) s9 ~7 Z
. O' Y" m6 ?/ y) \归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。- D, Z B0 X4 F1 }6 E
时间复杂度:O(N*logN)
1 y5 E, B2 z+ A3 W `空间复杂度:O(N)
: M U4 Y1 H; r0 m2 y. {% [稳定性:稳定
" B, F# j5 u$ n- J0 U3 a
6 N& n% l) G% O" [6 H+ @————————————————5 M7 K5 e; q% _9 S8 P
版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。* a7 [9 z* p" m! `2 k
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
2 G( f. ?/ n9 n4 Z* U% Q7 {5 x& V, L/ ^! r# A
* d$ ?# H! j: Q @& t# E+ ]
|
zan
|