- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563322 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174219
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序( Q; I& o4 g$ Y3 P' a1 u5 [
1 i' X& p9 Q# y) D0 B7 P H
前言
) b. ?) N; \$ x本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。! p4 A- B; n0 b! N+ D: W3 g
( z0 R8 C, `, j& }; h5 H
归并排序# Q. C& @( t: x7 m ]; d0 U; g' J
基本思想- |3 e: f2 N) @
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。) o4 |7 C) x, c# Q( F
8 ]2 u/ r i4 ~ K0 g/ Z" K! O
! u- ~& r2 |7 B. c$ O* F! ]
% @* R8 w6 U: e: u: y. O U 合并的思想其实和有道题目的思想如出一辙:
' M/ j6 }- X3 M8 v+ e( B2 |
& x4 r6 ~( r) m
2 A- z2 `6 W% M7 n/ w9 Q4 z0 q( r2 e* E
我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
' o+ ]. k3 w. f' ^ x9 Q/ j: ?# m7 W
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
& D. m6 Z- A1 W( {! A% R( M
) G: I, X/ V5 {$ g; rint* merge(int* nums1, int m, int* nums2, int n)
8 G! G/ p/ z) v( t( H2 z4 b{
q$ @$ P3 Q; M) d" I int* arr = (int*)malloc((m + n));! j, P& |3 J+ d. T/ Z1 H; q5 k8 R: ~
if(arr == NULL)' L" T. r- ]$ y1 ^/ n
{
\# b: u! }* d$ a% ?. j perror("malloc fail");
& F% l* @" _6 H1 m+ U return;9 T$ R4 Y: Y7 v% _
}6 w9 B5 m2 x R+ q! `0 M/ Q
: k0 F4 D9 S' |6 B int p1 = 0;
1 }. _% T3 g, ]1 n$ L& `5 h: a int p2 = 0;
( }$ p4 \' w. g3 S int cnt = 0;9 f+ }7 o) O ], J/ j# v0 [) Q, T
while(p1 < m && p2 < n)4 {/ p( }3 C! _- _. t2 a* N
{' _+ d6 v( K, S8 W# c# s
if(nums1[p1] < nums2[p2])
; s2 x6 } [/ l$ |2 c { V ~) L, g& R6 D4 |
arr[cnt++] = nums1[p1++];0 W# c1 j' @5 A+ l- Z" n
}
/ o- R f) v1 z" O+ n else
: t, C/ e( q8 Z B, s {9 J2 f7 Z. B9 H( X1 y$ g
arr[cnt++] = nums2[p2++];
- l& Q* N; Q' \ k( S* f }4 ~. X# ]0 p; j! j
}
7 N; Y- c5 U0 P while(p1 < m)2 _. h ?6 |; w2 ^. T1 O5 O, I
arr[cnt++] = nums1[p1++];" Q i8 K+ G. `$ [6 B. M/ z. q/ ?, T3 x
2 N+ Q( `/ q5 w; B' X while(p2 < n)! B" L, \) |$ q; ]6 I) k1 V
arr[cnt++] = nums2[p2++];+ A' g/ S7 A! ~& Q; V }
9 x$ c) ]! a0 [3 y return arr;6 Z0 }9 z& x# o3 ]
}& Z! C! {+ D5 K# o" c: y
; ~( a- |) u$ S& _5 N1
0 r4 u; z! @' U; x3 U% k2( w# k. h3 R4 k$ G- e9 R! P
3
6 W$ e4 q& d2 x$ A+ L- s$ D4; ^" Y$ x, j# d/ Q+ Y. b: R
5
+ w- f/ ^! w( s$ a0 M& v6
5 L4 Q( l# n1 E7
& D, i+ g+ W/ u8 g6 L8
7 X4 ?9 `4 B; M1 E( M j& i9) u! o4 V" U0 a% r
10
5 ~- b9 d: ` o- A6 b9 R. g11
$ K" Y+ ]* `* n# a( h( A9 O126 S7 O/ _) f$ D) A2 _
13
x' A6 {7 [" |' r2 q0 H# H- ^149 F" \% p. |9 I" P& ^/ G) t% g9 ]
157 V; F% U" H8 {0 `+ ^: z. w: l
16
8 c, `* q, ]" K/ B w2 h2 n17
& M% C9 d4 P3 A8 V( k# `18
1 G: M) O& S4 k/ z4 Y19
6 a; n/ P: N9 P! u. O5 `205 h8 O5 k ^7 \/ M
21
9 g8 T2 n8 e, V3 W/ l22+ y U6 T2 L. z4 x# s
236 N8 ~3 x4 U) b* n
24
6 h/ G, U& v2 D! z25. { K1 q2 J9 \$ o6 X8 z5 @
26
! g2 x \7 U' b9 O- t& e4 K) r27
" \( r3 c% B b0 ~28& S3 m4 F3 I& H/ x# x4 }+ ?
29
6 k8 s8 G- f' g6 [( G8 a$ c30
; _1 v4 Q+ V+ S N% v31
! s& X; @. d6 a; L4 q 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
2 g) F4 B6 ^5 `1 V9 R3 x4 ?8 [0 H& v; l
递归实现' P$ O' S1 x3 t2 C) r
通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。& V0 A# o9 o3 V- G& Y/ `8 c/ N
, x# f2 N7 k0 S3 X! H' |
% D; Y$ u c' T5 l$ R
: \! _0 Y. r* z' X3 y- _: o# `. y
9 D% e# {; e1 o) ?8 Wvoid _MergeSort(int* arr, int* tmp, int left, int right)
5 t: f+ i5 h$ S3 \{) E0 |; Q2 p8 g) Y2 E( ?: N" l
assert(arr);
* E8 T+ O8 m$ \- g9 c6 E' m& j( N. S$ r, F" {
if (left >= right)//递归结束条件不要漏了
% V4 S1 [, U) ~4 N; Z+ e9 j V return;; B9 A- a3 J. q
6 g) m; S# q6 ]
int mid = (right - left) / 2 + left;( W0 M- V; j8 Y( _+ I2 W. i
2 f9 |( [0 w6 b2 a0 M" i; y& g
//划分左右子区间[left, mid]和[mid + 1, right]
+ ^4 s6 E5 C) j% a _MergeSort(arr, tmp, left, mid);
1 {! A! e0 C) y9 A- D/ ]! H8 F1 y _MergeSort(arr, tmp, mid + 1, right);
( X' ]8 b6 b' R1 G; {1 ?
$ ~9 y2 W* E1 B& n2 M6 m //归并' r* c: r# y) V" D# \& C
int begin1 = left, end1 = mid;
( ~& n0 Y/ u. L% {5 P0 K int begin2 = mid + 1, end2 = right;
; o! _& @, |1 K3 n+ v int i = left;8 ~) j. w& C% c9 M0 P
while (begin1 <= end1 && begin2 <= end2)/ y, F2 U2 U( _
{! P. v2 a2 L8 o% C8 S
if (arr[begin1] < arr[begin2])7 s7 ]( F( x/ L6 \( a3 t1 G4 e
tmp[i++] = arr[begin1++];
9 u$ o% L1 W; s- { |% ]5 c else) T! {: y" e. g: h( Y& D
tmp[i++] = arr[begin2++];. K' Y% I$ D' w# Z/ F, A
}
1 |7 e, S4 D/ y6 U/ P E+ Y. d0 Y- [3 I6 R
while (begin1 <= end1)* N2 r& V* E$ G# Y
tmp[i++] = arr[begin1++];/ _( u4 T5 G, h
while (begin2 <= end2)5 h Q& g+ U5 }; x9 j) r
tmp[i++] = arr[begin2++];
/ y% Y. U4 w/ l+ j % K. B/ ^1 m, S
//拷贝回原数组——归并哪部分就拷贝哪部分回去
# B2 V! B7 ]" B l) l- ]# p" { //而不是拷贝整个数组回去7 N% G( L/ \- f6 C
memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));/ P( U+ C4 x/ Y3 ~
}' b% A" q* A, v) \; g
( E0 L; Q+ K1 {9 evoid MergeSort(int* arr, int left, int right)
' B% ?$ S2 T# b, ]: X! U{
|9 D/ Y- j7 _8 Z: k8 W7 l7 [ assert(arr);0 }5 P- r% t) X3 v7 }5 u, y
% u) Y7 k2 ?+ L* j
int* tmp = (int*)malloc((right - left + 1) * sizeof(int));4 q" z. C" g; \4 S# G1 \
if (tmp == NULL)' z# o' W$ X1 h% @! ^- R
{9 ]! t1 H; y- p3 F
perror("malloc fail");
. N% ~: i K0 D' j return;! \/ n7 @# C; v: |. K9 v
}
# A$ a- p4 W/ F: q) s
+ u# i4 ^5 ?% _ _MergeSort(arr, tmp, left, right);
& I' m, z s7 O1 k5 S, Q- I( h! i0 R
+ e* W% M k9 H; J+ A9 y free(tmp);; \7 K/ w/ ^- V+ h0 X6 W8 @
tmp = NULL;+ o% o! s) f/ j, @" l- ~3 r
}# ?9 i0 q' y! T( G) X8 J4 ^
, q6 Z& w2 A7 R- S6 [1
1 N/ A3 j; u1 ] S5 J27 Z8 E& D2 p( H0 I* G1 q
3
/ {: L2 j# N* c8 s7 F! h49 l3 A. S+ o6 O% v
59 I, t. H$ N# X
63 @0 U& \9 n1 `3 @; x7 j ~6 b
7
. I, [% c/ Z+ j) W7 X8
, V+ Y( D% J0 V/ w6 u. b9
8 X+ H3 _; Q2 z9 n* t* t10
. _; b. f. k- [9 r a11
. D7 I) K: n1 o* W12 l1 b$ k6 ]+ o4 O$ B" L
138 X' X: c' J% @
14: O0 M/ l0 c: P% ~0 g
15
/ _( f4 a! }( I* }: C4 y4 e16# C7 t5 P7 E- }! h5 U9 q1 `
17: C& R/ L; u" D7 S
18& c$ z. Z& [; P- z9 F: {3 b O
19
7 c6 J. i- q8 t5 ?: t q) y20
$ M) y y6 s O2 K9 @; I+ W9 g9 E212 f9 l. ^! Q" l8 T
22
# r, j' _. Z( f7 s) u* ?23
6 O+ \/ R) P) R24- o7 L" G8 j4 q T. j+ u# V
25 X: u% s7 A& k6 v: u( q8 }
26
) h& v# I5 d$ j) i' _5 q" F0 `27+ [ S1 `9 {, F9 Q5 P
28
9 S/ a$ \$ @% t1 V29, L5 I f9 @' Z7 n# P' i! V
30
0 e0 I4 \: t( U( R. `4 f% |; {" |317 J1 V4 L3 ?$ ]
32) e1 Z0 m5 _" `6 p- K$ \8 H
33- ~, e( [* }% v4 H4 X
34# e1 \% b; x X, U# s, D
350 p2 |$ u9 }+ V1 I9 J! O
360 \+ R% q& I- v
37
+ v; P& s7 g/ S% \387 u+ F7 h3 B$ G4 [; i' c
39
/ }' ?2 E3 o* o) u# X406 K1 A: j/ t: L5 s3 H0 J% _. n& ~
41$ |( o5 d0 [8 J! e6 N$ M
427 F! ?! m1 L. F1 [5 {
43
' e5 J2 {( Y. v44, z" d3 J" i4 q
45
4 q) J1 J! ^4 i2 n4 B; z) c46
- |- n: S6 ^6 D# c9 C0 q4 H/ ]0 Y47* {9 ?1 z/ }% q
48
0 e. |% L* ]* `: N& `3 @# X, ]/ M49
/ k4 a9 c) P; O503 U- _1 i% `7 L5 l3 D3 L6 X' E
511 X, I& |" Q* g7 w
非递归实现
1 C9 y* D* x- j 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。; A4 i" B0 \- l0 b. d) I C( |
% A& a- V- f W5 G R: Y: u7 d
7 n7 d2 C0 c. H
2 T+ v& b5 h( r- a# t 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
8 i* l6 P7 a! N3 @1 u. z
1 t7 u5 a; J1 [9 k$ y7 C 还要注意区间的取值,每个区间就是一组,就有gap个元素。
. i$ A7 b- }4 b
( Y7 ~5 m) |. L# s 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。- r( F" X6 l/ }# y, |# N$ V' w2 Y
4 O+ Y* h$ v" f; `% z
代码实现
0 C) ]6 W6 F+ J! b4 }/ @3 P
, }# S {/ K/ mvoid MergeSortNonR(int* arr, int sz)4 Z4 W) {# B4 ~7 I: d
{
' F2 H r) b2 v4 {4 _ assert(arr);! S% x K$ m) m4 m% \; T+ B
1 p' n- n. P# T5 I' \2 h$ |8 T/ { int* tmp = (int*)malloc(sz * sizeof(int));6 E/ I% u w* M5 {6 }0 R
if (tmp == NULL)
: ^( e# B; m1 E) u- L {+ P. R" Y7 y3 _/ e3 ?' x. q
perror("malloc fail");! W$ P# J3 A" \- H, S6 g
return;
& r; Z N+ X2 |) \& ]. ` }
5 ^! W0 v) n; d s; W& z- G8 C; N3 |6 `5 `# \/ R) S
int gap = 1;2 x* x7 @ Z: C( _
while (gap < sz)1 z2 q/ C" q$ Z) I3 P9 R9 p
{
. @7 C: f! G E) ^# _# C for (int i = 0; i < sz; i += 2 * gap)% w; t! I8 Q+ H) p( K
{
' M; g$ }2 B1 J' Y$ a5 \+ z! K% z int begin1 = i, end1 = begin1 + gap - 1;
2 V/ p% U! M0 g `1 {& b% w" w int begin2 = end1 + 1, end2 = begin2 + gap - 1;+ u2 G j& Y$ @! w1 d2 D( D
int j = begin1;
% y+ d, ]+ Z& ?: E5 `
' X; g1 I, V4 d- j( i //归并
+ G }* S- b( U8 _ while (begin1 <= end1 && begin2 <= end2)0 S/ G# d7 E1 P9 V3 t: S
{
' x: ], B8 ]5 c% w' ]. y if (arr[begin1] < arr[begin2])
+ l" W0 i/ t5 [ tmp[j++] = arr[begin1++];3 b$ m/ S0 d2 ?5 ~8 `
else + A2 _6 y# G% F
tmp[j++] = arr[begin2++];4 g. O/ v7 C6 f: K
}6 f9 J" y" q% K* S+ d* k2 \- h
K/ S( g* e( h! w3 |8 J1 ], a/ y4 P while (begin1 <= end1)
, G8 U3 P/ C3 E1 Q tmp[j++] = arr[begin1++];& f8 {# v+ ]% Z* q% P( t( s
while (begin2 <= end2): l- P. B0 z3 E4 X+ a
tmp[j++] = arr[begin2++];
3 f% q; Y2 n# D M6 K* C
" U. T3 q) f( y; r! L) N //拷贝回原数组——归并哪部分就拷贝哪部分回去2 ]; r2 w3 u7 W+ i! J- }
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));: g% z( [+ n4 c, S" h5 i
}
4 h9 K, }% r: h gap *= 2;+ _2 G; `3 S) {% x
}
9 [4 _" C" _5 Y8 @. s
" F( D( \( W c6 D- |7 O9 G/ e}
# C0 o" \0 G n/ C: A; m6 v: ?
1 r: H: ]% A4 T, s/ t1
- S- Z* R. Q9 D% F1 \8 i2
; ]# E* V/ V$ z Z# T0 O* K4 {3) K6 u. T0 }& ?) A4 U& z: O0 ]+ h
4" {; s. f- R: e7 ?3 c
5 J& o9 _/ y8 H/ t4 l
6
( K7 \" a/ N. A9 G) u* [" Y2 i9 [74 ]7 w" K& h4 w6 _ L* @" \4 L$ |
8
& b: G. q- r$ p. U9: {0 t- d$ x& ^. e1 d7 Y: Z. p9 _
10
$ p3 |6 O! J A% j2 ^) l11
; l, g* p i8 A0 ~, L5 W* u12
8 d( [1 Y! L' l: r( b( H4 W' J13
- h* j" h* b: \# `7 d9 r149 D7 }$ A3 s( w9 R) k1 P
15
+ B# {. Z/ B/ i4 C16, \) [+ x1 N5 n6 \* O/ x/ R
179 B( ^' i% L; j
18
* }) p# T/ u" g: i g19
( R, j" a0 Z3 \: H20
' F, L6 P. w( B6 S/ _% P. ~219 \+ K, {& l Q% q! h: z
22% n6 g, [2 S. P2 N
233 x0 o! S# n0 |+ u" }: M
249 L' R' F/ {# e+ a
25$ f, Y# E! L; z! X
26
" d! b% n9 V. |9 H! p27
* t" G- I2 T1 d# }% Y; Q289 S# W7 z1 x6 }, [) O
29
5 F: Q- i, ^6 r) j F( ]& e# T& c30. ^; t& E& Z% P; N* Z" w! W8 D3 B
31+ S- I! B4 y+ o, C. {
32
% b& ~: M# s7 Y" h' [# _33
; U2 O! {& L h- I# _% N/ i34
; ?* ?0 K* @3 X) G35
( A, }: H8 [0 W& g6 n7 S- G36% y+ x7 R' M: i/ T6 p, V9 l
374 a* j: D/ d- E' c# A+ H: C' i
38
& L4 \. j x# p1 E39# i4 ]# }7 B6 _7 h" I5 G
40
. V* ? }/ J& u8 _6 H41
3 x5 f2 x q: }, T边界问题
4 V( l& r* V& G. E( U 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
9 q o; z& J6 m) k/ J+ x# {1 D2 z% M( R9 E Y7 m* G. e9 a
举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:1 Q. U. z+ ~; @. \
9 s* [7 w- a, x5 Y+ S9 L
4 E6 A8 k% u, v: p& m7 U8 z
: a# b( r$ ]1 Q& F由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
. V3 D" n6 D5 u, k# r+ j! d# R" s. E1 k7 p. `2 s
第一组越界(即end1越界)* l) n9 D) D0 E9 L$ v
6 }5 J5 n! o3 \+ E& c D1 G应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。. M6 U0 B4 _1 N+ t
- ^6 \& U p8 ]' z+ b! z: M/ Q
第二组全部越界(即begin2和end2越界)6 }" v$ n9 K& G3 y
+ A1 ~& p) G+ U( T
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
) Y' }$ c" `# c$ b1 F5 t; ^. S! o3 [$ U. v
第二组部分越界(即end2越界)0 r O# [% E$ d8 O# y3 V# u
" P( l! A, |; O% z应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
# }% A ?3 g' S0 E2 U8 k8 `1 c8 O& l- X
其实第一种情况和第二种情况可以合并为一种情况,原因:) q# ?5 T# o" [5 f& b8 b
0 q$ A2 G2 s& v1 k+ n end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。: S- d$ N ?; T* O! s! I
! i) U6 l; M4 P7 {6 P- P' N 拿两个数组试一下:
( S' O1 {% \6 K
; b& [9 g. E" P: g( }& v$ f8 z0 o! x2 X5 V+ z" O' w
7 j- C8 p7 I2 h, @! E+ H
3 V1 m- h0 `0 V% u8 s
& W0 r+ l5 c, U# N& Z7 ]代码实现
- {% j/ D7 E" |
8 i) C6 v' _7 k+ W* p* rvoid MergeSortNonR(int* arr, int sz), I% Q) t) ^( ^# ?, b0 N
{
% K0 d1 G( E5 w7 M' |7 p( `& l assert(arr);* f$ `* @6 k( V! i- @8 ]- V
6 a+ ]; d5 u! x0 O
int* tmp = (int*)malloc(sz * sizeof(int));' v( p2 x) u9 o6 t" Y9 q
if (tmp == NULL). x0 v! F6 ?- s: B. k! Y) ~
{4 f! \* h0 N6 y2 l0 Y) \. ]
perror("malloc fail");
# W% A) a. G& [" O1 K/ O return;6 z g. k M% t2 `. n
}
3 I+ s, j6 y/ e5 F. |9 j' ~, \, }: R
0 i8 X& E, K: o0 k# ^; g" }) m E int gap = 1;
, M" J2 Q6 @1 \- S" Q while (gap < sz)" ?. v4 ?; H# P+ `4 t
{
! V& M, b q/ U/ O6 | for (int i = 0; i < sz; i += 2 * gap)
6 m5 Q2 v, |- W: m& i+ m# [ {% Z( j5 J% {6 u2 i j
int begin1 = i, end1 = begin1 + gap - 1;. X6 d" l3 o& b$ n9 ?
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
7 E) p- n% S; T7 o$ B# X; L) b/ A( T int j = begin1;
1 }# u, i" m" C5 f# y6 W6 l2 K8 e //越界检测
0 }0 S* v6 z# j. k+ D% h if (begin2 >= sz && end2 >= sz)5 D! k) M: p/ q5 }, j; b- ~9 v
break;$ G: H; E) v7 w6 P' v! i
if (end2 >= sz)
* Q% ~5 z! n' j | end2 = sz - 1;* D. i* o: C% Y7 j) ]
//归并
6 S- x% H& Q7 o4 U& q* w3 J9 T while (begin1 <= end1 && begin2 <= end2)
- O0 H6 C& Q* s" Y; M- c" E t2 r8 E {) L3 {# i4 T, G* o5 n
if (arr[begin1] < arr[begin2])
% C9 D! \7 o' l. l8 b tmp[j++] = arr[begin1++];3 z# ~+ E' M5 A
else
/ R4 }6 K9 H i. t: J4 B9 c tmp[j++] = arr[begin2++];0 _+ H) ^$ \- b( {6 N& [
}
! l- k& a+ L$ L- g* C6 j1 [2 z% a, B* D8 K
while (begin1 <= end1)) ?( ?% G# H) q/ {; x& F
tmp[j++] = arr[begin1++];
! q: k1 s9 I" L, x. _- A while (begin2 <= end2)
& ^ m. b2 k' S1 t9 X tmp[j++] = arr[begin2++];3 ~3 s3 `0 m( q9 B. a' F! p
0 h+ ~2 A% Q/ m3 r //拷贝回原数组——归并哪部分就拷贝哪部分回去" E3 M) v6 n- d2 y
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));/ U y% P0 I" G6 [
}
4 j7 b. Z" @0 h3 K! [; [" } gap *= 2;- X7 ?! Z* o: u5 A, q
}) j# D5 p1 C6 U& b/ O! z5 g4 m
b; Z5 k: j! {& S$ P}
) X$ x ~ W3 l' g- @3 J4 z/ R. o, E
1
# r8 ~0 b8 e' A2
r5 [( B* U2 [- U9 U% L: w, a4 D# H3 a7 H3 r' I* t) ^) R
43 ~: x9 R) S/ q3 N+ y* C
50 E- o% i$ Q! m8 p# {0 v
66 o) V4 V% i8 Q/ D# d! U9 B* n
79 R0 B9 }0 B: U( B. g
8
* g& C; I( P% l" D' y/ j1 e. H9 m0 i! @; x3 i. _4 C& J
10; q" {( M+ N1 Z/ H$ f% E
11
0 _; w3 ]( ?0 z- c Y, U' L9 b$ g120 _5 u9 i0 e7 ?: \/ ]. P4 m
13
: v( S0 Y& B# }6 k, X: i14
9 [) d: {) p" S. z8 w( y, Z15' R p" d$ w J$ P9 Y/ _% k0 H; S
16; u# J. I. i c2 j
17, V& E. F/ P. t" f Y( e
18. ]! |; `$ ?3 }% G
19! X! K* u9 X4 s) d
20
. U# B9 `' d8 C) A21( Z5 Y c" j$ z* `( T5 B! V+ g
22; ]5 } g! ~0 d3 p; _
23
2 |1 [/ h/ j5 C! r- D& \/ |24! U5 Y# ?6 ^, k8 }) I
25
7 L. X0 s* P9 k+ V: y& w4 k26
, Y6 x$ p$ D7 f27
8 b) e: Z8 V1 k1 R8 L6 _28- N; `. `% z# w; M/ a5 i) P# O7 G1 j
29) | V* J$ Y6 D) P7 W5 s
30
+ n: j5 y- {0 a4 z+ H313 B* l% j- ]5 w) d1 ?
32
) v6 V; q5 A ], j6 \2 b33
" X" w: Z0 M$ G" i B34
& y* k. x0 Y5 C/ |1 H$ P, G! D35
6 E# }" d) ?7 L" ?( x. U5 ^% f36
) S7 s, a1 K5 @37' w9 U! U6 o+ E, {" R
38
% h( ?3 T1 e* f R( z39
0 E7 Z. ]$ \# X, X- M406 ], M0 Y4 N( o" z8 h# y
41- d. b; P, r' G: q9 V
42
4 U- _5 Z8 |6 H0 r; v6 d3 Q43+ k! V4 ^/ F8 l9 e2 `- R# _+ i
44" A6 j- G& v, N- M
45. g1 B. x5 e/ s9 f' ^
归并排序的特性总结:
! u: x) E. e4 W; Y9 S( u7 b; B& R( q; E% u+ i7 c5 T: n
归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。! o- N v7 h( I/ U% L' A% L7 q1 U
时间复杂度:O(N*logN)
+ c4 {5 n2 H2 U8 I% }; \2 }9 a空间复杂度:O(N)
* J. W! G6 k3 K# H+ h( C' J稳定性:稳定/ S5 i1 Y: M( t- A' p' h" j! X2 t
( c& X) V: \& E8 ?# O& o
————————————————+ ~. }6 X0 z, M' ?
版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
5 h; `; Q" s& ~9 E0 P5 {原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657- ?" v2 C2 s% m, E
N3 ?& A! X5 |; \( f5 p/ C
5 p8 n6 q+ w7 b' Q7 w! e. n" T |
zan
|