- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566250 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175098
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
【基于C的排序算法】归并排序
9 x o5 E4 [5 m( C& z! J: B
$ o: o4 a, f! z' @. v前言0 c: F2 X2 @& z4 x- \
本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。: s2 S4 R: p1 n2 [9 A
( U7 p, i5 \6 e& A n2 r; W5 j归并排序
+ R& D; G) c3 g/ L" |/ }基本思想
% @* Q5 ^* k' T$ D" d 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
; R5 {0 ]/ ~5 z9 v8 f) q3 L
# Q/ I7 a8 L, e! x
; ]% a4 |+ M1 @# }' z$ |2 p* r; x
合并的思想其实和有道题目的思想如出一辙:
1 v& o5 [2 B) D1 j
# O* T" O9 T- Z( S h4 G3 d, S/ q# e- ?) q$ q, m' B; a
. T7 p' O& C' c6 ]
我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。5 ^6 Q* a. L9 a# ~3 P
- w! _0 c: z+ q& k9 k( ]) a+ b[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
0 C, J& C5 C+ a7 m
6 N* _( _" @% ?" Q. H# Y/ Yint* merge(int* nums1, int m, int* nums2, int n)
4 h- W9 K, H" t2 m8 N1 m{" E( \5 M# u+ [
int* arr = (int*)malloc((m + n));3 ]$ E5 S; o( X0 \, T# L
if(arr == NULL)
) O( w! t4 Y2 B9 [3 u0 B% T {
" L/ c# S# ?, K" b1 N) M perror("malloc fail");+ `% c' m- ]5 z& J s# ]/ \& w
return;) D0 L8 B" p: `1 f, W
}
0 N6 y, q, ^" l& B) r: j, ~9 c" G) E' N8 N6 v' @3 i8 l* n! ?
int p1 = 0;
/ }. B- }* q/ t7 K5 M int p2 = 0;$ U' W' d0 F4 K
int cnt = 0; H) t- o7 t' A6 m& I( _0 u5 D
while(p1 < m && p2 < n)( x: J- c! r- b0 C
{- ]9 |- q9 t2 I8 h: f- s3 G+ X
if(nums1[p1] < nums2[p2]), Q& O a& _ h: N
{0 [. I9 r; f! s
arr[cnt++] = nums1[p1++];( U' q, k5 }1 U1 X$ n) i: t# s
}
+ J/ ~+ K M! X/ e! |( S else
' B/ }4 P2 A0 u/ F- H- ^0 Z {
8 h, P8 P$ w6 ^8 t arr[cnt++] = nums2[p2++];
( Q6 C# C1 ~4 E) z- }$ K }- V$ I# I6 ~4 J' f3 L: Q3 ]
}
8 \, k7 |3 }% t, a% y0 E) e while(p1 < m)! S6 L8 |7 M5 c0 r0 u* ]$ z' d
arr[cnt++] = nums1[p1++];
% r) J% E6 J D! N x9 i7 k. @% A8 \& E& y
while(p2 < n)' @& |: {6 l3 u1 O' \6 C7 t, G" [
arr[cnt++] = nums2[p2++];" O$ E V' j- V+ L
Z4 b; N; {/ X' |0 _ return arr; x* x( M/ E5 `2 S1 ]
}
X, M9 o7 w7 e, Q
% }+ N/ I- J( v X0 g6 C. T/ u1. P; v. p. L. X$ G
2. k# @. ~, Y7 l R) v
3$ d g9 x D2 x Q
4
* X7 P0 b* T& o! d O. u/ s V55 {+ L* A, L8 R+ _ }. \
6
& t, W( Y6 ?+ C0 g7 ?7% J3 ~3 ]7 z ^: q& D
8
% s2 q1 \( d/ y" V3 Q, W& |9
6 I+ R. z6 w$ {4 v+ l% T10
2 f, r1 ?/ T, ]11/ | P4 T" {0 l! R
125 R. Y; J) ~# O0 n3 B0 M. t& |4 \
13# j( w( A5 z9 f/ }5 ?
14
$ H8 |2 {- |6 l; E% [15& r: T$ P# O) p. T) x a! y
16
; p* ]( D3 R% T1 K+ ?( d: w17
5 ?6 ~8 s1 F2 _% b8 O! j4 L18- u3 R) i/ a1 ?) k) L
19
2 d. k9 l3 u- N" ~/ t3 I. K20
- E ~$ e& U$ z5 k. W21+ j: I7 p+ c" d3 w
22
8 `9 X& B7 q! H. E; O- m23
N5 i* {5 ?7 v$ _8 M" @! M2 z24
& t" ?3 R8 r% j3 ~25: \! ^! J( D8 H2 `, V/ `
26& s" q6 n1 {: N
27
2 A' w7 Q8 W( [28
7 i$ [8 W) F5 T0 U+ B! R7 f29; G/ W2 \+ s" s2 @5 [
30
) R# }, A8 W1 j3 ^3 D6 ~/ [31
3 r" [( ]& k- E1 u 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
3 D' v- q" w; m7 Y: G! F ~
p' _! b4 m* w' p S递归实现
0 `0 H1 A2 Q- v$ S0 f- c7 {4 s9 H 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。9 I- h# b: z. a9 ~
% z$ _: D- ?5 @. W2 ?' ] R$ G
9 ~, p/ V$ ~- r( i: b( D! J/ P8 `2 Q6 I2 H- K9 r
N9 N0 Z; Y A d2 X4 F P
, v4 S) j5 v. a& kvoid _MergeSort(int* arr, int* tmp, int left, int right)4 H) \- I. d' p5 s U' j
{
8 R! m4 Y# ?; `& U* V4 H) C assert(arr);
& n) r& o+ q. f9 P9 c+ E
9 }2 x! W. u6 H- l! G$ D( m if (left >= right)//递归结束条件不要漏了6 C3 ^7 B, }5 D4 N' S( q
return;
9 g( u9 y! M" ~' j, ] ? q0 _
* y8 W6 H* ~& j4 s( S+ l int mid = (right - left) / 2 + left;
7 @* S; H8 \8 m, @/ J) B3 f. X# o; W. q7 p4 ?
//划分左右子区间[left, mid]和[mid + 1, right]' Q) G* D0 E. A' k7 @4 s1 c
_MergeSort(arr, tmp, left, mid);
( n2 r* `! ~- Z) ]( Z. s' u5 Z _MergeSort(arr, tmp, mid + 1, right);
+ [/ I R. \: I/ o T' F4 C% }
//归并1 R5 n7 A# R' n) I- T/ x5 k/ S
int begin1 = left, end1 = mid;7 A$ i8 M; r4 _4 E* }# E
int begin2 = mid + 1, end2 = right;
. \7 C7 o N5 j0 ]3 f* W int i = left;
5 a2 s, y3 S, g/ z. z7 L8 S7 Z$ B while (begin1 <= end1 && begin2 <= end2)6 ^3 Z; Q. ?& J4 f+ x7 E& H
{ A" X) d; m. K/ `9 W
if (arr[begin1] < arr[begin2])
+ s6 G" @7 f7 E+ d6 n- `) z/ G% g tmp[i++] = arr[begin1++];4 Q7 u, r( a6 o# S& j/ E$ A
else
) \' S' {7 z0 C) h3 `5 { tmp[i++] = arr[begin2++];
d- J& n/ \- N9 L }2 O: ~: y: C: j _4 z
2 N' |$ S* ~5 T. Y {8 `% H
while (begin1 <= end1)
& T3 V1 j4 N2 [. H tmp[i++] = arr[begin1++];
8 T* S7 c# H, y* T7 {; x) A while (begin2 <= end2)# `0 J+ ~# j+ s& ?
tmp[i++] = arr[begin2++];2 m0 Q2 I: N9 f- Z( C
, A# ?" m: o" o4 O$ | //拷贝回原数组——归并哪部分就拷贝哪部分回去
; @3 U9 g) n6 `- Q# I3 D //而不是拷贝整个数组回去
. B l9 Q) m& W/ a9 r9 N0 B: I4 }& { memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
+ P$ x' s* G# h/ H1 P9 o3 y}
' z7 a, V- X- [6 `, c$ r5 F5 K( |/ L2 Q# p
void MergeSort(int* arr, int left, int right)
, F! t2 d% R A5 n9 `; K9 w{" E% j% @: b+ A8 i; j) ^0 ?7 l
assert(arr);
' x6 w4 m) \( s+ E+ Z) J& U4 @7 b( w. ^
int* tmp = (int*)malloc((right - left + 1) * sizeof(int));" u$ D$ ^+ s. H3 T
if (tmp == NULL)' G0 Q* K( p5 w/ N2 _/ r
{! T: p! J; Y$ A0 ~: J$ F' @! x# j
perror("malloc fail");
' l1 f3 m, K" ] return;
6 O! m2 H4 ?! G0 {; t }, I, g6 E: N/ S2 t! A
$ \' @" p* I+ T- X' ?; L' X _MergeSort(arr, tmp, left, right);& I6 w* I0 D/ E" h" x: ?
1 U5 ^! j- U, `( | free(tmp); H% E9 l& Y5 _. r4 W0 W
tmp = NULL;
* `" a! X9 ?% q; v4 l* @* P" _}8 n2 m9 j! p, |3 H K! U
, w( B! z: N( ?# @1" q, S7 s& b6 Z9 R
23 u1 e! m* ]/ J
3/ ^2 l& G9 h! t0 H5 s) j
4
. p& u8 B4 B# y9 \! ^5$ W. P3 b) A/ S8 ^% q- C$ h" l
6
$ P2 }$ {0 x H0 h9 q6 f7
3 A& O, V% E3 j5 `# A3 S0 m8$ v0 {' z [& W% J
9/ X: W9 w5 ^% y+ t K' X
10: b( ]1 A9 S7 j1 R) {% \- g/ h& Z4 ^
111 J1 c; k @/ @3 f3 y" V
12
3 c; v7 M7 B$ R, n$ m. o6 f3 z0 s13
2 R2 Z7 |# Y. W" X7 Q# |2 {# J14
; Q& j3 x* e# Q- c6 O8 I3 l% H! F154 }% Z( p$ v0 V" N2 v/ x
167 ]! [5 D+ |! ?" B+ |
17
$ s3 U3 B! w* x) D+ q' J# l9 ~18
% C9 V! |/ T0 ^/ \* P& T7 i19
, V4 T& M! V" N) F/ b5 B+ }20
2 l0 T8 E- }, q) m, r21- c5 J- S; `5 u& m0 ]
22# ~+ ^* l* n" u: m
23
) d9 c% B' s( ]9 \0 E8 t" v248 [# M0 p9 z( A+ @0 B
25
' ]* A8 a+ V' h4 _26
" I+ w6 ? M1 X& e9 n27
# s% U3 C2 B2 @286 [1 c/ B0 Y7 Y' |/ c& D( U4 Y
29
5 O9 p! j; [2 b" n30
! O; a7 j6 y: R31
( Y0 q" k, m& B. `6 F1 p" h. Q" w! R" y! P32
{4 S% B+ W& j% ~& L) K33
7 C0 Z* Z. q& e, l$ ]6 M: f341 ?* y: r. }; e* M. d+ a
35
8 [: a0 z: k: ` c/ Z* x6 b36 N( I) e6 s+ h7 b5 `7 p! Z
37
8 w. f1 b+ d" P2 E+ E38
( C: U% ?" t6 @! r" d" u, p/ d39! M8 d" C: R$ ^8 J) O
40
0 B6 z0 N" g% @41. x/ @$ p1 Y% s, k7 s+ D
42
) e& t2 C) \! F/ @43
; D+ [1 J: Z7 e4 f2 Q# v44
$ K# Y C9 n+ U3 m0 A% M45
- s7 z) Y$ I- m; x( i0 U; R. S3 J* s46. J8 q# l# ^* s, a' w
471 P' l# [! G' w6 Z, m& ]9 q4 n
48
& t) o. [7 t+ \ _- _0 ]( u6 I% y5 I+ h: H490 _& ~* }2 T' Q7 w4 O) z0 u
50
$ \1 Y) r9 k$ c* q512 F8 d% y+ U' M! R3 ?
非递归实现
; s$ Y+ a& ~# A. s 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。2 c( c! u" u3 c% ^6 _
# r" Q6 k8 T% |# F* U( F1 C) D, A$ B# o% Z7 e# n% ?' \
& N; N' x0 N0 j! ?7 L1 A
不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
) Q/ W H, O- g. g' `$ O5 d9 p2 G- V/ f& K" p$ K3 s( i1 V
还要注意区间的取值,每个区间就是一组,就有gap个元素。
3 w( V& G# k$ N7 X3 Z; X! ~
q; T7 y0 j8 I4 c5 _- ?( f$ Q; z 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
; K% b/ p" Z# t! B4 n0 K. |) h# d! K# Z3 U* |7 \, ^' U/ p- A4 b
代码实现
) P+ b7 c% j" Z/ J, e. v! |5 B" c1 P% K% e1 e
void MergeSortNonR(int* arr, int sz)
0 |. t8 G7 X0 x' U/ H/ f, t{
- J1 i2 \( l! g& a+ D+ ? assert(arr);
7 n4 I1 I; N9 ]
( l) O7 g+ r- P9 A3 h int* tmp = (int*)malloc(sz * sizeof(int));
( i* l' Y& S( A, e if (tmp == NULL)
3 m8 c7 n3 B1 ?, }8 i {; \2 k4 _3 W: i: r/ w
perror("malloc fail");
, ]' |" _& I4 U* W% v; R/ P return;
" ` `- f0 U9 j% N8 K }
/ \% i3 y4 m: ?. h: }
$ B3 k; B$ D! t: y1 X& k int gap = 1;
6 h$ G8 c: W6 b% f* D while (gap < sz)) p) ]" m$ p& u
{5 C8 D& m. j# b. a( n5 w/ f- ]
for (int i = 0; i < sz; i += 2 * gap)1 |6 D+ ]6 E2 k B4 a' C3 E- r
{
6 F0 ?% Z- x" S% l) H, l) L int begin1 = i, end1 = begin1 + gap - 1;* }; P9 y; A$ N5 J7 R. M
int begin2 = end1 + 1, end2 = begin2 + gap - 1;
% @) D4 \& h2 \0 n int j = begin1;( A/ ^3 d& K: s) B- E6 M
" l7 H1 X2 B" N# W
//归并
- P7 I' H0 s. F2 a5 | while (begin1 <= end1 && begin2 <= end2)6 G9 F# Y$ A) I
{
" q' b- {6 [ I4 z! ]3 X$ T if (arr[begin1] < arr[begin2])
, o( U) [7 G1 g' H tmp[j++] = arr[begin1++];
/ ~' E/ Q# Z+ M9 d% u else
% H9 h0 A$ F( M' X2 a tmp[j++] = arr[begin2++];
- b+ }- p" ]4 n+ W4 R3 A }
# M, p5 a! Z+ ~* n
! I- N1 k( u" y8 o) @' R4 D7 ^3 i while (begin1 <= end1)+ _, j: w( j2 e3 d# U6 ^! g8 x2 j
tmp[j++] = arr[begin1++];/ |4 r F9 }% F1 T' {
while (begin2 <= end2) S% [3 [, d3 j: w
tmp[j++] = arr[begin2++];
, J/ J: P, `# ~( |! L& b
/ z g3 E4 e& I) t/ j- r: ? //拷贝回原数组——归并哪部分就拷贝哪部分回去! ^) i1 x O) w2 r$ f
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));% u/ f& y/ l8 o
}
1 K: K5 p9 e" d0 G gap *= 2;
( W2 \8 }( s) t( ], R8 f3 z4 M7 M; @ } U E+ |. q* K( a' h
" I' q, K# O% |5 H `( m5 Z}; [8 ~: ?$ x. ]
: M% s9 g- Y2 Z/ k) b1 [
1
- p5 T4 }3 C$ I5 L2
5 `& f! l' B8 X" e33 I5 ?, @3 F6 k8 \2 m, ^4 ^, B
4; e4 e) I+ V3 b" B+ `
5
" ~/ {- O5 }4 Q7 b+ h) P6
4 c3 p$ ~: h- W I# j7
. Z6 J6 w* V; W& ~8
0 ]4 H( m* l5 w$ |9) ?8 a$ g7 t3 @7 r& T( O+ c
10
& P3 c! T- t3 ? A& N% A! q11
0 e$ n8 W5 G' J5 F+ X: S2 k12& K, {2 |6 P9 _# l4 u7 Q, n, y
13) c0 f% R; u8 X& ^3 j8 H
141 d- A- U7 b* Q: ~# O" d5 c; b" L
15
; t+ `9 Y1 p( F7 ?! p16/ Y6 q/ e8 [* k
17; n/ V; e9 M* r- ?
18
) Z* w! O: U4 ` M1 v$ _2 Q192 I4 ~8 h+ V$ @/ y6 \: e
20' j+ E+ `) J7 _+ G
21
4 r6 G6 S( A/ ?7 w5 G" T$ i q$ _22
) r' O6 h0 R3 M0 U* n23' r8 s9 @+ n5 \- }
249 x* B# w7 b) I6 L1 c, G
25: L+ z% R, x& f) L# L
26
, G: s# u5 F% E& q$ ]. I; M27
4 ]: n- s' e8 J& e% V" I" l) T28
/ X: x& i8 P& S& G29
, ~ H9 P5 j& ]7 g30' t m$ G& `# Z6 G/ k* k
31
) w; u- G) e* b( q% }* U' t32; O& n' x7 m. |5 v
33
( L P% {1 _# @' Y34
! v2 n3 ?( N0 a5 j7 P350 w2 H2 U/ `# V- Z7 D, t8 R& S
36( @+ O" @8 ]5 m' E
37
, C5 a( X2 r; J3 ^38
0 V1 L6 T# o, t0 j* O6 X39
! Y3 h$ k3 j( }1 Z+ F40: y: K5 r( ?, X
41
0 [: R% R, V, m5 j& H4 [边界问题
$ n; x( F. t$ j! K 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。' `# A& H1 F9 J
- t* S, U5 o6 L! K举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
+ i, r2 q) \3 d3 q" }8 x# d0 i0 ~8 [
# \7 @' J: j6 y1 H5 q! @
9 C8 F! P$ ~3 l) p由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
, Q1 P9 Z: t( [; g% w# P! ~
6 F+ m! E% M; N! P! x( y第一组越界(即end1越界)0 g% |4 J) Y7 q& [0 |" @# a
5 z& F4 T& Q* R; X' n, e应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。; l. Z) G2 r. M3 n- r0 o
9 g* ~0 }9 G6 Y3 O; j& N; \6 n第二组全部越界(即begin2和end2越界)
. V! n8 ?, G: `3 Y- s' f# _; f/ Y1 e% e% U% `
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。" u) x) i' p2 V; z4 H5 k8 Z
# e8 g# b& |! w! S+ U7 \. R) x- L
第二组部分越界(即end2越界)0 }/ ?/ q- w3 B0 p
, l5 F) ^( d! ^0 N) l" ?+ J5 l: Z+ T应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
9 s6 C, h6 z& P2 B) s; P/ ]3 p. Y' h" C1 y
其实第一种情况和第二种情况可以合并为一种情况,原因:2 F" ^+ ~, M/ N. l! c3 P2 W
/ B: ]' Y3 M& r, Z
end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。4 K2 ]( |% Y7 L
8 V& h) ]" C5 Z R: z" l" @3 k
拿两个数组试一下:
3 w7 t# `& o$ f
) b) \( q5 `# N
. u: g! r$ }4 l* J( q$ Q
, N Q, r- H+ w' P
, ^0 ]1 c7 N% E: r/ `: D6 K- u4 P: A( K5 Y4 c
代码实现3 c! Z. u% p& M% I( Q! R& {( P
; W, @& @% |' F8 ]
void MergeSortNonR(int* arr, int sz)( \/ j' d/ S2 K& ]. v" C
{- H7 g$ h3 ]8 P* `: L! K
assert(arr);' f6 W: ` p( P
1 X- [1 x8 O5 W8 R4 w% r int* tmp = (int*)malloc(sz * sizeof(int));6 U3 k6 A7 F5 i
if (tmp == NULL)
7 C- O# R6 _2 q1 Z8 e+ A& x( ?" ? {
4 H3 t4 `& b9 O perror("malloc fail"); P0 @4 S+ O$ a2 |2 s& @; k( ]
return;
6 F% H# Q$ y0 P( h0 d }
5 L6 }! g" W, g0 ]( ~ d- G
( u- N/ G' i5 z+ q3 U int gap = 1;
4 M* ?7 T. a" p7 d while (gap < sz)3 y' U P) Z' k: U/ H4 c
{
/ Q4 z& U1 e' N' S9 K' k4 S for (int i = 0; i < sz; i += 2 * gap)
- E5 H- M/ o$ b( @, E {
. q1 I/ ^8 m2 f/ U" e; J# I/ m int begin1 = i, end1 = begin1 + gap - 1;
7 S+ |7 x1 n7 o9 g- b, ]0 e# i int begin2 = end1 + 1, end2 = begin2 + gap - 1;7 `( E0 g7 r2 i" R
int j = begin1;! [' f3 R! d) ^& ]* Y" f
//越界检测
/ P" m1 C, e3 w if (begin2 >= sz && end2 >= sz)
8 C0 }+ A+ T2 q, l( J* k break;
2 v- Q7 z1 q! u' H* F if (end2 >= sz)$ H) _- A/ I$ z5 f
end2 = sz - 1;, \7 \7 r5 b( I f6 G
//归并
2 G# a* p, S0 l+ [% h( B7 q while (begin1 <= end1 && begin2 <= end2)2 K! k8 E/ u) X4 J5 E
{7 w1 n3 n5 I V" h1 [
if (arr[begin1] < arr[begin2])4 c) ^# V* e7 U; I9 j7 E* r
tmp[j++] = arr[begin1++];, Q7 @8 Z6 H7 I- a; y
else
4 Q% b1 c2 t6 i6 ^% r tmp[j++] = arr[begin2++];! Y" u0 }+ }! R( ~% W
}
- Q" d, w& |2 \+ J! l+ ?. k
# H% D0 T) y" `2 C2 v while (begin1 <= end1)7 k1 X' i# ^0 U# i" x, G
tmp[j++] = arr[begin1++];$ _) Y! e" [. x9 D
while (begin2 <= end2)
2 p$ J5 o& v b9 c$ F" |6 Z tmp[j++] = arr[begin2++];8 h$ D8 e6 y; \# \- k5 x
+ x& O' ~0 R$ J+ Q //拷贝回原数组——归并哪部分就拷贝哪部分回去; ?0 q4 n8 S+ C/ \8 K0 Q$ |3 L
memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));' }( t8 Q# O" q, l \; H
}# c* u7 ?: _9 v+ p2 H5 P. B
gap *= 2;
6 l: m8 e' U$ n9 g$ i) }; Z }
3 i& c* K. p5 q9 f# C7 C, q
4 X, U' u3 S$ b# R w0 f}
V: _. ] f0 X k" x. P: K
: W/ m+ ]6 m6 ?1
0 Y6 I3 | o9 K) _# j2
# W! x: [% n6 }( {2 e3
) ^5 M! I2 F2 g, i+ ?, @49 ~5 z) [' a& E* |' E. v
5
; q! R: n! N9 x7 Y) V7 w# @( q6& T2 R$ E; r8 B, K. Y
71 A! r+ q# E! @7 y- x5 {
8; N5 C, N1 v9 O& n
9
! |' n1 B4 G4 d3 X10# w; l) v0 M1 h! V7 ?! H/ m; T
11
0 i$ ^8 C$ B1 a12
- [; O5 Y" ?9 @( ]. H- S5 K2 p+ `- T13
9 g7 p1 r, g/ C' K$ i144 M- W- Z4 A: a5 e
15+ v& p/ s9 d$ T- p6 j
16
& g% k- s3 ~% [" p17
' B# A% t* I: k; h18
9 o' P! ]$ _5 j8 B19
# t+ M6 J) v' H5 ^209 W I5 {- j9 s0 e
211 W- S# x( h& S; G' Z
22
+ v4 R9 Q: x4 z6 H3 G237 V2 r( N1 t% F- k0 ~
24+ d0 V6 A- }: d) ~8 r1 ]
25* d5 Y' U Z) _6 c
26
5 _; ~* p2 N3 \# ?% S3 B$ a7 S: b273 G9 m; y3 R/ Z9 {/ T* Q \% [/ S
28
6 F& U* q1 L* t/ V29
/ i3 a3 k, E5 b1 l8 _2 j" o! m30
) B5 F. f s* f, n1 _- _313 `4 [" E& f' t* @& K& A$ a, ~
32
( }" _$ c$ R @7 W( A+ B G33% i$ C# m* k" \* @& R
34+ k7 u/ O0 W# K, T- g
35
/ a( G: F1 l2 b! ~- q9 O8 M# S: U36, P% y9 K3 y }: Q( z. p* o0 u
37/ b0 g/ I ~$ n3 P
38
! r4 _! i8 e* e5 M0 j# C0 T6 F39
2 ^1 d0 E" s, E/ @40$ X+ @( j# f$ d! k8 I$ ?
41. O( i7 G6 M: M' R
42
) S7 C( R' x3 }4 N. @+ a: Z( G+ S439 f; K, T' b% @9 n
44& \* g: q8 [/ y# S
45; A. x3 L" F' j
归并排序的特性总结:" M" e5 K6 D/ t
/ Q, w0 F8 g7 u c) c归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。5 G* G# z U* g
时间复杂度:O(N*logN)5 d2 Q K8 }2 O( W2 B8 r+ Z8 x: ?
空间复杂度:O(N)
6 i1 P7 i0 @6 E' j稳定性:稳定, b5 t1 [- w0 T9 M1 l( [
" J* R L- C g8 F+ s————————————————! B' R* K9 [/ u' ?
版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& B! u/ \! @/ O9 ]) b+ i: G& s
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
0 a L1 ?9 a& {1 ^2 N6 N. F8 @+ R4 }2 ~/ p
/ q: n2 J: y- p* `5 ?8 V2 l4 x |
zan
|