- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564702 点
- 威望
- 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的排序算法】归并排序
0 X0 |) i3 h x7 b) O& Z
) [; I; e/ Y# D* V3 T$ G2 [前言
) ~1 y! n" r* r8 {4 J, j# }5 [本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。! @; D/ O' c/ M( B& `7 Y$ i" S o
x, B) \7 N0 f6 [: Z I
归并排序
) W2 w8 b7 F, l& V$ ]/ |基本思想# ]$ Y4 w, J9 {+ U
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
3 F8 I8 E! {: ?! W. _% H x# }
+ ?8 A8 I# X: q% n7 K4 R- [ `$ x" P1 n- J
, W3 t! P3 q3 t/ Y! s
合并的思想其实和有道题目的思想如出一辙:
+ l5 L" j) c( p% {# n
5 `; M3 F; O+ }, g& i! O( a: e% {, b9 j5 q
9 x0 G' _5 X9 U ?( p, h: b
我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
0 n' @) R1 U9 u7 z9 Z: M* w' G3 @3 Q. T$ p. @9 m
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
& ?; m) a- ~5 S6 l3 J, j% L- i" @2 x" o
( W" U3 V! W5 y0 dint* merge(int* nums1, int m, int* nums2, int n)
! C2 g* M: {' Y, N{
- f7 |/ D0 I- G2 r5 X0 p int* arr = (int*)malloc((m + n));
) E7 n/ q5 `8 [ if(arr == NULL). v* `) U6 m8 ~+ K1 X! ?5 q
{. V1 p0 H1 A/ o* {
perror("malloc fail");! U$ k% c- ?0 {) ?4 E
return;2 J! Y$ x+ I5 X' G4 a0 n
}
* t( C' T% B6 d; E) e- c! N: `" E1 l& W0 o8 U; S: p! V" H" I
int p1 = 0;9 T& b; E# z d/ V4 U* I7 D- h! a
int p2 = 0;# z* x7 m! e# \! l4 y4 `: y; N
int cnt = 0;) [/ ^. i- K; @, I: C0 W0 t
while(p1 < m && p2 < n)
4 P) ~6 \; h2 t5 E' K+ O& |+ m {+ @% y' L! ?+ M3 S" H
if(nums1[p1] < nums2[p2])) w" D4 W$ g" e2 a
{2 X: x7 p+ r8 _5 W. ~' ~: e
arr[cnt++] = nums1[p1++];* D) x |3 n8 |( g9 [! X2 V: ~6 d7 E! G
}
4 G9 R; |7 \/ I! ^ D1 a" b else
' F7 U0 e6 p5 P$ Z* l$ h: U {
4 x" ~1 ^, B8 E5 J/ \2 I7 B3 w arr[cnt++] = nums2[p2++];( e% `+ q+ {- |' F. Y' X5 Q
}
5 e- W( s b4 W8 U3 s+ e }
/ e) N9 H9 i% I8 F/ ^% P+ m1 e3 } while(p1 < m)
, g" Y8 g" D# G/ I$ I" @ Y arr[cnt++] = nums1[p1++];
' t) O* s1 l/ ~9 N, N
9 E5 Z, x; i& o" U$ h* G$ h while(p2 < n)
6 x+ F# K( [9 F6 M1 V arr[cnt++] = nums2[p2++];
& g5 B2 I* o) G% K% E: Q5 H+ g: [$ A' | ^* C. z6 t: M
return arr;8 M9 N! t$ _( ^! g* K6 G; o
}6 ? r& }0 w) j" ?8 i& e& T
1 j8 C% m2 Z- R2 x+ S$ M19 J5 Z7 ~* z+ A
23 E, F; W: y. b( m
31 j$ z4 O( c* @ ` w8 N+ m
4
2 s( ]5 A' p2 v) K0 B53 ^% G, u: n" H' [8 Y
6
5 X* u) B' I1 |% X8 M- |7$ C& i" P0 Z$ L9 N4 I+ J- Z" e
8
6 O; P H4 J+ ? A l4 y9
% @3 p$ ^, e3 ^0 k5 ]10
* m+ k& N; G; d1 h: a" a11/ D, J+ t2 o$ b1 l+ a
12
& _; A# ~5 w: J0 W13& H1 U2 d0 e4 o( j# u: H: E8 k
14
+ M: Q; Z9 t/ z# N15- i" n" A8 Q2 m; C. W( x# V" A7 i
16
3 V5 z8 a W8 N* t4 N17
5 C+ x. ^- O7 ~4 z8 V$ H18
6 j" Z8 i' }2 h19& M* Z, z" t8 E' i
20
- W: E H/ H& U E, p9 @2 ]$ D; C$ f21' M' A8 G6 Q/ n+ T; x
22
% }& X1 w$ g7 u, X, V1 }23
3 N+ `% F& U4 f$ q5 }241 V7 G- ?4 L9 x2 B, {$ i: ^5 m
25; T5 a3 I. }) F0 |
266 W% z9 k! w8 K' b
27
7 h5 W, B4 ]& k284 \; d. ^4 [- A8 _8 M
29! n& D) g2 i2 r3 n4 _
30
' O7 q* |3 S: c! U4 E; _31
* y* ~1 q* D, k# G+ {+ j" h% b; a8 Q 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。: ]/ O6 c) B- _, j# q
. y% w. k' I' v- C递归实现5 [7 B. Z3 |3 s- O; {2 W3 z: A
通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
6 [( i1 F5 M+ ]& l# E
" h) @3 U4 M# V: h8 E- }* Y6 C* g9 t" I3 F8 L# u
+ d6 y5 [1 R4 L! D6 A
2 E' Y ^8 S) ]* S8 w5 ]
; A$ n; B& k* vvoid _MergeSort(int* arr, int* tmp, int left, int right)6 | m# m% `$ l# ^
{
% p0 q6 z( V4 i/ O8 S h% C& W k assert(arr);
0 _! C x# z" I& F- b% R+ x4 ]0 x% q
if (left >= right)//递归结束条件不要漏了: D5 k+ q! P1 a" V% n1 V' x
return;2 q/ q* M( K8 R* t- t/ E& E
6 i9 k7 |7 u# J- A int mid = (right - left) / 2 + left;
- J3 r7 c* t+ n( R2 @( {; T, c" H4 b) T/ m; F
//划分左右子区间[left, mid]和[mid + 1, right]7 \* M; h3 G7 A* e1 N
_MergeSort(arr, tmp, left, mid);& [+ w3 N7 z9 ` }2 ?) O' b
_MergeSort(arr, tmp, mid + 1, right);
+ W1 R' N1 \* j$ |3 Z" _ m
2 u- [5 S1 i N //归并
9 s% a `+ i: X% W int begin1 = left, end1 = mid;2 y! X8 i8 `7 z9 ?
int begin2 = mid + 1, end2 = right;6 e6 \/ I5 O% X& J4 Z. s% p
int i = left;
% z3 ~/ }. m- }% s! ?3 c while (begin1 <= end1 && begin2 <= end2)- u6 G) S4 Z" Y& I& i* h0 D
{ D6 u* l1 z# k2 B/ T( F* _
if (arr[begin1] < arr[begin2])
% [. N/ m8 T/ n: G8 F; Z: V tmp[i++] = arr[begin1++];! m- r8 e& i5 E" ?5 r3 k0 @8 ~
else* m9 c" U: b, d2 s+ w: R- \
tmp[i++] = arr[begin2++];: _6 `* w" o$ Q
}' z# z/ }' `* w' d
& `1 I9 M( i, k2 m2 d while (begin1 <= end1)) W7 S* @6 t" i" I
tmp[i++] = arr[begin1++];) e5 O- \. M6 p3 V8 |3 t- B
while (begin2 <= end2)
/ X% Q5 ^* P% \% @, g tmp[i++] = arr[begin2++];
) W3 x1 [! a5 K! ~: X! G & j( r1 h8 }2 P) d; q
//拷贝回原数组——归并哪部分就拷贝哪部分回去
/ V6 n+ C2 [- v$ z. T //而不是拷贝整个数组回去/ H9 K. n4 e& z6 o o
memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
) d k! E! L9 E! l2 _( x/ Y}- C% K) o& b' s2 X- a8 _' I
) H9 N# [3 B: u, W jvoid MergeSort(int* arr, int left, int right)
! f8 ~/ a% b/ _) b R4 C{# e9 b2 ]% a+ }& f1 \
assert(arr);5 Y U4 `8 A* h; N* B) E
2 J) O" b5 V$ Q4 ^$ W! P/ Y( `
int* tmp = (int*)malloc((right - left + 1) * sizeof(int));, f; X6 R0 Y, i6 n$ h% X+ y5 Q
if (tmp == NULL)
3 z0 t( e5 W$ ^9 H {. n+ W3 h" z9 n' Y+ V, j
perror("malloc fail");
5 Q) `' w! P# m; z5 @6 I% Q return;
0 R w4 Q1 G" o0 c3 L }
! B2 n5 j1 @6 t/ m" s! v4 W3 N0 I% w) X; Z! _7 I
_MergeSort(arr, tmp, left, right);
5 T7 n+ A- C9 L% E9 _# }: h0 A/ T5 b* p; n
free(tmp);
! ]; t& [5 D1 n6 E. F; b9 I tmp = NULL;2 T6 |* f7 g6 {, z- d
}+ {3 x9 `0 e7 I1 ~) g, d5 \
! y3 k' p7 Y4 \
1
- m7 F( q& n* d7 n8 t2# P) a+ X: K5 S1 s: c) G
3 _9 O4 W# B0 m2 T" s8 E0 |+ O
4" _$ d3 i% F1 u# H" ^; e
5
( O& _, r, I6 I% T6 ^& W! `; _- p* R5 ~% h
7
8 M3 g3 \& ?" p% Q: h6 l8
& k; E! r0 M8 p" Y0 M2 N+ M0 P2 h9( A4 Q9 F9 f/ y" u. |+ R( g% d$ O
10
3 w' f$ T4 k' ~7 T) q; ?5 R11
9 v+ y$ k, C* B4 X I12
0 V9 O: @2 P8 u& l8 I13* Y/ g d$ l6 @5 z! e/ t( x
14, R1 [( O; P# @% z. x- L9 B y8 |
15$ Z/ n& N+ x4 ~$ Z( t2 V4 ?/ m
165 K1 ^' ^6 ^: R+ y+ o
17% O2 _6 U) M3 O; q3 q% \, B4 h
18# A" z' K; u* E/ ]5 e/ u
19
" i% B" C' K; N* G T- W) _- ^20
7 _" X/ ~# W3 j h21
7 C* j' N7 Y1 z# q3 R22
" q7 y5 y, n v! v5 ?23
1 K+ J l7 h' ~; e3 r. D: f24
1 D9 a& B( X$ t& G0 {4 E+ x+ u( b25; c; Z8 Y, Z+ @0 K& B6 l# S( e
26( |5 W2 D4 a* L6 v* {4 B
27
! }+ b+ Y/ v( _7 a3 Y2 E28
4 b/ b( T; u) o3 ~4 K9 W" t29( R; z8 z# n- m; o( J
30. `' B# r: {# j% n
31& u9 D7 Z, v5 e5 H5 G( x0 E$ @, g
32
+ b r/ B# z3 M' ` t6 [0 L33' Y3 X @* H. V
34
7 L# o7 L, f3 W, U, e35
0 J; z' y8 R8 G- y" ]# m: F2 X36
: f4 |1 \6 Z) b37
9 u4 d& \7 @$ k* n0 [% D38
+ u7 d, H" ]8 t: l! E( \& `39
* H, ], g" t2 ~8 q7 e1 K40
4 P& P( ]7 r, e- g! K41. p2 o% l3 V8 _0 ~. M
42/ T& F% z5 f+ H/ t1 N
43
9 |# l, S8 f0 n* w& Z44
% m; ~: Z0 c' U* K4 P L2 H* G& b45
; E& H% h7 y4 f2 [3 e K46
2 T! n+ G1 y- F* O9 d( R5 e5 @, } s% J47
/ }" F. |: a. L, n3 B48; V6 X2 l4 c4 c: d: o- \8 u+ r9 [' l
49
( V& ~+ A% Z9 f0 S0 ^$ Y, f50* o6 I3 H' }% Z
51) X1 Y9 X; R% h {% h
非递归实现3 D# _7 g- y4 E0 C6 Y6 \! J- z
直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。 O! u% t8 ?4 U- n( m2 B
7 F9 O6 A4 f' R
0 {: Y' i" t1 J$ x8 ^: A
8 k3 v) R& s0 o7 g; H7 t$ U 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。# `2 b1 g, ^% C& e
$ D8 d: I! d. {9 P
还要注意区间的取值,每个区间就是一组,就有gap个元素。% B$ R4 s5 l M! j
1 `1 |# X; [, i+ b( O6 p
整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。4 |: T0 _9 B! o% C7 x- }
3 d; U. G# H( b [7 y" ^1 P
代码实现
! O6 |, ]4 {' f& g% u5 C% }- i! G& q/ e6 D' }
void MergeSortNonR(int* arr, int sz)
, g$ f8 d+ X$ Y& _4 N{# O: d- n: ]: ]( ^. [" G
assert(arr);# P4 w7 X1 `! y- l: I3 s: g1 P' d
( ^5 ~ J, g/ J int* tmp = (int*)malloc(sz * sizeof(int));' F6 }) U9 z4 }; r
if (tmp == NULL)
/ P* E( n' g- ]- O; V! G# Q9 a6 r {8 d& K7 r. _: T: {/ V" a
perror("malloc fail");1 y* e$ z) j) |
return;
+ g9 q- ]6 R6 k. k# [; J3 V( o9 u& ] }
. r2 A: [/ a4 T. v$ y% d. {2 J. t1 a9 h F- `4 ?. V" @# d
int gap = 1;7 A$ |( Q6 d% Z: Q- g3 Z
while (gap < sz)5 L5 I& L# f+ W# l
{
& Z p" ~4 i" A% p2 R# y for (int i = 0; i < sz; i += 2 * gap)
6 S! U% i5 w: b {( W; I5 f* B0 W" v3 `
int begin1 = i, end1 = begin1 + gap - 1;8 X! z- } c$ i( e- ]" l
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
# Y O" J4 d- k7 ^- e% p; V7 L int j = begin1;) y% R2 y5 o; G/ u
2 P' w7 o R) Q2 l1 }
//归并" q; Q8 U, J1 x- e" A8 \0 v
while (begin1 <= end1 && begin2 <= end2)
8 T6 h7 b$ n9 y' W {
7 g# w# h, ~0 P5 D if (arr[begin1] < arr[begin2])
( D( h( D$ u7 M5 k) S% T tmp[j++] = arr[begin1++];* r& l9 X! i! a& h; @
else ! f3 R# U1 h7 p+ c9 P
tmp[j++] = arr[begin2++];
: Q2 g% j) w( }) k }6 P7 w. }7 Q" M, _
) X6 w$ a) c F' K1 |
while (begin1 <= end1)7 o7 W* x+ v# p* Q& R
tmp[j++] = arr[begin1++];6 I' N* h0 h$ c1 f. \: C+ m
while (begin2 <= end2)
& u6 v% h' J5 H v: h tmp[j++] = arr[begin2++];
) A+ h4 W4 a- c4 D
* O7 i1 r' D3 f3 L( j7 ~1 | //拷贝回原数组——归并哪部分就拷贝哪部分回去) w+ s/ V% e s( V; V) d
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));" \9 l' o" y2 b' @1 K
}4 }3 y$ e' ^: @1 @2 Y0 X
gap *= 2;$ ^. L- Z* y' q
}
* R9 I1 ?1 o1 [: j! q; O1 A1 m8 |4 B' T; m" h+ B" r4 ~! f
}# H( e- P9 e/ Z6 j9 F( f
7 [/ q }( @: n
17 k8 H) Q; q2 V5 [. t% r
2( m$ z; x' `) K5 a' x
3
: C7 k- ?$ n: Q- @46 O+ m4 I+ n8 T1 |1 _
5
' `) x2 h: {: P4 J0 _" J6
6 _3 X" u! ]" v6 T9 q( C7
2 w) q* s# P3 n: W! z0 V8# a6 Z- G! v3 {2 S& z O
9
: ]8 n2 _; P% w, ~6 d; p" [10
, \0 s! [6 a/ f. v% t0 `11
9 T# e3 J8 X D2 v12& D r7 R2 q. N; I2 Z( X2 b
13
+ ?. q8 x- {" U: o14
! L& _' _& }- O$ q15# m4 D/ a2 d( }- ^2 R
16( r. \! o6 q; y6 B/ e$ @
17
_% Q( F( i" o4 w* t: t1 \; J) \. B18
+ \% H# O% ^' D* S$ O9 r19
2 V1 z# X0 p8 N* T5 x20
7 o i+ J% E+ d21" y# w- i7 V' ?' `% B& o, O
222 Q" W# r/ a& s7 o* q; k8 i
23( O0 h* s+ f4 i1 a5 ^2 @1 r: F
24, D# ^6 I& n* a8 C
25
% @3 ^0 c$ M! t& l h4 f26
. h/ o# d) N @) R/ t2 q" C276 V9 _! F7 {$ K, }$ P
28
/ x3 O; |6 [/ R* I. p/ R2 |8 w5 ^29
! f: H+ P: N4 N3 k4 i30
! f4 o7 B5 V3 G9 B31
9 {; D8 \; o; m' p/ Z, L, K7 B323 y8 G& p- f5 F8 H* d7 |% U/ @
332 D9 M2 D0 T. _& |$ f/ [) d
34# y$ C8 R; E8 r4 F; R2 g( n* C
35' q7 b+ \( s {
36
4 m- Z9 ~7 U! p* r3 i6 |/ F7 V37. [7 }3 S; @7 y; l% J
38
; u l7 ?; `9 U& Y39
- h+ j8 I2 H( \3 @40
8 }- v4 t$ v$ v41( \! R: |1 K/ B; r
边界问题' B+ {4 e6 J% R/ v8 _8 E; m
实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。# e# L8 |' k' K( i4 i# e6 A" }& X
2 R% M8 n9 \- Q* C/ H举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
" q2 F, L( L& u& O2 e$ U, v+ B* _& T! n- z& c2 G
$ b' c5 e1 Q& m$ C
: t% \% k% c7 f# q" E3 a
由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
- I+ b2 k& \( [
# W4 A4 p2 n2 G6 t第一组越界(即end1越界)
: V$ A+ r8 d: t( s+ D% O, B0 p5 K
应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。. O# Z. d& r l; s0 ] P8 ^
, t# u( {8 v- ]2 S# F第二组全部越界(即begin2和end2越界)
) P& _4 E7 S' d, O5 v5 M, ~5 M) _( I5 J) W& B% K; C; X0 X0 }( T
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。1 w8 ?, Z7 a( Q
8 Z6 ~: J# ~$ _$ X8 M: z2 e第二组部分越界(即end2越界)1 A1 c" f& N6 d4 k
9 [5 ?: |" D: \6 _# |! i1 I& U9 W
应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。* E+ t' M- k/ v% \9 c+ |
8 M% ^' ^! v4 @
其实第一种情况和第二种情况可以合并为一种情况,原因: `' V2 v, z, G/ U
) t+ @1 j Z7 q
end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
9 k9 ^3 h# P0 R6 |( ]' W, o3 a: w$ V5 |! D; { n6 u6 _
拿两个数组试一下:- U1 d1 x F# w, V
0 {" Z, H- {7 K; ~
# A7 g; P. n, O; t; A
: p% ~% U5 o5 T$ X+ T1 F r
5 e- ~) b7 Y9 @# K# `' Z( j' J+ x% ?& t/ Z: F
代码实现
1 c2 Q9 u) `# E. i5 x9 Q5 J+ m6 G7 B
void MergeSortNonR(int* arr, int sz)9 y0 p7 g, o0 A Y+ Z
{- ^- M L k7 [/ f. z/ F
assert(arr);
2 H: }* H0 Q- n& c# R t
: o7 c$ b; O0 [, N! E3 _; D int* tmp = (int*)malloc(sz * sizeof(int));
# t. w: {. n% D* F l Q+ m if (tmp == NULL)! d ?3 S m; A0 D: z1 Q6 w" N. S
{/ Q' w6 O5 i* L+ ]
perror("malloc fail");
S) Q( E5 J) i* d" ^# a9 j return;
! K$ j6 l* \+ o }' E- t0 c8 h( ~/ t
! W' P ^- `+ G5 w int gap = 1;
" @6 O- m% {4 n( ?* i: t1 W* E while (gap < sz). X ]" M# Q6 {& Y/ E. u
{5 P) l' h% @- M( u9 _ E$ @
for (int i = 0; i < sz; i += 2 * gap)
8 i# l8 ^! R8 Q; {4 @& O" }! H { {8 P, Y( n# b
int begin1 = i, end1 = begin1 + gap - 1;
5 _/ a3 @* o p' V& c, c int begin2 = end1 + 1, end2 = begin2 + gap - 1;, g: x" @( M# p: z! o
int j = begin1;
4 P0 ~1 a9 i0 r- }7 n+ w/ E) O //越界检测
' y6 M9 C' v$ w9 Z! _5 }- U if (begin2 >= sz && end2 >= sz); o3 y: H2 o" Y
break;
7 l" K0 D2 E) H: X0 \$ V if (end2 >= sz)$ h8 r) H% ]7 Y
end2 = sz - 1;1 W! O* e6 Q7 ~2 E/ K" r
//归并6 F* V, k. J! ^& S6 A2 a9 X4 p+ v
while (begin1 <= end1 && begin2 <= end2)
- h9 A. `3 [3 v9 g4 P7 N6 ~ {
: c. L2 f! c* ^' ` if (arr[begin1] < arr[begin2])
) ^ y& J/ _' V) D( \$ l/ K tmp[j++] = arr[begin1++];
, J5 H- C7 Q5 n& F+ @% w else
; ]( {8 I, n4 H1 Q; S* i" i tmp[j++] = arr[begin2++];
& I& N9 k) [7 h9 } A3 A }+ i2 J6 d+ y9 L+ X
0 D8 O8 z5 @$ i! a8 X3 P* }+ n ?! z while (begin1 <= end1)* ~6 L# ?+ k4 ?# c( }( p) }; h# X
tmp[j++] = arr[begin1++];
3 g' k7 s) z/ X: j/ K while (begin2 <= end2)
* z. p6 q8 x p5 k% d& o tmp[j++] = arr[begin2++];
1 I4 [* ]0 r; E- W6 P9 [0 S+ s
. d( i5 x$ x7 N* p+ [ //拷贝回原数组——归并哪部分就拷贝哪部分回去
3 i6 k. z6 Z% i! l, R memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));: v4 X6 U `; c0 q+ n
}
* h& X# y2 |) B3 r9 ], S1 M R gap *= 2;
) O3 R: [: P% O# Z+ h }1 J7 t: w, P/ a, A1 U$ u- ^
+ z1 F& z1 p/ `, `1 h
}
( J, u3 L! V7 z% f1 N# `0 r; l; O9 T: u& f* R V: Y
1" d( i1 m, M8 T- C* w) j
2+ O9 M- P8 x' m( [5 M
31 _& I9 x- q9 [6 y- b$ [" b+ E+ ^
4+ p& ~, W# @2 `8 J
5
$ U2 y+ P( `$ \3 e6
2 \, v4 a0 N* z2 v8 s7
% ]8 \3 O% X( T7 c% |% n& I3 j# w8
+ [( S2 X& Q# _% B" n; V" ~9
8 P, |: r; h$ O. x0 |10/ ~$ R* V9 Z% a2 d# s
11
; ~' ~4 E- x$ `' O) ?6 Y12, y9 s! }+ L2 f0 p# Q
13/ b# V5 K% c2 X) `% \. M
14. t9 A* |+ E- G& n0 G$ a# M$ c
15
) ]. k7 x- r5 T$ T16
5 j9 r, y: h! B k# G4 ^171 h; \7 U9 r7 d3 [( r* ^1 i8 C
18& Z& e4 f& ?0 _! n% @
192 g3 D2 C1 a/ |( q- ^* b
20
6 H& m/ H0 u. v8 h7 R) e212 A. R9 k1 q: L! @# t
22+ Y' W( z p2 ^, z0 @2 q
23$ p* Q# {7 D* j, H1 b- @. o9 m
247 o7 }- _4 J9 i" Y3 Q' M
25( [8 E: a# j0 n
26
' D6 F# g- J7 }3 ]27
6 K" k; ~( ?1 z ?28/ }1 p7 W: C" F- a7 w: C
29
" e" V6 I! c! Q0 C, E, [6 \30
5 {1 I4 j7 r! e318 _ k& C: f* [( I% y) `
325 T# b3 w7 {8 _% @7 w7 o+ Z* `
338 O1 m0 U/ q% r/ s6 P
34
2 l1 G% f6 U5 L9 R( K359 S, b1 E3 s+ Y& x
36( V! W# m( `8 z/ f
375 Y5 y$ K5 n5 Y0 r; x5 q
38
$ `8 ^2 ?7 s' Q1 T5 f7 ~' t: d39
( n5 L. p8 s7 y; R4 w40' A$ v. [9 l: r6 X6 B) p0 x) y' R
41 {' K1 H4 j/ P) M3 X
42; U- F. z4 R, s: [
43. c- ]# z- }; q' _8 p$ ^# @
44" O% E3 f$ `9 O: L& y
45
+ n" r3 D/ O. W7 a归并排序的特性总结:2 T! D2 s6 A. o% H# s% m4 @
0 U! i: e( g: }" H
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
5 J& j- _9 u( ?时间复杂度:O(N*logN)
: R6 \/ [7 Z" W空间复杂度:O(N)9 b% _3 n$ [ _( W+ S
稳定性:稳定0 A2 }2 d u2 u# I
& R! V8 \; g5 ~7 Q) U————————————————1 e' D l {4 {
版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。# f% s3 h I4 d& d1 C
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
9 I; ?- }" W' W, n- I4 L; q5 E
; L6 l$ Y- h! @: z) v0 }3 Q
7 ^7 Y: ?1 P3 y: U. |; S6 B' d; d* W |
zan
|