- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565162 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174771
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序
0 ^/ A3 Q T( a4 Z
& i. B! s8 X3 P/ n; `2 X前言
3 Q9 d0 o6 {) r$ g本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
& X6 }! E$ T# R% t* t' ], f3 Y& B* B' u- @! q
归并排序* j) U/ E) v7 Y1 j5 A
基本思想9 M6 N" b- k: E1 e. P5 @& K8 d
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。/ u/ O; J8 s) t1 }+ e" V( Y! Q
' z h1 z) x1 @ Q( H# f5 q/ r
: ^0 C: K$ A. o& t1 H
8 \) p/ ?4 X# j6 d8 ? 合并的思想其实和有道题目的思想如出一辙:
7 c" D" D: O9 m: j- c& l G; @ e8 ]4 P- ?9 V, Z4 n `
8 u2 t" H, j. \% e
8 P# y* f8 }, e6 c; J& q8 V l2 F 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。0 e9 z" t2 j6 F7 ?5 r# \: j
$ x* _% |/ x; ?! }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)], D1 H& G8 {& j! n+ f# r5 T- V/ `
3 d' g' `8 c3 B5 m: aint* merge(int* nums1, int m, int* nums2, int n)* V; ]$ g: a/ }8 i7 j; z
{: Y5 a4 Y/ a; j: s r# l5 ^( ^0 S V
int* arr = (int*)malloc((m + n));5 e$ f& S3 i" J- {" Q4 g
if(arr == NULL)0 |- z/ F1 K4 V: ~# C" a4 \7 s3 p; F
{
5 x2 [ ] U5 N, [+ X" \ perror("malloc fail");# E5 B: K$ P% L+ N7 q) w: I' Y
return;
( e) x# c; H/ M9 ^9 _' f }) Z# [$ ~* @. v/ s
5 ?. T# s% @4 [) h; `' h$ G: G- F int p1 = 0;
3 o& N* z9 U- ^ F" x1 P int p2 = 0;
/ I: o7 n1 E- s ^ int cnt = 0;
, @& b6 d' _$ o8 x; |- p- q" T while(p1 < m && p2 < n)/ ? m* s3 K: r
{
6 e% G7 @4 N' G' H if(nums1[p1] < nums2[p2])
2 g2 _) C+ h& B' K# L c) T {2 l2 k+ J; ~+ J% b' w2 l3 D
arr[cnt++] = nums1[p1++];- R9 f; B: d% y9 m) h3 K- v
}
8 x' R- K& d: U% N1 D* Z! O5 {1 V else# M# a* ~( J( p: j% c/ r
{: P5 z4 k+ T4 M) _: a5 e
arr[cnt++] = nums2[p2++];
5 r& i# \; J8 u' h* ^5 }8 ?. q' [& ~ }
$ D' L7 G$ G! \; M# B" Q$ E, V: l) T }
3 ]0 H) z+ O( M0 E" V1 C+ C2 c0 } while(p1 < m)
: A9 i* I( W" p arr[cnt++] = nums1[p1++];
/ u/ U6 f! A. G3 a- n5 r3 m5 D( T- a& c; \/ q: d2 [3 U/ c' C
while(p2 < n)8 H1 Z" k& m" f- J) p9 [
arr[cnt++] = nums2[p2++];- x* o: D9 A6 M9 h p' p
V% |# P$ [. y9 ^5 w
return arr;7 P, g; D* e: r" |/ d( y
}7 R+ d7 H% @6 x* q
' F, c$ J6 y. b i, B& B! |1; N/ |: {; l; B- \9 Y+ W- L- m; `6 {
2" R2 n9 m: t$ z. r' B
3
6 f/ f6 G' z- b! m% h0 m. R5 ?4 X% B7 k9 I8 D# e, }% S
51 p. }3 k5 M2 }; F! _* r$ l" u, D! @
60 }, o5 Z! [( q/ j4 j
7# z7 l4 q/ [( N) p; S
8
; O w2 K( [1 W% \ M; a) e& e9
C0 M& u0 N w/ K; ~6 @10
0 a; o$ O4 C9 L5 J- F( V11
- ~& D9 H4 w! O3 ]. ^7 i; [% P9 ^12( y: S: J z, S4 [
13* l0 K' n( ] I9 ?
14
! l) y6 f# V$ y: {150 L, W6 z' m9 w2 @
167 Z3 M' Q8 H2 l4 G
17
9 N8 B. K1 `7 }4 R. U: X. F18
) m3 y9 c! L& _19$ V$ n% ?5 Q. M+ @, n
20
; c2 D3 [4 [' @21
2 C& A# x9 S4 ~' h# h& x221 }1 J6 n' L) u! c4 l
232 [; ]: z' H( j5 P
24
( l/ ?5 D2 K. B" n: h0 y25
) H3 Y7 I- \2 e1 y5 I+ e; e+ J( U26
- g+ g n/ N- g4 Z1 N: Z4 l4 C27
% i9 _ ~$ C2 @28
% t0 \2 n7 O8 f- C" N7 Y29
$ O' e; u9 E d5 Q0 C( R, _$ a: m305 Y% h. j( y& ]: X4 k* _
31
0 J$ ~2 L8 U/ J5 @( P+ P 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
5 I0 x) q. x8 e, @1 s& ~$ y' ]& G, }( R, {6 n/ a: O+ d
递归实现
& ^/ w m. l) U* P 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
+ u6 U0 z5 {% k9 g! o
. b! V: ?5 n8 \, V- f# X9 F1 O
h, D$ o% B# W$ I8 v4 ^, G6 g$ f* p Y; D q* q
/ }& B& K7 X5 t0 e
' k5 r/ E7 x- j' a7 l+ A8 ?void _MergeSort(int* arr, int* tmp, int left, int right)
: v& M6 P8 W A# w6 P; b{6 b8 r' x* J/ o* }
assert(arr);" i, U( n1 u5 T* Z
9 \4 y H1 f2 ? ^( [ if (left >= right)//递归结束条件不要漏了
( M/ r7 x; W- k( _! _. x! F# C return;
8 F6 ?# D* K7 l+ `# V3 M; u% l v ^ e; v; i
int mid = (right - left) / 2 + left;
0 M& g7 W3 b+ T" m$ j* c
5 Q g. N, J# s( {& }( G //划分左右子区间[left, mid]和[mid + 1, right]
& N! K5 ~1 a' h( B. [( J+ ] _MergeSort(arr, tmp, left, mid);6 q R5 n- E& q
_MergeSort(arr, tmp, mid + 1, right);8 y5 R- `/ A$ k$ u- C9 u
+ G* l9 t3 c2 j& ~: t: o
//归并
& C# c& H7 `! O2 C6 w* | int begin1 = left, end1 = mid;
& i3 b* R1 D3 M+ R- S. ~ int begin2 = mid + 1, end2 = right;& c7 ~* H3 ]; P, }' A2 E4 l
int i = left;
; C9 `" l4 ]5 w$ u while (begin1 <= end1 && begin2 <= end2)
6 e. `2 g' g* D8 S B. n {( l7 z" f0 ^9 K/ e
if (arr[begin1] < arr[begin2])
0 ^8 Q& [; }: `, ] L# l6 | E/ I tmp[i++] = arr[begin1++];$ U2 y! }+ ?( O( ?# _
else
# ]* J& ` h2 r% B7 R# x* _ tmp[i++] = arr[begin2++];
/ e6 S# J$ M- n& j9 l" v: m2 L5 J }
9 w/ P' d! x' A4 X! I+ r6 |; h' S, K8 O8 E/ v( d4 S) H; `
while (begin1 <= end1)
u( r- t, E. A! X5 z+ t3 ?* L6 r tmp[i++] = arr[begin1++];$ W% a! L0 l5 H7 p1 V# F
while (begin2 <= end2)
/ n8 k: o7 a8 p5 L6 z tmp[i++] = arr[begin2++];, [: J1 U8 b6 }7 G$ A0 u
) Y6 M" J4 i3 k+ F, ] //拷贝回原数组——归并哪部分就拷贝哪部分回去0 R9 \. u$ t& r( G
//而不是拷贝整个数组回去
, L- X5 C+ W2 G, ? memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1)); ]& D- y! E( y3 k7 i) B
}5 `0 r8 w" x6 ]0 F4 g1 u
6 a2 x% {0 w1 G9 v" c
void MergeSort(int* arr, int left, int right)5 @. s$ i: p, }3 J) R* q
{
# F/ Y' r4 a8 `3 @, T8 a5 X assert(arr);
$ n9 [/ l0 \$ v1 I
; R- d9 |6 y7 U int* tmp = (int*)malloc((right - left + 1) * sizeof(int));% l. M0 l$ i$ G% F W
if (tmp == NULL)
- {9 j3 M$ s6 M' D: \, x% w5 U {- E& C8 {. p, W" Y5 `
perror("malloc fail");
/ i8 x3 h) y# S# q5 z8 [ return;# ~0 V2 o7 Q5 Q/ z; C
}
6 h1 a# @% e6 j/ X
, ^5 w! r# W1 @. a _MergeSort(arr, tmp, left, right);
9 X6 K- ^: n) k' q# K" a" s# q
/ y: |' e( g2 f/ ? ? free(tmp); _7 @! {* k. x+ ]. I
tmp = NULL;; S" u0 ]& j+ Q u, Y3 k4 e- ]( `
}
% l# i' j1 a6 }+ G
2 @& t2 A! M( l1) Z8 S: ~: j( A' c6 u- u5 @0 _
2
% T% o. Z, {+ l. M6 C' y' x4 g3
! z3 q$ G/ Z" b) I& U4
5 X8 i1 A3 U' A3 L8 D5$ o V" }9 T" \$ V
6
% A7 |& {1 H. S' j7& H# I, z) L& }( B
8* A4 E9 s2 E {' A' a
9
: K `" r" {, L E10. J6 S- m7 T* `, X5 T4 k
116 C! c3 m5 I" K9 w2 _
12
: n7 \4 [) R% N! H0 ~13* D, l) I W4 G9 U. P/ d0 n
14
5 a) J5 Q! r/ a% R& Y7 ~! S+ |5 o- L# y15
, @, I$ t e6 O164 u, h6 W" b. p8 w# ]
17/ c) l: \: B7 y+ N4 s' G
18
X0 O( ?/ `& v C4 q* b8 i" [19
9 W- H) ?8 T2 o1 ^; {20: Z$ U( ?3 Y* ?. ]
21
$ [$ C5 P7 d3 ]22
8 p) X9 O9 o; y. q: Y m V" q23
2 i9 \7 A8 n, ]* G1 ~# A24
* C9 p) Z1 H) w0 J+ B+ Q25
7 ]9 S2 U* F9 u26
: F9 G8 Y3 |) X8 m4 h! u272 q6 G0 v) B. `, K! u
28
$ h, J/ u* y3 g6 h; n9 r29
! n- l" A o1 k- f* f30# v0 @- l& V& `8 |7 c2 V# ^
316 h1 D. c5 w7 ]# r5 f; u8 B
32" }" J) t: Y* ^0 k3 \! H C% X! ]
336 h4 c: |0 ?4 ~' }% q# _& Y. X2 D
34# }) e9 K; A; V; D: G: k8 b! p
353 x9 L- L, [' X0 l1 r0 ~3 r8 |
36
3 k; f! |8 ^9 F1 w373 W% ?/ H, ~: r E
38) u* W( `* @2 b) I- N5 P7 `- t
390 H- y9 q S9 o0 W/ X( b
40: @, [: U0 u% r% a# n
41/ O, c2 o0 c& e! O/ G
42
1 Z1 C$ n# t3 i& Q' h$ f43
5 w3 \: q1 L, r44
2 x4 y7 W; [. z2 z459 K* E8 ]6 _1 e' l6 w% v5 g1 T& K
462 u$ E! J: |/ U$ a$ b# ?
47/ [" n! X" X, D1 b* g% x! A2 A
48/ D! S2 [3 c+ P0 ?" z9 I* _
494 D, l3 l W, M5 D C! b) e
50 Y5 t$ ]9 ]! x8 L& A& G# C
51# }2 Z; r8 {) [0 S& V
非递归实现
% m+ `& x) _' Q& R9 {" s 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
) I+ m$ g0 h6 B5 K( B) a4 U* ~2 f% ^( H6 g1 K( K: H) _% K" `* k0 T
' L3 G) A# q4 v. O9 x; b/ h7 J
$ |/ H6 D- I) e# a$ h 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。: V7 C7 M8 [" K8 m: g* b7 J
; N3 F2 C4 w0 y! [; S
还要注意区间的取值,每个区间就是一组,就有gap个元素。
- J" f2 h0 ], d/ m) p$ \! f; Y$ e# z; ]* N& K
整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。) V6 r% X' n" `! d3 u; N- C
% a1 |* y( m! D" B
代码实现1 f3 E3 W* [3 W! b
% k: ^+ T) k8 ], F _/ s% qvoid MergeSortNonR(int* arr, int sz)4 Q% m+ H+ J" h
{
& c& C8 j, D) J' p assert(arr);. t. a* s0 {/ t
; u, E' N8 q! P
int* tmp = (int*)malloc(sz * sizeof(int));
7 G# |: T. S( S if (tmp == NULL)) c0 Z$ ^5 w/ i: R
{
9 _" ]* Q- Q/ t+ F k perror("malloc fail");
" D* B- L1 v5 { return;
* \ m$ h9 i. r# o5 | }
* Z/ {2 H5 V/ H: a# {
& ^% w. S# v- D# h' q" F int gap = 1;+ O! b4 q K d' [; z" r
while (gap < sz)
6 z; w' E4 L' C {
- O Z! m6 o2 @. e" y' s% ? for (int i = 0; i < sz; i += 2 * gap)
; R8 [* m. L- c4 _" v {
, t0 J! X; B& ]8 d) ~ int begin1 = i, end1 = begin1 + gap - 1; F' Q# R8 }, i$ @" i* j' u3 Z
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
( Y& }: w# f8 L5 F# e: Z7 `- Z3 O: u int j = begin1;
! R7 f+ S/ X: ]+ v% m3 \" S2 J) q. ^* D
//归并" }5 f$ l4 l. p
while (begin1 <= end1 && begin2 <= end2)
7 O- `& d# r: L/ v { g/ D7 H; O- y: E
if (arr[begin1] < arr[begin2])
9 { T) g* E) z9 w8 L tmp[j++] = arr[begin1++];' V$ s& z" N- U* \
else ; m# {; @5 ^, K, e
tmp[j++] = arr[begin2++];
* g2 G0 [9 _( c( T }
" G" H1 D4 W$ z: o/ G# [
7 K% f( @! `3 `) e2 } while (begin1 <= end1). Y' j) \: K. V
tmp[j++] = arr[begin1++];
" g& U# i. h' z$ e8 E while (begin2 <= end2)
H! I8 w* i4 {7 o" a+ t B tmp[j++] = arr[begin2++];) Y7 q" o' C( j' O
1 j$ m1 z5 D- S* [ //拷贝回原数组——归并哪部分就拷贝哪部分回去
6 [( i* H+ I p c memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
* Z) b2 _2 G% S- Z: c }
* z0 u( }; i1 a' Z, I. z gap *= 2;
5 G5 d& I2 j+ t* Z" d( g: w }
' K$ j: J. e! l! X6 q$ D1 w& v- C' @- v# p* ]0 N6 Z j
}2 P; a: ^: s+ Z/ L6 w
! T5 d' \! F; C. z1* O. N6 C9 t2 P1 ]1 R4 t
2
4 N! l$ e' {. i/ o' A' F: C: a3
2 m7 |' v9 _0 C9 C. o4
& c0 R. q. K1 D5
, J$ w. Z) Y# Q; m6 {9 d( u6
4 \6 m z8 k, U/ k+ q7
- [2 K5 G) c, B+ r6 k# \) Z8
0 V" G. j" w5 X$ c5 G. r B90 O% f, Q, f0 B5 t; m
10 L9 D$ S7 O0 Q# G
11
; b0 k" g% ?3 g120 j6 {2 A# c5 g! G; [ L, g0 ?
13
2 V2 O+ c& v V8 n, r5 _, k147 t2 o% ]# r- @- w# Z" r( ?
15, r. M4 e, p7 O/ C1 D% z1 U
162 K6 p5 Z2 W( x9 P/ D
17+ i$ {6 s1 N! F' j8 V' v2 _
18# n# j% D1 O k- Y$ M
19
) Z$ h' s/ D, v+ j4 ]20
+ ~* ^: k0 u5 ]$ B! _21* h+ N' m& T$ d2 E; x2 n
22" y) K1 s. e9 A! X; f8 V1 U
23: X7 R8 f# P+ q( \6 `
24
. w' m6 n6 j' [: e25, U' ?4 H& [) e& ?1 V, G
26
4 S& `& O0 \) `, e, [7 i$ }* a3 k27( U6 T8 A+ j8 ` W, ~/ v
28$ T* x3 Y/ t- {0 C
29: `) r- p- L# u0 i
30
5 T. J4 ^* V% d% \+ i1 D31
3 M/ |& ?6 `$ ~, m/ a323 ?/ t4 T1 Z) N+ B
33
M# o7 p3 ^: f7 d. o347 z- `7 A& r5 ]7 L% m5 l( f
35
4 S9 u* ]* r% s9 m36
7 i4 D9 v( w: T. I37
( E9 n; q' W7 j5 W9 ^. h38
' y, p. k" |3 x39
# v3 `# {4 V8 `3 y2 j40
/ F$ F, M y9 U( n \41
) i! w6 g: c1 Q4 P边界问题' W- n ]# T' _& Z% v
实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
. B0 r0 u9 D0 [8 F; Y3 F3 D& R5 N: q* W5 r; {
举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
. w5 P& s5 \: b) z! y; w, \- [3 l+ D z7 v2 O. D8 h
/ a6 y, t7 G1 M! T' E0 v4 x: B0 b( a/ b) @' z# f8 ~
由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
4 r' D) ~# Z8 Z& F0 l! ]1 S# S/ O! C& [; w
第一组越界(即end1越界)
2 k8 x; [8 S, u1 u& h" |' _# S3 O& z' y
应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。) M: c G$ }+ N" {* Q& D
9 g, g- h/ h# [4 _: b: U第二组全部越界(即begin2和end2越界)
- |$ A+ M/ _; {+ I8 V. q
8 J4 t6 r$ l% V应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
( Z7 t9 Y# }1 L3 e
9 a% n+ e$ `2 y, x第二组部分越界(即end2越界)7 D/ F* {. k2 }- v1 P
$ n9 ^5 L& C; T& G
应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。( A+ M" X# G" f6 r3 t- r7 u
& d' L& x* B5 ]8 \* k7 C
其实第一种情况和第二种情况可以合并为一种情况,原因:
3 Q/ \: w+ F0 n. \: o
/ u+ X3 \( ?9 J end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。5 j8 c, h0 Q( ], \
& A9 ?: i R4 w3 ^" h- ^9 W
拿两个数组试一下:; S/ x, Y+ C; K1 } i) M. d0 f
2 o. Y; H% ~0 U. X, k# E4 e, d: ?, r$ V! o/ M) G. x- h# R6 H h
- a) w! w% J% E. m. j& v& s# f7 _# D0 y
% B |: s+ g+ l0 G( K {代码实现+ G7 _: f0 a: j6 d& f
5 K+ N% }. W7 p
void MergeSortNonR(int* arr, int sz)( }. u( K5 c. o
{
9 {5 q/ a/ K; `2 Y assert(arr);
# Z V2 O* z" o8 Z0 y* d6 E) {4 V% u1 c ^) f; ~
int* tmp = (int*)malloc(sz * sizeof(int));
6 p1 G0 r2 Y& b `' @1 ? if (tmp == NULL)* I- i1 e, ]4 E, U# H$ y
{( M# N# ~5 [" R6 F5 l0 v, x m6 e
perror("malloc fail");, o E0 \5 f* {' Y% |
return;
- l3 M8 L$ R: r# ]7 {8 E }& N# h4 P- o% j% y; _3 x
1 O1 x# b) x3 f3 x) c int gap = 1;
& a M+ Z* l# ? while (gap < sz)
5 F1 _ ^/ P* \7 \0 c6 T {
/ L8 F/ q; E% |' D) q b for (int i = 0; i < sz; i += 2 * gap)
/ O; M' i6 [& B% N* _, C {* r% y( H3 V1 {" w0 L: a
int begin1 = i, end1 = begin1 + gap - 1;
# R& F8 G* U) O J A9 _ int begin2 = end1 + 1, end2 = begin2 + gap - 1;" t/ A5 g. V* m
int j = begin1;9 H+ \# ]6 E2 z
//越界检测
& i& Y6 Y' F) U3 |& R if (begin2 >= sz && end2 >= sz); j4 _' i1 Q/ f- [7 w, w8 @
break;6 g4 P* o; [6 Q( N5 J3 I
if (end2 >= sz)4 N- K$ `( j; [2 o [7 G4 H' B
end2 = sz - 1;
- z w' \ L, m* D4 g //归并
; [. v, B& u" t7 N" A( W( ?' \ while (begin1 <= end1 && begin2 <= end2)
- e2 o& y% Q3 F {
% h, Y' A6 j6 S4 s/ o2 E& e' u if (arr[begin1] < arr[begin2])
3 n2 P5 Y3 V4 Q# l( Q9 y tmp[j++] = arr[begin1++];0 ?7 T& n7 s8 v4 B: ~1 C& a8 g
else ( e7 e% k' _; H1 d
tmp[j++] = arr[begin2++];
* b' B/ d1 s5 e: u) o+ W8 ~ }
^) }; T( m2 j; I& {: }1 Z
$ b9 x/ m; F1 ~2 l while (begin1 <= end1)
7 e. i" n; N. v3 n( c) z! x7 B% \ tmp[j++] = arr[begin1++];
! _2 g( H. C. Y9 \& e/ K; L while (begin2 <= end2)
/ F; O+ [# _; V! i6 G& @. x- h tmp[j++] = arr[begin2++];
+ E0 b' ^4 q- M: j. t4 ~- j0 p& D* A$ v& _6 t+ a- O
//拷贝回原数组——归并哪部分就拷贝哪部分回去7 N3 n# z7 x: t# \5 _. o* n# y8 P
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
6 E/ E* h8 _; Q0 L; q$ m. ` }* [9 {9 o4 }, B
gap *= 2;. W; Q( W" _6 G; C# F
}, E( m6 ~: E1 J# S; J
# {: q" e/ v- {* u* g( n6 _: `: x
}
) H4 V1 t; Q* ~7 i2 D& V/ s; k- u$ E# X4 f6 w* e5 v
1% L' b8 P8 U0 H$ R" M7 W& L: F
2! _3 z5 f5 n2 w+ W+ Z1 h3 w7 g
3* p3 W) f8 `/ i
4! k$ V" {7 H0 C+ a6 J2 q* y
54 g4 G( y2 R7 A* p& L) D
66 t6 W; B% \+ D2 t
7
* G$ i% v& _+ m" k! {# r4 Q( u0 u8# B7 g: p9 X P! K, D" M' v
9
4 u+ D8 ?% e9 Q1 \# b, |- I10
9 l; ]$ j0 J" s/ [- f- q11
" w& `& d+ Z; j0 O% r7 f3 k# T12/ |; ]; G d2 {4 R* r
13
7 b* A8 `3 _% V, g7 K: T6 ~1 O14
2 i7 b) N' |& M15
" F% D3 X7 U2 H5 u9 y! j: Q16- ~- T# w: w9 i7 @. x3 a
17
$ r( d. x" a7 P4 I18
, z: A) w% N+ \5 {- Z19; m0 k4 @3 I) ]
209 S ?7 J# i6 z# T0 H5 e
21& k. k9 J6 h" v! N: P/ Q5 H& X
22
! Q5 x V, L+ z3 D: A1 V8 V23
0 i8 U' Q9 i/ t; p3 f24
$ s. @4 a6 ^ l5 H; i2 S25
$ D& M& X, Y0 X' K26: G9 O# n3 m7 `
27
O) u# |. C. s28 Z) j7 m7 K4 q7 R4 l6 I
29
- `$ R2 L$ I: M4 E30% f$ s4 a2 U- @
318 ?+ B* Q9 A* a$ Q
32/ Z9 w+ } ^7 }3 {% H
33
9 U% M' t" K* f" D34& N1 h, O& C' t0 h( o
35
0 p' y; T( Z2 j1 P; O [, K x# d36% i$ w2 T3 Y$ P- a, Q
37
1 V* y: I/ f/ [1 T38
4 d* S& q7 Z: R0 ~, H: J39
( ^3 Z K( S, a# U40' W0 |/ P) V4 x* X3 G' i% u
41
0 r) V8 u4 @* I! B8 Q) c42
' h" ^1 A2 [4 y& |6 a2 W* h) m43" u& M* d- W4 C; k7 G
44
! E. r5 S6 x8 i h$ d) V& A45
/ l% h2 e/ M! e t0 t归并排序的特性总结:# a& o8 s& A+ x" w0 ]
; w6 M. f5 N+ J3 t
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。8 l4 o% J3 Y" w! e) [
时间复杂度:O(N*logN)
* X& B; B {1 C( u# r: H) q/ o空间复杂度:O(N)
) s" r' P" }$ r2 r稳定性:稳定
% u& Z: J* A2 x* w- H- c% K+ O
' k: |% J+ F7 w————————————————
" y: @* C- h, U版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, R" s# i5 K6 W7 q% ]
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657; K- t4 g7 b* Q1 o/ k" a9 y' f
* @' b+ e5 S6 U+ ^- o) H
6 r( J" u# s& k |
zan
|