- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564443 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174556
- 相册
- 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 e* P8 F7 u" \) {7 `% Z5 J* o5 \+ k+ R3 U. p
前言
5 o- Y, G- Y, Q本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
) v3 s- ?, `1 J* S/ c: x
" c1 Y6 V4 I# @归并排序
4 y9 O1 \1 K+ T, t2 z基本思想
% }5 Y% q" H! o+ A/ `9 e, { 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。- j; D' @9 n0 k; ]& i/ O0 }3 ~
+ z; \& K8 w2 g0 I! E4 v3 w* ^$ M1 B. d1 f0 E8 k1 Y; p( m L# r, D
! ?4 k( n I7 F3 }4 _& ]- a6 B 合并的思想其实和有道题目的思想如出一辙:
' V, w2 l0 |3 l
0 j9 M% B# `3 X* p1 U: S. I; }! ], w9 t, Y8 X( [9 J( `
6 @3 K4 e) x S: S 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
; G8 X* @% u- p
0 F8 ~+ ~9 o3 [- j; B" k3 }[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]; R" s0 X, d7 \4 j; X# D7 W
) N3 C L+ [% {- C# ~
int* merge(int* nums1, int m, int* nums2, int n)
& Z4 n; E: j8 L! }6 j, p8 i, R{3 @6 w# X) H# B4 [0 Q* J! w4 a
int* arr = (int*)malloc((m + n));& r) H& O! J' } T$ Z7 \
if(arr == NULL), J" E' g( F4 \2 R' Q, m
{
: Z$ v+ j% }; _% @" J5 a; } perror("malloc fail");
- [4 q, X, c3 E/ w return;
) ^! X1 Q. ~3 A }* o4 A1 d% Q' B; a+ U- T
0 s; b7 f7 x/ n% D) l9 ?
int p1 = 0;
1 d3 k( i$ Z0 f! j$ A int p2 = 0;: D. z( C+ {7 [: L# h
int cnt = 0;3 n0 D# ?) C$ ]5 k a: n$ |6 v
while(p1 < m && p2 < n) D2 Y: |0 Z6 N. @9 L9 t
{1 ~) P9 S( V) ^* R
if(nums1[p1] < nums2[p2])
M5 T/ E ]5 w e' J" v5 J; ? {
; k4 ?7 E: t8 {% z# p* w arr[cnt++] = nums1[p1++];
; O# ^8 T9 Y$ C. P: K G }% l7 ?) I5 `, I; y
else! T* ]5 l, j9 X |- d4 @, u4 ^
{
9 ]3 a4 L% E/ ]7 |& g arr[cnt++] = nums2[p2++];
& S% u! V% e# _1 K6 b* U }: `) |6 m2 n4 q% `& P
}
$ i8 v- s- c$ F while(p1 < m)* d4 @2 B! X, C$ `! O% U) o
arr[cnt++] = nums1[p1++];- A$ }/ V' c o d' i
4 y9 d; z1 W+ z1 ^6 F* P3 f while(p2 < n)% m9 G4 G5 H+ ]) a) ]8 P8 h' [
arr[cnt++] = nums2[p2++];; g* K- l% O, R0 {3 K+ X# V3 }) L
" D) t% j/ ~' m return arr;
1 @/ i( d2 t+ R$ [}
% l" o' r, z0 g" C' T
& V3 x5 P" G8 F* f) x+ P1- \; R8 i. m& ^3 K1 ~* Z( V
2
( p6 t2 }3 i6 B/ ]3% w6 O& O h8 }" k F
4
! w }2 t0 G5 K" P2 L2 Q52 m3 a( U! b) Z4 _6 \& P
65 Q/ G) j- g, }8 X, k% O. b, a
7
$ U; K# ]/ a5 U" U; i& V8
2 T, D7 w$ F- k. k8 v$ \92 K7 l/ O3 @+ z% L: s' |! g
10
4 o$ j i! m! V11" y+ D9 Q/ W: L8 \
12
, r/ c- V% Z. B. t3 `13
& X" h! X7 P0 W% h8 ]* B14
2 T5 f" a7 C+ w155 Y% v, Z- J- p, E1 l8 \
16% G# Y0 ^% N6 J( r# e
17% D4 D* X3 b! I" C4 |! ]4 O$ b
18
1 D( N9 q' e& _* n- K7 e& L19
' l0 F) q2 }2 L/ S3 k7 \20/ m& V( g7 @) r" w7 p$ h! F+ o7 T
21: H) r2 k1 V) z4 u
22- B2 u0 q/ L& i
237 t8 |8 T* j+ z4 k* L
24% y8 w# x4 H( p7 ~+ J2 {8 r# i
25
: {+ J N m$ q2 z* u263 _! n; G% U: G7 p" s" r. v
27- ~3 T2 J2 W2 [. h
28/ T1 i7 k5 ~% b1 u/ M# d9 e' @0 A
29
% ^/ t; |1 J, C1 {6 U1 g( K30% _# m6 E( U' W9 `3 w# L# z
31
, P, x7 r) H6 `2 |4 u/ B5 y7 ~# @ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。& q8 l# J) P+ z. H4 y
5 [2 a7 |$ ]# ~& b递归实现/ S: Q9 U. V0 K5 c% c! o
通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
7 A0 {- X, u' C2 }- ], Y# e. F( q. v
) H) b2 t1 [) @$ h! ]4 t# p3 Z. [- d5 a
0 s& J3 t; @. X1 b
J+ ^$ j, r6 ^; H6 z3 z$ Vvoid _MergeSort(int* arr, int* tmp, int left, int right). m( E9 x8 ^2 l+ S
{ ~( U9 w9 N- U" A8 e
assert(arr);
9 X0 U. T" t& y ], q" T3 y" U3 }" W5 g5 F/ Y+ l, ~+ r3 k
if (left >= right)//递归结束条件不要漏了) @1 A+ ^+ I3 S+ ~4 ~
return;
2 p" z, \* u5 C' ~0 {4 P! L
2 k* [9 F9 ]" g' p int mid = (right - left) / 2 + left;5 R6 h5 b( f4 g# T3 S. n2 p
N/ V# s/ `; s; f% h' d9 ?" d //划分左右子区间[left, mid]和[mid + 1, right]
+ O% A- B- R& ~ _MergeSort(arr, tmp, left, mid);
8 B4 I0 M6 e$ T8 S1 ~0 x5 ~, y _MergeSort(arr, tmp, mid + 1, right);
) y! ?" A5 x% O( o: M
% O- ?2 x$ o1 U1 a2 m. o //归并! O, _3 H1 W6 `. d+ l( m2 f
int begin1 = left, end1 = mid;
" w" t! Z7 K# S1 {/ k4 P) U int begin2 = mid + 1, end2 = right;
& Q5 t5 r* E2 H7 f0 a8 y# ^3 ] int i = left;
V2 p5 v# Y5 E5 t5 Z8 j while (begin1 <= end1 && begin2 <= end2)1 }5 @; B' d' v
{8 z, M7 x$ s+ I3 F0 g
if (arr[begin1] < arr[begin2])1 T' V1 ~% i+ G7 @5 o% a {1 z
tmp[i++] = arr[begin1++];
8 {) K5 H: j, X$ | else
! T9 @ T5 v4 L8 }. P0 y; Q tmp[i++] = arr[begin2++];+ P# u( X5 i% p7 t4 @3 ^
}! E, n0 p5 f7 }) P( S0 L
" l+ m- ~. o( v3 Z# C while (begin1 <= end1), z% U! ~* `$ P( ]" `( V) p
tmp[i++] = arr[begin1++];
3 M& [2 q) J3 x" E9 q+ ?$ J8 R while (begin2 <= end2)
3 ?$ {" h( t5 w8 x6 p tmp[i++] = arr[begin2++];# {9 p k' }: @. U; R$ G* n
5 d5 `; l! ^/ m, R$ n //拷贝回原数组——归并哪部分就拷贝哪部分回去
0 |! @' b$ p/ @, s; d //而不是拷贝整个数组回去
' R3 O4 D. L; I3 h& _) a memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
# D: s5 Z* B* W}
, p) ?: t3 x" [/ i& i) n7 S1 M; t2 Z# N" K. t
void MergeSort(int* arr, int left, int right)' x& G- u! R4 Q% v- q; o
{
: G3 ^. H0 B' l5 D+ \5 ^' b3 S assert(arr);
# C; v. F/ [) }5 L$ I4 I1 ?; N- ?
: {, c% v: v: g& G; U int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
- j# R7 ]. M* S if (tmp == NULL)6 {- |* n: e$ B7 Y& A
{. x1 z5 _; X5 V, j5 y. ^& \
perror("malloc fail");; V" b1 q, X+ ^* V7 Z
return;0 H# J: L. P8 g1 s3 C& ~% N" R
}: j+ W5 f7 E7 B
/ S$ a8 W6 F5 E, b, y; ^: V: @ _MergeSort(arr, tmp, left, right);) X1 T* f8 L* F" ?, T! M
4 x: l& i8 V' Y# |0 [) s) {& v, b free(tmp);
\: {* b' y# E% c% E: R7 ~' d tmp = NULL;
* c2 Y" F% I$ a2 Y}
; P N1 z+ x& F( @8 o) @: \: o& P6 N; U
6 ^0 w* P+ F6 S6 ^/ o2 p1
! C' Z$ M' z6 p. \. H. a, O2 g! }4 n( U% A- F$ J3 o8 p
3, F. D- |4 T" U* L9 M
4# p4 K( H* x' M2 }2 _0 U* e
5
! B- J8 k8 x9 {* S0 _8 i6" W9 F) `/ E$ o0 l/ z0 u
7
' Z$ Z5 c/ a) ]. ^8" h3 a) _) u7 ]. X" v, @2 {
9/ c. G6 `6 D/ m9 Q
10
7 i& T/ Z- p% |- {, P$ h' g5 a11, w( d5 I- e% c9 g/ g+ V" P+ S
12) J" o" z+ v4 n: l3 }" I! c
13
, ?" K1 q' H* F147 k7 M, l5 S0 g' Z
15+ W* P( ^0 G3 b
16; B6 i9 B3 z" o' a+ J
170 H4 d7 g8 I6 Z: C0 }3 y3 q
180 T- G/ v6 a. l
19
4 \& c+ T* m7 w. f, I20: i2 @' l' o$ k, C; o
21
; ^! C7 l) S8 R; a22; T2 V& Z, c. K1 p, x/ E: H1 O
23. z6 d O0 Y% b6 d* N7 [% M
24# D$ p1 }& T! B% P
25
/ s" R% m- e; o' J268 y: [8 h( j7 I; {' d7 q
27
( Y* z6 T# N! h* S$ S28
% c) p( R+ Z) h2 c& }298 A/ T. F7 T) C* Z
301 y' H7 B+ u8 k9 P. N; R( {
31
7 X7 E8 v- r% y: X5 G: R* \/ Y32; \ K) K# x$ j2 e- A
33
* R5 i6 Q# P" s! @' m8 j7 p" ]- A34' h( w; i! U1 ? R
35: E( w* }# I% v& p9 M! X
36
# Y. n5 T+ U. g1 K37& U0 Q& P4 e, w4 O! W
38
, S3 Q4 S M4 i39
( V: l$ ]0 @6 X2 D* L- x40
7 P; c3 X0 Z9 v. ?1 D0 I/ L% Q; C5 V41% y6 K+ t4 L8 ]# N5 x
42
6 t0 |/ j$ [0 V0 e( b43
/ h1 ?9 v6 d3 V# l" \44
0 ]8 i! s' A" n% W4 J7 e45
6 Z- n5 _- s$ q/ I) A46
, F$ H* t" F" Z47
3 k* E7 D. s( @# w48
% D+ x$ f' \/ F; ?49
; A3 U. @( ~ ^5 G; z50
1 k1 x8 J: i: m7 i+ {. y8 g51
% b1 t) O1 l$ h$ ^( R" ^非递归实现
6 g1 R( R! t2 \ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。4 Z7 _' g2 z( q* O) w4 J, i
/ l3 G' @; \' ?+ t: N' o* P! F; F2 J
4 |4 C; ^% \! y
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
6 `( d5 s1 q) w: _# D1 o; O- W: N0 q7 Y
还要注意区间的取值,每个区间就是一组,就有gap个元素。9 y; V: j$ j) c ~0 L% G3 W
2 p' k1 @, ]1 ]# h( ^6 M3 ` 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。- d a, e) N( y6 h3 R
. i7 d' C4 o! y& w- y
代码实现
. m. ]# ^6 X+ J+ K
! g9 R4 z' S: dvoid MergeSortNonR(int* arr, int sz)
) a1 ]- e" S. p9 z; E{3 z, f; N6 F. ~; O4 y" N
assert(arr);
1 I. V M3 f: ^, L' p( r8 o7 A7 q7 j' R; Q9 E+ X4 k" }
int* tmp = (int*)malloc(sz * sizeof(int)); z. O3 g/ G, i+ ?" @9 s1 D
if (tmp == NULL) m/ }$ \5 V, @
{
" s9 Q3 b. U! G& x; L perror("malloc fail");( x( _0 j( Y7 I2 L
return;* H6 K# [7 e R( Z* e# @7 m& G
}
# K( f; F+ h% J( r$ F3 t6 E1 M/ Q4 M* Y, b& K2 F! Z
int gap = 1;# [9 o/ t7 }: m( T" i% E4 x. \' d
while (gap < sz), d/ u1 e) K8 e4 ]/ A# o. o5 b+ A
{8 ^7 G8 w( {9 z- k8 d
for (int i = 0; i < sz; i += 2 * gap)
, y8 ~( i: j4 p- L1 {, H {6 M2 d# F' W( T" q
int begin1 = i, end1 = begin1 + gap - 1;5 Q/ s+ P1 w( T( u+ o
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
0 g2 O( n# H& |6 H+ ? int j = begin1;
$ y" b! {5 v5 V/ H, f. C
' o, V4 z; S8 F* {8 X7 l5 { //归并5 \# b/ M" [" g0 U& \
while (begin1 <= end1 && begin2 <= end2)
! D; A/ `9 |: u0 G- V: }; A# }, e& I {
( O- l# A$ y" }( k' b if (arr[begin1] < arr[begin2])7 U! }9 Y/ V/ g( V8 ~
tmp[j++] = arr[begin1++];5 W* ^; J9 H5 @% ?, I M
else
* _4 x' t! D( r4 b4 I: Q" j tmp[j++] = arr[begin2++];
5 N, U* e4 ?% R5 _ u1 X }
, B. N* i7 o9 U' `. h ~# \
5 Z4 h1 _2 m$ @ v: V while (begin1 <= end1)
: e7 h$ U1 `* Y4 w( T, n2 l e tmp[j++] = arr[begin1++];
4 X7 [+ O6 k, Y8 c; v0 R% e while (begin2 <= end2)% V4 Q( p% O4 v+ _( b
tmp[j++] = arr[begin2++];
! W$ z$ A7 e* y# ?, m% q$ y2 I" g, v$ P/ N7 {& f6 j/ a ~( S3 _" y0 D
//拷贝回原数组——归并哪部分就拷贝哪部分回去6 X: w" O, m0 B# e, d1 t
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
: p% g2 c3 x$ C& _: `# K! d9 R( ] }
2 b$ G" y0 R- K gap *= 2;
+ f* ?; ?6 F( [+ S1 b/ S& @+ q }' c0 _3 Z4 S V! @, D5 h
- p" p$ G, W4 x, ~. ^3 y5 Z}# Y- q! b+ J. T! m+ Q; E& Z* m
3 D7 p5 \6 z% R4 L" U" k4 S
1
8 { v1 E- p$ w% I& F( C& S& E/ V! h2
( e' E3 q! V, w+ l2 i33 L% _9 E1 O, t) a0 D7 u
4
* i- ~4 u/ O$ `9 q1 ^$ P4 h5& H I# Z) G) I" P3 d* X# Z; y
6
; D# N% h; v9 t; l) S7# L& h9 n7 W& ^# |1 K& K* S
8
9 ^+ O! W l- o( F7 F9
, \4 m% V7 j+ N* y2 t. B10) X- y$ q. W5 ]- S. }2 K
11 e9 f8 R% e/ s. K# D) W9 q" m1 `
12, l& p9 W+ x' i
13
9 H9 U! E' w8 t, B14
1 \6 I3 V X, l f6 j& _6 A15
( Y5 D. l, K$ r7 P1 [166 l/ b2 M8 a0 k1 J* b
17
; P' {/ F7 `" x$ E18% s9 f/ a) N% W, P( y- |
19$ A8 ]8 E. @3 w7 r% D
20! J+ S* c* y: a& ~( A
21
' S, K6 l s! Q0 a* J22
" c$ Z0 B9 ]! L* V9 P231 d; Q+ l4 Q, @ v* h
24
! Z# ^4 e; h5 u* @ b- n- P a25, \' e8 F7 k3 Q9 f) }
263 d- _ Y# [* u# H- o6 E3 j
27# F8 @4 N" U& k* m# z
28" M, e: f: O5 m1 |, ?3 E
29- D& @3 o" V) `$ h. ~
30
3 I( Y% G) h: R6 v& d5 _31
/ y; O3 z+ b( J1 J32
3 X' c6 y9 B! G$ G33; j: ]* w& U% d
34# G; X# A. w2 Z4 ]
359 M/ z0 X& ]" a+ Y" E/ {
360 j) E9 v( J" I3 U6 O9 H
37
$ H+ j; J0 O. U0 _9 E38" a( j) \, Q* {! W0 @5 P; I
39- b \3 @+ l3 ^4 Q' Z! C
405 f$ B8 U% v- T* c/ C! r
414 E, W5 @" z% J% M7 n: m8 B" p
边界问题
1 \' g& [9 H; Q2 A* u 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
5 f. B4 ^( i; l% m5 T
4 k0 Q. q* g# B举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
4 d ~! ?' B/ I( r1 z) Q- O* M& G$ f, b) H$ U* a
& m2 L: m6 c) j, Z2 q6 k4 H: {: `3 ^- n
由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
% y7 E* g5 p8 ?, X9 _; d* h7 M/ E& Q% p3 ^
第一组越界(即end1越界), Z6 {8 i$ }. b" T X# W0 P- P( t
: K: `5 ~# y( Y. `1 S
应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
4 M" s4 z6 W) T! C' @+ L
% x3 }* A8 W, y3 m1 k+ s第二组全部越界(即begin2和end2越界): ?$ B- U9 h2 Z$ t. F+ u
, h* Y+ V# s. J4 y应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。 Z1 a H. a. @. b
1 o* v% J; h3 i: m9 n) Y/ ?
第二组部分越界(即end2越界)# D9 ]2 h! b" y: \1 [7 _0 r
* {8 ?& Q& a$ A' R+ {应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
a* G P V6 t- f( |$ N1 W. ^7 X6 T$ @
其实第一种情况和第二种情况可以合并为一种情况,原因:
2 N, {9 X$ e' h( Z: j) R) V
0 h# q8 ?, b% _ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。/ ~1 R* g3 H; ]( J7 W: g }. B6 A
$ O2 x# C" D6 C1 q. |1 j( x4 N) L* V5 ]* v 拿两个数组试一下:
1 W& x* [( @5 \
, c" F9 L4 V+ Z; m: J9 h; L p- a* k- B7 n4 G* w3 T
/ y: `4 @6 V- A8 I: v
7 I& x o* {% R8 E
' d5 Q) @0 Z+ E& D5 [2 W- d
代码实现2 `: y8 [5 ?& T! C2 f' l r
7 D6 X( H+ I$ `7 wvoid MergeSortNonR(int* arr, int sz)
, j; _2 l3 x) p( L# h- Y, x{ y% G( S# U4 i$ H, i; e: E; b# S
assert(arr);
; D, o; `3 l$ K9 L" r" q: s, L0 A7 ?% ?0 N! W, R
int* tmp = (int*)malloc(sz * sizeof(int));
8 `5 {# D% c. b% C. W if (tmp == NULL)+ } [' ^! b, w6 j) \! ]
{% H3 z$ `, E3 y. W
perror("malloc fail");
5 R9 y, Q a# v' ?# I: [ return;
" n* \" |& r0 j2 `4 w }
+ h: c& [3 Z- c/ @- a! g( ?" r6 j$ a9 G" `1 I L
int gap = 1;
+ {) L# d: { h6 Z6 I while (gap < sz)& Y" N7 k- Y( {8 A* E
{4 ^5 @8 P3 l! z3 P, y1 C R
for (int i = 0; i < sz; i += 2 * gap)
; b' [4 Y- F2 {1 w" |% a6 R9 i3 w {
8 W& P0 z: U9 w" C& t2 W6 ^' H' k int begin1 = i, end1 = begin1 + gap - 1;
1 o6 x' H5 u! x4 x! ^5 @8 t" H int begin2 = end1 + 1, end2 = begin2 + gap - 1;
- M: H, r% a$ s6 k0 X: F int j = begin1;( f8 N4 Z) T/ o6 V: t9 S9 g' a
//越界检测
3 i# M; Y1 t" h if (begin2 >= sz && end2 >= sz)3 W/ r. C: T c3 M2 k$ g, C
break;
5 y3 i& E% Z" b% I if (end2 >= sz)7 A( T0 \5 x8 {7 x8 j
end2 = sz - 1;
, l; t9 I2 Q) D. \7 o6 m& @ //归并9 v7 m5 Q$ ?$ r H$ a+ f: s
while (begin1 <= end1 && begin2 <= end2)1 |7 X$ Q6 @9 f- R& k& F
{
, j& L# M0 c* \' t if (arr[begin1] < arr[begin2])5 G7 O9 z ^; H+ K) E
tmp[j++] = arr[begin1++];) s M1 M' j0 u
else
1 Z6 A3 ^' y6 t tmp[j++] = arr[begin2++];7 D5 m: W8 c4 u* M9 i5 \( F; ]! X
}
0 Y& @. K) D7 I$ e) P) m, u4 O% i% \- r! L1 G& a }& r# V* w; |
while (begin1 <= end1)
, B; p- k% t2 P, P4 J tmp[j++] = arr[begin1++];
- A& k' \, p* I+ I' C* @% h while (begin2 <= end2)- ~! h# N9 |) u9 R5 ?$ ^
tmp[j++] = arr[begin2++];
: K/ ~5 a0 G% J# c6 c$ h2 t, p7 A
//拷贝回原数组——归并哪部分就拷贝哪部分回去
0 ?0 \% d# F+ ?& f, ]+ l. j memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
9 Z, B5 U2 o( ]& n0 o) s }
8 r `3 l5 a0 d" t. m2 t gap *= 2;
& t; [* [( [ y* [$ ~9 s }$ s; P3 ] c4 Q8 l; c$ N- X7 ~/ S
! W5 T6 e0 J$ x( D/ J
}
6 |- E! H$ Q$ w1 U+ L; K8 ~$ R" |' E& a: M
1) A a" G n- N
2
+ h H$ @: H6 x" m- r- S* C3% x0 v" B( b/ {& C7 A, F6 U' [
4
" x7 E) r. e" X. {+ O- `& L, P. ?5. @7 F: o1 _6 i% K* w9 J2 q
6 N: N( ^3 h3 u2 {9 _, w+ L+ M9 M
7
, b* d6 M) k% U; @/ S8) _; Z; t9 k9 s& d
9
6 r# k. @+ h7 V) d, U$ R10
1 N3 ^+ K' |; R- {' L8 F11( a7 D( `6 a' A/ U4 Q, S
125 g& C' z" k0 K) G. k8 r" }( V
13
( X% L; |2 L0 |# | f14
5 a* b; B) O) Z) \* P! ]15
: m1 r# G; Y7 J& B P6 Y16
7 X# d$ b8 i c3 H1 t6 p% o+ X$ V7 q g17
, ^% a/ e$ G. I/ A18
, O7 c Z/ L* R- j. U198 Y1 \# |/ ?6 G/ f0 s. ?/ M, }" J9 C, a
20
' P r2 Q3 g, e3 U21& q( e* j6 t& j( j, N: m1 x1 L( B; {
22
$ d0 [; K* G' D3 @, }1 u1 {4 v. T9 C23
9 x+ Y( j# Z [6 k6 P2 T" |$ j) l242 x0 S- p/ |+ A; m- m# w
259 |. \4 C5 {0 J9 G
26
9 B: l' s& ]( P0 h27
1 h: _* I( g3 L/ r28) u8 ~ h! R$ r, Y: ?( l
29) l& K3 M( c- ?$ U' H# `
300 y6 H: ^" K* t. y3 D& n) x0 |
31$ {6 m% |+ z$ v" l3 K- }2 S
32
) ?$ I# s! w: O! {3 c, Q# ^33
2 r M! M, S" u! u0 Y% o349 d( ]5 M7 i5 U3 m7 E# Z
35
@- p& _) ], D9 {0 m36" y, R/ v1 u, b' h
373 A2 N% D" F' C
381 v1 d% Z, j: q( V
391 f" v1 d7 K6 A9 Y: w5 i6 H L3 @
40
( t; u( [) @- A% T$ U0 Y* m41
5 i9 D4 i2 j# d4 g) ~42$ u. k& u& \% n2 v8 F
43
+ J [; p" @4 r# t; N446 [9 W. ? Y3 ]9 Q! V
45
; v: ~1 D- _7 n& x+ |+ C归并排序的特性总结:
O% d4 g2 x2 I% Y
6 H8 m+ ~8 F# y: b k归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。6 a2 q& r! S$ B- b8 {9 r& X" D9 l2 N
时间复杂度:O(N*logN)$ M" S8 U l8 e$ r% l
空间复杂度:O(N)5 \* w! \9 R5 Z3 i4 B
稳定性:稳定
" M6 D" B8 ~ w% l
5 P0 S6 h) \- G; m7 H6 }————————————————
" V0 c- @0 } D9 I [/ v% E版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
" r& K1 C8 U8 ~) |原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
; q6 @, g- t. h, ?+ C7 A0 T
# H; X5 |; \4 O2 k8 S8 S( u% Y& r' J, T; l
|
zan
|