数学建模社区-数学中国

标题: 【基于C的排序算法】归并排序 [打印本页]

作者: 杨利霞    时间: 2022-9-14 16:22
标题: 【基于C的排序算法】归并排序
【基于C的排序算法】归并排序
4 R" @9 u; _' V( {$ o' {) c9 z
. \; J( ?! Y; V& y+ B8 v! S前言" U! W: k" O" X( O0 V
本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
) }) i  i, k  x8 o, E
6 N/ `1 V7 \* f6 g' V7 x归并排序
3 [( k* O, j! t4 C% F基本思想
" B& N5 }) g, w4 |/ D: f6 X​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
6 R1 N% _& L+ A" k; v
/ P) b& o$ F: t. Y9 a; ~' d& D' ]; w4 J; U
6 h8 k0 G' F5 X8 N: M; p  z1 Z3 g
​ 合并的思想其实和有道题目的思想如出一辙:6 |& B) ^$ k' g) R
# p7 m* N9 N4 G+ g6 E# G

. U: I: @  h. }2 `6 a' B. f! ^( I/ F9 }- r9 D0 i
​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
7 [2 w  d+ K  O+ Z4 O& F7 E- g
' z, Z& ?" D# O' b[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
# @6 p5 P8 h  [2 S) ]1 G& T8 l. Q7 |' A8 y" ~3 A9 d' z6 }
int* merge(int* nums1, int m, int* nums2, int n)  a! {: b! O" B# a' u1 z
{
  ?7 m. n6 ?5 J( h( l; ?# O5 C' Q        int* arr = (int*)malloc((m + n));
/ n2 S' E, q) D- v0 M2 N0 E    if(arr == NULL)- E7 H* s* v  O5 P8 h* x
    {- \' k# o( s0 A' ^1 X4 G5 k
        perror("malloc fail");. O* C4 A6 ~( O
        return;
/ ?; x9 l/ ]$ S: w8 Y    }
4 X* X' E2 Z8 K+ G  k
! y* ?& c1 r% M3 h0 r0 O7 ?    int p1 = 0;& m, i) O8 r4 N) N* [
    int p2 = 0;
5 }; O& y) M2 M8 a# s' u    int cnt = 0;
$ a' M; d) q) W, I    while(p1 < m && p2 < n). O2 W. b* c, [3 @+ S
    {) c5 M2 R3 Z1 @2 A5 b& y' l
        if(nums1[p1] < nums2[p2])
; ]9 r7 c6 J1 [' g# H6 d        {6 H1 G6 b0 b, U7 w) ~
            arr[cnt++] = nums1[p1++];
2 b; |( G7 f; ?/ b        }# z7 F" v; Q* f; D9 Z5 Z
        else
1 d5 s5 I' d+ U( F8 x0 h        {
$ ~2 |" ^* X2 H, a+ s            arr[cnt++] = nums2[p2++];
3 |0 W7 t" F; ~- ?& @' b' \/ b7 d        }
! ?( E) ^) c) H% f6 X: I* x    }* f4 @7 F5 m9 l3 ]% c
    while(p1 < m)+ M& `1 H% e' q8 g8 h* Z6 U
        arr[cnt++] = nums1[p1++];9 q2 C: s4 T5 s9 M* q  E4 Z

& b2 _$ Z! e* E8 M3 \5 ^5 I    while(p2 < n)
: X5 l% n3 ]$ z5 P4 ]9 a7 d        arr[cnt++] = nums2[p2++];9 E$ B* ~6 B+ I, t

( k8 I5 i1 n* b! V' m3 C+ a+ z7 M6 p    return arr;
6 Z; o- f' y% I6 Z) \/ C}0 Z6 D) F/ g' J* v1 Q- n# t4 w5 o3 S

5 x' C  J/ p0 o" ~! e) g( Y. k1. K( u- g/ @  N
2
; l% w/ n+ J" O. b: i( j3
% }: v6 ?0 `& r* \+ U! X& `4
! |/ F; w9 ~( a# w9 r- i) k2 Y: ^5
2 @, }4 \. Y2 K; y4 x2 g64 E: G, m9 }! ^( x+ z9 x( c$ ^* B
7
$ w% E) g; I5 t" _% E88 _/ _' l. f4 ~% t1 l
94 H$ j3 `5 a+ y( X
10
- D' p3 `8 N7 x' o8 ]& t" \118 l4 u' S9 R. Y% o# k
12
  ?( S4 b1 C* {! q) Y- O  e0 @134 U5 H9 l- {. P& [- e
142 C! {% z6 [4 j1 C- P
15
$ Z% a6 y. l" M( J. b+ H. {16
) B1 a& K* B0 E% P6 c" [, P0 z17
7 J3 C* |) R9 R8 y! }3 W! @( m189 k' C1 V( w  ?' C( L3 ~9 D6 w+ ^
19
" H( C2 d3 x2 O; ]1 H20
3 z$ |: Q. V; o21& Q, Q) N: v2 b/ I! [3 e
22
( S. g1 r7 M. k/ ?9 c23
" X, [2 h, X4 H24
. e9 e( l% ]% p" m25
' x- U9 {4 E1 w, d* A26. `, O8 m2 I% L6 E+ i$ T. C
27/ R5 b& m4 V0 D$ |7 g! y
286 Q/ z+ v9 J* [* }6 t4 k! D
29
3 R8 J0 p3 n' x/ o# p6 y  [" H4 V30
" U8 p+ X8 M) S% a0 e31
% t7 u5 |$ G" c​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。! t( C- T% S9 {

  o* v6 b3 ^5 `/ d$ @7 ]5 U; U: P递归实现
- |, L3 a  r8 p& Z6 a# z3 a​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。/ `* K) Z+ \! I& S( \1 R
: r1 P/ w8 A- Z4 P5 [

5 K+ ?  j) w2 e+ I' W/ }/ O; h4 P: W& n1 T* M0 g

3 u! f$ B  Z4 N# }. k1 y
( e& {# G" c5 }void _MergeSort(int* arr, int* tmp, int left, int right): I6 E6 J+ {8 D) W# u* N, f
{
( ~8 A0 Y4 q: m1 F  X3 E    assert(arr);
; i' d4 E. P+ n6 L8 [3 U4 B: D/ S" o- T+ k
    if (left >= right)//递归结束条件不要漏了
! I& Q2 n/ r; \        return;
7 |0 @5 X! l1 g' Q- t( o0 K0 G. Y& G2 Z$ ~: n8 I
    int mid = (right - left) / 2 + left;* ~: u2 J4 o1 D, `% A# U5 d
" d7 b. p% |& |" l3 B' o
    //划分左右子区间[left, mid]和[mid + 1, right]
1 D- A- c, o" O% V- D+ x    _MergeSort(arr, tmp, left, mid);/ ]9 U' h& y* U; T2 D4 i: k
    _MergeSort(arr, tmp, mid + 1, right);; N' B- w8 j3 l0 R  B8 X+ T, A1 j5 L

* y9 ~( g  K+ O( _, u    //归并9 H# r7 w: X- j$ l+ [1 ~3 T
    int begin1 = left, end1 = mid;
* c. b( k' {# \  c+ _    int begin2 = mid + 1, end2 = right;6 p- ]4 f1 D8 h7 {; p
    int i = left;  l2 S* |: w& y+ i+ n/ J# @
    while (begin1 <= end1 && begin2 <= end2)& K: Z! k7 d2 r, h9 P$ n7 X4 N
    {
/ O5 Z; r. `% Y0 Q% S% [        if (arr[begin1] < arr[begin2]), b: N3 O7 _7 J' T6 k4 j2 o2 L  r
            tmp[i++] = arr[begin1++];$ Q$ B7 t" k' P) N0 |  c
        else
. \- Z% B! x. O3 U4 W            tmp[i++] = arr[begin2++];4 A9 z4 p, f1 `: O! }6 |
    }1 h" |3 z8 H) i+ g  h5 l& H
6 o8 H+ q: m8 s
    while (begin1 <= end1)
& {. f* d) S& s        tmp[i++] = arr[begin1++];
1 R" Q* t4 W8 T, T/ i    while (begin2 <= end2)
  y$ C) E+ s) B( W        tmp[i++] = arr[begin2++];" V1 g, Y  f* K2 n, r3 K8 `6 f
       
; \& @0 j" l3 ~( j" v    //拷贝回原数组——归并哪部分就拷贝哪部分回去8 G) I' ]# r# [+ u4 n
    //而不是拷贝整个数组回去
% r2 W- b; b( d( D    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));, R% ~+ k" T6 `% w  z0 ]) t& r
}
  X% l; u* k4 s' V( W9 E" P1 Q9 \5 L- K
void MergeSort(int* arr, int left, int right)8 B$ O& D0 O; _" u
{
8 s9 P! L- n& |8 E; R; R    assert(arr);
; ^1 a  }$ N. @4 M, [  y: {
6 h" b! H1 ~/ X6 d+ \. n7 `+ o    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
" z2 r% M9 u+ C+ ]    if (tmp == NULL)' r$ B  `+ F+ R$ M7 l( L
    {
1 g, @! ?2 a! c* X% j) h; @: _        perror("malloc fail");+ I8 W0 ^+ y& L3 w! |( \- C
        return;
5 J% G: p# W; \' a    }# o  T; K. ]& c/ B, S

: I$ i3 @' {$ n- T. ~' Q3 s    _MergeSort(arr, tmp, left, right);
) O5 S0 `& t8 y% Y2 w$ r
9 W5 u/ G1 N% k! u    free(tmp);
9 S# T! {# E# `    tmp = NULL;+ V# c/ [4 B) B( ]8 y- U
}: E. g3 T# s5 b9 q
3 B2 O- F( P8 V- @, r, L
16 c" N/ D( E( C/ R/ n0 h
2/ n7 L+ J% I# c
3; I  ~  S+ F1 l1 f" J* |
4
' ?) J$ q8 ]5 g) z8 T4 ^/ K5
; X/ `) [- O9 l% p. z) @6
/ y  k" ?5 @0 b. G1 v" i7 G7
" W3 m' I% C. o+ r. @8* ~- \& ]" t/ S- f0 O5 n
91 x4 p& N4 s+ E( @! O. Q
10& V2 Q+ I9 B) l. H( m0 r& m
11  n( b& ?& Z7 X5 ~" ]1 D; O: N
12
. p( g3 t' B  C! t! K13$ R& t# S( m4 J) p! J) }/ t
14* e# Q4 d; Q) a% X, F/ N
15
/ H3 j, e' N) u3 Q( U( x% U; L16
+ q5 U- n9 S- Q5 u) a* {8 e5 U7 W/ _17
: ^7 z1 g& N; W18! c; m) _9 J% J$ g  [5 {$ G
19
4 {, f& C+ g5 b: x. t. P20# _' W. w) V5 Y5 B8 E) h
21# ]; w$ @9 e/ e, E8 m
22* D* W( f$ M9 c* x
23
6 @' B! F) z+ [, {2 ~; g24  D# m' T% R' d4 f. y" r
25/ M/ y) T- U. O1 p
261 M3 y: U, O9 W
27
4 f7 I9 ?$ @% M! `28
* n8 N  n8 O1 [29
) y* A# }8 T( |+ I9 B' O30
1 U8 k. Q7 g  o0 r; u, s" O6 V% ~31
& b4 L2 v9 v: J6 c$ p) I; ]. ~- _32
) u' J7 Y0 y$ Z1 V33
1 C! q3 J# l& b, A" r344 n0 J# A* o. F# @6 g
35
/ `. r: R  y& T2 @& r$ ?+ g36
7 c8 T2 r! }3 f' O8 L% l37
4 i6 J3 d. {- n7 H" a+ {& V38
; F4 x( X1 Y" t" h% D; V39; ~: J6 R% w! X
405 |1 ?; w% g9 {
41
$ W+ h# x% B+ u/ _% d2 V42+ h( t( u) i2 J3 R" i# D
43! n3 I( _! P  }; }6 A* O& K
44
0 B& I/ F2 C2 c3 X45, p" Y. Z8 O  m  G7 C& F8 [6 j
469 p4 r2 x; M3 U; K
47
% n) N5 Y' _1 ?) Q" s! `48
4 C# s1 e- U0 {# d; J1 ~49) P! s" e6 u3 }
50$ O! Q9 c! I& G& b. _
51
1 G7 E( I* M' B# f% Q  Q4 M非递归实现
' M" m! V7 W0 G( r6 d4 ?! @# Y+ R​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
% V$ m$ ^0 ]# O$ v/ S" _
! y& m9 _) D6 _. G+ f0 H; k( q, Y
) G7 M0 ]+ S- q+ z# p' Y$ D
/ s4 f  D  S6 K& T6 K% |​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
: E6 A, I9 s4 V6 `* w8 J1 b5 ~5 E
4 g& w( m- T! m' k4 c3 l1 q, Z​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。1 m4 O, \7 o' B* N: h* ^$ _8 [

+ v; |& n/ C* I: \; n5 M% G2 P/ [​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。2 ^6 [( s: l. t6 j' t4 T

6 G) Y3 ^/ Z/ O" c) j代码实现
1 `1 w; g0 g% N" o5 k
& ?% G4 \( A0 F  d$ jvoid MergeSortNonR(int* arr, int sz)
4 b) i. r* U; w0 |{6 M# j  `8 m! O6 [, n# E
    assert(arr);0 A2 L; W& i/ `! W3 l

  N. D! \6 S/ \* E) Q8 s& i, i    int* tmp = (int*)malloc(sz * sizeof(int));, g" L1 n1 Y1 [, C; K
    if (tmp == NULL)
4 o) b! S; ?2 m( {8 k) n3 F- @    {
+ S; P, y% \/ ?+ j" @        perror("malloc fail");
- Z( Q/ f. D7 O        return;  t4 {$ q; g9 k% z. g  b( `
    }3 n. _( P  u% w  L0 O' P; e1 S

" n5 _% B4 E1 `/ J" v    int gap = 1;
; h0 V6 Q8 V: C! x2 f9 c0 ~    while (gap < sz); ?( t8 P; @4 e# y
    {
: a3 T* }0 y; [* q        for (int i = 0; i < sz; i += 2 * gap)
& m% r5 t& Y1 q0 S' J        {5 S- }+ h7 F* ^  N) G) i. U5 s
            int begin1 = i, end1 = begin1 + gap - 1;* p% ?( v4 A, U: y
            int begin2 = end1 + 1, end2 = begin2 + gap - 1;1 \. M) T7 X: h" ?! ~: f, |9 C6 h
            int j = begin1;
  j' g0 Q4 m' x( X/ w5 L0 X, V+ G1 O5 H* h2 L" ^7 U
            //归并5 [$ q8 Q+ g- D. g2 D4 e
            while (begin1 <= end1 && begin2 <= end2)
' x1 A! F/ u7 O$ z7 Z  H            {5 F1 l) U9 n% y: d" Q, {
                if (arr[begin1] < arr[begin2])! `* Z- Z, V- o2 B: A% O
                    tmp[j++] = arr[begin1++];3 R0 E0 b* F3 J; m6 [! i, U' D0 @
                else     $ c" h8 i" W6 L% @
                    tmp[j++] = arr[begin2++];# a3 R0 P' D  n8 b, c: X
            }
! F: r. u3 h# O; M5 n* r% m
+ i# O1 ~4 O8 {            while (begin1 <= end1)
4 N' g/ ^  u% X4 V7 e. u                tmp[j++] = arr[begin1++];
& k3 p) v) b( Z3 ?" a  m9 U+ W; Y            while (begin2 <= end2)
0 f6 `% P5 _) g3 U                tmp[j++] = arr[begin2++];2 ~6 n/ t" A, L0 |8 K

# k0 x9 V# t) U6 D5 g6 Q# \: R            //拷贝回原数组——归并哪部分就拷贝哪部分回去% [7 F5 U: p+ }
            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
/ h, b3 i6 \2 x        }
5 [! n# K8 F% Q* G) x* U' k        gap *= 2;, k4 X- e& c( i
    }! W6 k) @9 }: q, {1 c3 o  t8 G
3 P8 z0 ^# l. \5 i; i% l6 L, }5 c
}
) m6 w: a  {2 B- e: r
7 l; M! B& A! E1) O! d* ~/ G" ^" Y" R$ L: F% e
2
$ z5 G% d" k8 }% O+ `( ]8 Y3: ?1 M9 j, x; }* L" F( Y( ]
4  ~" Z0 G3 _1 P  w: j7 [8 d2 H
5
9 t, |* ?4 P# B5 X: R6
9 r2 E/ x9 x0 w9 e6 }7) I! o. D, y4 h
8/ O% Y4 `- j4 o
92 g3 p7 E- `1 b1 {
10
8 f3 z7 m- i& P) v" v11( e/ s1 A5 t$ K  `" `
12
+ b/ U' R  e5 [# _3 w' t% ^13
( {3 O4 h4 I1 B" n5 V14! \, E% C( Y. @% J, f
15
4 a. w  |+ \& U, n; \167 t% L, G3 u, ^: d
17
) e" D# ]! `2 z18
$ P: ~$ r3 k* a, t$ z; J199 O) L% E& `# @
20  u$ V( q; S0 p
21, o) [7 t9 C# y2 l* T
22: b! h) E. `0 ]5 T8 _0 o
239 ]5 J5 C: @: c9 k
24) n0 E" \! R# n. Z4 W* H
254 V$ i- v! s& l! G) Z. b
26# q* o3 s, S" Z' r! R( R( F7 o
27: o1 J# v% h2 D5 p
28% o) u' W% L+ ]) X4 U. a$ L
292 d$ @* z: R1 S- X0 F8 a" b3 {
30
4 j6 F/ ]" M- g$ ~1 z3 r8 s31
% M5 x, e% C4 \( F- q32
: [0 L  c- P5 a. ~: `33
& {; V9 l( X$ M$ a; k348 |2 E  Z+ i. D" A7 [2 A
35
- ?$ }" Y5 m) S- J+ S36
% w% Q" d0 `* P3 N" w1 u+ M- _37/ Q0 a% M6 @1 J; S' q* H* f6 [: F- @
389 m6 U* w; L4 T
39
; C. {, b1 a! B2 ?! k6 E40, z* [0 r* g& p
41" m; M5 M6 t- P1 v
边界问题" U3 A8 p  U7 n
​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
7 g2 _. d& E% W  R# ~  B- I3 s( K0 U  Z1 f5 j3 q5 N
举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
$ S4 y. [, h2 K1 w( S& L, I( U
6 p, P7 L+ j/ r" \. N; d4 D, X8 H3 U8 e8 B" l, ?( M0 s

1 O# \9 \; Z2 r4 Q! o- N5 @0 l( W由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组); L5 w' ]4 S, K, I. s% }7 i7 Q/ P

" [" |6 F3 E( T" s2 S/ y第一组越界(即end1越界), D9 l  o+ A$ O* t9 r6 p4 G" |: A

+ B; c' j. G7 y3 A" y, J应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
/ K4 H2 S$ g; w$ ~! v# U; I& i: J
. ^. E  ]8 y7 g: Q第二组全部越界(即begin2和end2越界)$ _  G; Z" `0 r* @
8 P$ J" R6 t' W+ J$ L& G
应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。/ b# c+ Q- t+ r( Q' n% t7 n' ~; d
5 ~0 @5 g. ]: I; f8 T$ t- ], g
第二组部分越界(即end2越界)
% [8 C0 j- _/ Y! T9 {9 ?7 s8 E2 L+ D' w$ \  {
应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
: c  K! u& Z$ S7 W9 X1 _3 U
6 s( `+ l# C9 M) k/ [5 Q​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
7 Y- ?% h2 t' _8 e, R% |# D: E' d/ f0 n
​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。5 L) a8 z4 p3 [( p8 `( o
! j4 p( L& |+ B& V. @8 `
​ 拿两个数组试一下:
4 T2 C/ I# A; v4 t  G9 }2 N6 v5 F, Y- F
# ]* d0 c8 p8 s) z6 q+ s

7 W- F0 {; \+ S" n; J3 H' C- B  F! @  w- V5 N5 K9 {3 u
) J' E% m/ k/ X; Q
代码实现
7 ]; t+ l  x& r1 }! g2 G) T9 h$ J: Z7 B$ E  G4 S  Q% }$ N, W
void MergeSortNonR(int* arr, int sz)
- j, O# O6 R! Z0 P$ ^{
" x2 X- t& u5 R1 j# p    assert(arr);# ^" A1 n; p$ X/ D7 Y
  q- O! f/ M, X& Q# {
    int* tmp = (int*)malloc(sz * sizeof(int));
8 C4 I+ ?: t- C$ s/ ~% `& ?    if (tmp == NULL)! V% h" X  p7 Q& Y6 q, t" j
    {' u( l; I- B6 B' l
        perror("malloc fail");) R2 s6 E/ N" N
        return;9 Z. Y2 o  Y2 o% m6 E4 m. S" p
    }
+ n! i9 w+ C; l( X, v* C# ]% z
* J; @! w, P- L) b# d/ d" u    int gap = 1;' o" ?' q( }6 c$ h$ q, }& I
    while (gap < sz)
* i& L7 K! f+ q8 ]8 Z1 k    {( H7 B3 ~# l* i
        for (int i = 0; i < sz; i += 2 * gap)
' w8 T' d. A" z1 P# u        {
9 i2 {- |" [1 P. p            int begin1 = i, end1 = begin1 + gap - 1;. D; i  L$ `, {& U% [
            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
6 I/ j' @, V6 @$ K3 \% {            int j = begin1;
$ v1 q; }: l" K  {8 ]9 p                        //越界检测, v# t8 d$ z/ {/ j! X# i* v
            if (begin2 >= sz && end2 >= sz)
2 \0 ?! Z0 Q2 m9 {9 n- h6 i5 v                break;' v% ^# L; t. Z! D$ p
            if (end2 >= sz)  O$ v, b0 v$ o8 s1 J. y
                end2 = sz - 1;5 F: m/ ~7 ~+ T9 z9 g" h( x5 R4 V" o
            //归并6 B" v/ a2 v5 u3 @$ q7 B. h! h
            while (begin1 <= end1 && begin2 <= end2)+ ~6 T. s* K! {! A0 ?
            {
6 S' u) y' Z# a' l, f; Q; X1 O/ y                if (arr[begin1] < arr[begin2])
+ K0 h/ ~$ F2 E                    tmp[j++] = arr[begin1++];
1 N( ^# J8 ]3 n" D                else     * B0 I! }* b2 A/ \% d( O
                    tmp[j++] = arr[begin2++];6 [3 g  C& `7 R  K5 @* P, ^+ m
            }) d" y8 @9 F) s6 r

0 p8 f6 c3 G' _) B0 ]+ b- N            while (begin1 <= end1)
$ Z1 X: L0 ]- m0 {& ?9 L. X* Q' t' r                tmp[j++] = arr[begin1++];/ @3 `" u8 S5 }# o, M, A. j
            while (begin2 <= end2), [# N( m8 O( U) m  L& a
                tmp[j++] = arr[begin2++];: A  Y* R  q! [# X0 D6 Q' d

/ [# o8 }- i: A: }: |$ D# L6 |            //拷贝回原数组——归并哪部分就拷贝哪部分回去  f+ w, s9 P. n- W( W7 d
            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
7 f: C' F+ t& ^* q        }
; }- d' J5 z  Z2 w        gap *= 2;# W: g. f' \* B3 k: _
    }
+ \. z  R6 F3 _- Y% A% _4 ?
$ b* K! b8 q  E( O}8 z* Y3 J$ z4 U/ w

9 s# H6 Z- P" ^) [8 q* O% K( z1
$ v, M9 D7 N2 l/ m% ^2
2 f8 K2 F8 O. W5 g% _7 R! U% C3 p3
0 s8 Q7 M4 ?% L& P47 b/ x( ]3 d+ n9 \/ H, F/ s
5
7 w; a' g! ~& \9 `$ \- X6
/ t: q- t" E1 M7 W4 N$ u- Z7& B5 Z* X0 m, l
8. ^( T. z; h% v% f' w7 G
9" g! i' E1 e7 @
10
) f% q$ O4 I" X& Q0 j( G2 r11
+ k9 Z$ q( k$ n: P120 T2 r" x* s3 r9 D$ e, h# @
13& f* }& k+ q5 g/ b2 ~8 p8 H
14; [5 s, y- t  H3 x. ~: P' m, |; A0 R& [
15! s" i) u/ x9 h" h/ l
160 \1 U4 O2 @- q  @
17/ c! n8 X7 C8 [! t8 j+ T! L
18) p# ^( {+ p9 [  l; j0 n% m
19: l& G) ^; e0 N6 c
20
. t, W# ?. v. r. }7 \21
% O. i% h$ b4 }5 a220 H9 X( N1 ]* h2 z1 {/ H% N3 K  s  K3 I
23$ K9 j/ W. K, ?7 e
24( V, ]% Q  N+ x$ I# d; ?* l! h
25
& F8 H$ P* O" s4 J2 [/ U265 b# x; d' t9 b0 r2 h
27
& Q+ `  |- }, K# e7 {* B28! A( E$ W- y5 T
29
& L2 P2 a& v* H30
2 x$ F+ M0 o' \7 L4 p, y31; M5 ^4 ]$ s' b# \$ N
32/ K" J0 L* }9 z1 C5 U
33, ]) k% q6 L+ g) u9 s) i
34
9 Y, R, n2 A7 q. h35" c0 i, Z7 B/ ^- s$ J
36; G4 C( O, {5 b( Z
37: i! b0 l  x/ j$ {% ^' b
38
3 O0 n9 P5 g' G# T! c. f3 i395 i7 Y& w6 z* R; O( M0 F
40
7 @- [5 S2 _& h3 B; E& @41
3 [2 w( {% a3 d( M" _% G6 s1 K5 T42' t4 s1 b& b; @0 M/ S
43! m; y6 S) G4 {! ]  @
44
( W. _; I" l) Z% d/ y$ D1 y2 n45
7 [. E$ |/ B1 U; m& I归并排序的特性总结:' `$ X, P3 N& s  _6 n

- K, D' X$ u7 m8 _: E归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
( j9 I% q9 r0 p( p/ L时间复杂度:O(N*logN)
  T4 W' S+ b+ l7 l+ z) H% h- O7 E# r# x空间复杂度:O(N)
" E! _5 |  A0 n: s/ A, K. u稳定性:稳定+ d3 u- ~2 x7 e. ]! |- E9 e  J

7 M( S4 o4 Y# h( h$ n- B————————————————
1 w3 J2 J' E# w  A& ^& `版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
( K0 C0 y3 r+ L0 G) I  e原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
0 v$ U5 A/ J& T1 H9 ?9 W4 o& L3 G( k% O# r
5 Y7 J& R' w  o" Y7 ]9 D/ E. T- i* f+ {% T) s! _) S+ r





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5