QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3272|回复: 0
打印 上一主题 下一主题

[其他资源] 【基于C的排序算法】归并排序

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-14 16:22 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    【基于C的排序算法】归并排序
    7 G, i5 l9 J1 q* m5 o; p9 r( P* W, l6 b/ N6 N; z5 B% i
    前言
    & |' T! P; u# ]3 [4 j4 D本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。$ o6 i' Y5 l4 H0 a+ y

    % Q+ i* F8 o: y4 r2 |& @归并排序2 e3 ~5 V% U" [
    基本思想2 \0 O3 c$ a( @1 I% D& M) d- R4 f
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。2 d$ e8 p7 `" O6 R% T

    + w# N- ~/ r, t" S! g& d
    - Z/ C* r# S: H; K
    ) `# n, i9 _6 L9 j" I2 U& X- k' c* \​ 合并的思想其实和有道题目的思想如出一辙:1 y& d$ N! w# Z) Z6 s* ?
    5 x( `1 ?4 `$ \3 x9 S  u6 l* s
    , |# j' S4 h2 C& W' Z% [4 D% P" H* q
    4 Z0 ?  a" E  L# C
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。5 I7 y9 \, v( ]3 i. ?- n

    3 i& y; L2 F$ r' l& G4 P6 A[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    3 [/ M' k7 \$ Z: o1 W
    # F* O' S8 B8 e, o, M1 l2 P% [, |int* merge(int* nums1, int m, int* nums2, int n)
    6 J1 h$ u) l$ F8 O, `{
    9 U; d! b9 X: L; h& g4 E        int* arr = (int*)malloc((m + n));: {4 X' v% O! b$ h: J; a: ^
        if(arr == NULL)
    & T; b6 j) I  y7 p3 D4 i    {
    : j8 ]) O0 [% e3 G+ Q: d        perror("malloc fail");
    ! m! s7 S4 D% B# b        return;
    7 i: _! V% h- [6 o    }
    1 ~, d1 X8 E( y- Y+ z/ _7 v! q4 w+ `4 B7 M' q# B
        int p1 = 0;1 M( z$ c0 x' [. e% `6 R  e
        int p2 = 0;
    4 M; ?3 Q5 U1 _3 K+ s3 O& A$ z  \3 r    int cnt = 0;
    ; w# J3 s; b) V# |1 u5 c6 _    while(p1 < m && p2 < n)# Q7 b& C( {- w" d; Y* n! A; o
        {
    + }" s1 o% B0 k! |# W        if(nums1[p1] < nums2[p2])
      P  j6 l1 B, E  q, ?) b, v, k0 c        {
    - h8 i/ u3 s4 H/ E' @1 ~            arr[cnt++] = nums1[p1++];
    ; {7 _# F5 X2 F. B' `        }
    3 b& r. E1 ^! o; k! Z5 D6 ?4 u        else
    7 H. c8 {. v# r& j# b        {
    1 @; n5 ^6 e1 W! m8 G3 a  k            arr[cnt++] = nums2[p2++];3 Y$ P1 M3 c( G- \
            }: x4 I) i4 P8 r& J  C2 t$ \6 s
        }
    - @  y) h6 E: j4 Z) s    while(p1 < m): v- x' b" N) u4 H$ P4 E
            arr[cnt++] = nums1[p1++];
    ; x) o0 Q2 \9 q6 Z4 X! a
    + o) u' R2 B* K" o    while(p2 < n)
    5 o) j( R. x( k* _; ]        arr[cnt++] = nums2[p2++];
    5 z( l3 e8 ]5 j9 x( W" Y% b1 K: S3 @2 o
        return arr;: J7 x( t, D* J; p8 J
    }
    8 K# Q; u; c% I+ L/ n8 e6 j2 `
    1; N$ f$ u8 a; ^- r! u7 W  X
    2
    . F3 N7 w# x3 K33 G) n# H; E8 B  v1 Q
    42 \( e9 I8 b$ |
    5
    : p+ d% v3 N- Q- K& c1 s+ @6
    5 p6 V( i: ^7 B74 x5 O3 r/ ]/ k/ B, k7 ]2 [: L4 x
    8
    6 A+ {9 ~. Z4 W) Q' j7 f9" e: {0 T3 O# u/ k0 p
    10
    ( x( D3 h" C3 F4 @; a113 {8 K* F) S" t; l% f
    12
    / Q! Y6 [0 }( d0 t2 _13
    ! p. v( K' U% o2 F! B! {9 D9 ?6 o$ b14
    / _; O- @2 d! ~3 {$ k' s$ K6 Q! h, f15
    & N9 c, A1 g6 A- q1 r164 e7 }8 Z7 U( O- F
    17" T& p# i( @3 Y3 ?8 V& F2 X, S
    18/ G8 e) K# U9 Z/ P9 o& Y
    199 {' W8 R' C; ~+ `$ R. O4 b
    203 t) _4 L6 w9 b8 \  j. r
    21
    / n1 f* D* g# ~  U6 ^22
    1 o9 R3 S. G5 c23
    : z* _- x/ F5 ^4 r24
    6 G% H8 F& a1 a( H+ q25
    ; c9 K( I+ ~' h& W9 k6 Z26# Z+ V3 h& r* ~9 D, `% v; B
    277 g  r. w" u# G
    28" j( e+ m7 P8 A* }" V2 d. t
    295 m% S$ t+ k0 }7 j2 D  e
    30/ B! V8 |% d2 m
    31$ ]+ V! Q5 m* l: Q4 ]4 T
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    4 V: o, H6 X4 |2 B: c" c. P8 \3 Q$ l3 h$ l, f
    递归实现3 y! O! s! L( O% F' L$ K5 y
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    ! [8 r" Y/ m# o
    # j* g# f3 Q+ K, [: O/ K, `) {- w) z
    9 z0 x& D2 A# C2 x; o+ {

    # N! H" L% V# S( T5 L' }6 n* @' V  v0 b# x: s
    void _MergeSort(int* arr, int* tmp, int left, int right)
    : i* |. p# M7 x{
    & O2 z+ c! K- v- o% u4 N; G    assert(arr);
    . j+ H& i9 b/ E8 {) F1 w% |# x% X: f, ~. b
        if (left >= right)//递归结束条件不要漏了
    0 i$ w8 y) _& J. f        return;8 E8 z* D6 I$ `1 _2 O' [

    ! E3 b: C! @# _    int mid = (right - left) / 2 + left;1 l; J9 m; n" |8 l

    , e" k3 A6 j+ b- B+ E$ g    //划分左右子区间[left, mid]和[mid + 1, right]( Y0 ^1 ]  A) V2 a& M7 C, N( m; g
        _MergeSort(arr, tmp, left, mid);# h! |$ O) w: ?8 H
        _MergeSort(arr, tmp, mid + 1, right);
    ( ?) F) t, K5 v: W% d
    5 Z+ |+ ^5 k- s    //归并& s3 j6 h8 t  v. v2 O$ X, _
        int begin1 = left, end1 = mid;8 ~2 u  A0 a& s! B
        int begin2 = mid + 1, end2 = right;
    # w& U4 {: n0 I* j; t6 y( l    int i = left;1 r; S+ v* C% M7 l+ n* o" G
        while (begin1 <= end1 && begin2 <= end2)6 k9 i! w  d  @+ [
        {& C$ {: n: X- u) m8 E
            if (arr[begin1] < arr[begin2])
    4 G7 J0 H% y% v# r+ H8 T2 a' E            tmp[i++] = arr[begin1++];% |/ a4 \, d1 W6 W5 z0 }7 h
            else3 d, I$ x# l" N
                tmp[i++] = arr[begin2++];
    2 z) K4 F6 c5 m" s, X+ T    }
    - f6 L! p! Z5 d$ Q6 `) P+ j( u  R6 V3 a( S4 z) e- Q
        while (begin1 <= end1)5 W9 x0 S' i. m. i9 K
            tmp[i++] = arr[begin1++];) L$ w$ `. {7 B$ y8 @
        while (begin2 <= end2); Z* ~$ F" W8 [( v% Y
            tmp[i++] = arr[begin2++];7 M: U2 k: K8 p, {' N% y3 t
            $ Y( M* g4 @' k# d9 X
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ' ?( C3 n, V. i# y  i! Q0 w' D    //而不是拷贝整个数组回去- {; j6 J8 G8 `' I9 @
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    . a' m* d) y. W}' Q) ]% A. l2 X4 G8 p0 a

    : y* V1 [- R( p& Lvoid MergeSort(int* arr, int left, int right)3 _7 I( l/ A5 j6 H4 f9 P/ ^
    {6 l( X4 `% K& C, b5 l
        assert(arr);# U, K$ n& J, r
    8 A; |. v$ B. \: O& r: @% {+ y( h
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));/ x6 [% H# f% e
        if (tmp == NULL)
    . k9 r* h  E) n. T6 L- v    {
    . _) n) T* ^9 Q) E. p        perror("malloc fail");7 f1 L8 Q, d- q
            return;: `7 }4 ^7 m& Y! v6 a4 [: k
        }/ j5 B; M0 @# O/ |
    6 |" [/ ]1 E/ x( b8 d% f/ ~
        _MergeSort(arr, tmp, left, right);
    ! z# d4 M- Z( ]4 l) {$ `8 a" ]! K2 G8 L( _6 U  y2 E0 t  L
        free(tmp);5 I& N7 L) {4 w% p: N* r" E
        tmp = NULL;
    # s( D- Z1 v4 i$ S% I}
    " i( d$ h- r5 F7 y
    3 w. i8 ~( W$ y+ h  {2 j: Q- k) X- x( x1
    ( Z# @8 b" `" N# a2 {" C& \26 v4 B; Y6 V: P2 |/ p' J
    3, U# J* H1 m) V7 G" ^
    4% @* }8 M" E. P6 _5 g/ @0 l
    56 J9 E7 {5 Y* ?7 X3 L
    6
    ! ^2 x+ j3 p; f& _  r* e; ?8 o7" D# r4 j% @/ n6 ]1 w- `; a
    8. L. z- w% a7 q1 Z! ]* \
    99 U8 o/ y) Y! Q- K, t6 \9 k1 g
    108 t* }1 ^* m+ m! z
    11/ X2 N  J% S+ Q3 G& @% U$ _
    12
    8 Q) x7 w* i9 b4 P- Y7 Y13* J8 m( J8 e% y6 N
    14
    * T2 h; ]2 L1 h9 i+ v15! Z8 U1 u- L( I4 M( A  c
    169 M; f- M2 _. U* E- G% P
    17
    * I" f5 y' e2 n0 F8 X18: e  J9 w9 ~& C+ q' K7 F3 b
    19! Y; ?8 l6 T" ^7 t8 |
    203 i: \$ M; t- F' R% Q0 X* T
    21
    " Q( I9 }; E! B# ]! @% R22- v( n' H$ f) E4 {$ q1 Z4 v
    23
    0 o8 N+ ~9 f$ i" W- W24
    " I6 Q# r, d( |. h25; V& U6 q6 y( L" Y; e
    26
    & ?. U* e, \5 r9 {4 ?+ i9 A0 N2 K27
    0 K- m  x  H# V9 b4 c28+ }3 [. |5 e6 e6 ?
    29
    . v9 l+ V) e% ?: m; U$ _30
      c9 F9 ~( l4 f! l5 b  J31, `6 K/ I$ D6 ], k* S" ~1 w
    32
    / L+ X- D  B/ a7 B4 A7 k33& x: ]8 M! `9 M. ?/ C0 V
    34( U( m! J1 C0 |" F
    35
    9 f7 M* y+ U# H6 O8 b6 t6 ?36& o3 W4 a& P3 Q% M$ |7 n
    377 a2 P/ H! R' c
    38: Y& D8 a) e' R% r- ^) C( P
    39
    9 A5 r! H1 _+ G- [40
    , x( E- X" _3 ^% _41+ A& ~5 f7 y9 V* r0 Q3 ~" d3 W: q
    42+ H6 ^2 B+ X+ a0 \
    43
    # `  g' _/ _$ D3 ?& m( v44% J4 [* H( \2 {$ @  y1 C
    45
    - y% Y6 J9 p8 k4 ]46
    ) ^6 J) R' w# N8 n5 l47% Q7 e# B( r- |. f. P
    48
    / k, j) K) L( P% \$ o49
      n: G' [1 _% c50
    # |3 H5 g8 {3 R5 L. G9 S0 B51( n6 D, y) p( T) U* z8 {* U; d+ K
    非递归实现: T' ~# e; q, E; P/ s  [+ o
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
      U4 l" i, `* T, D
    3 Z$ ~% r" G6 T- x! e
    9 I! n; i3 S" `+ T; R$ y
      m4 ?, n0 O% ?$ e" S/ a​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。4 z# k4 _; r! g, C7 a- l" M! t# U* j

    9 x8 R, E% C! `. X# J​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    % _5 R9 G  ?# N! m0 p  J9 E  N, i! ]/ ?' ~( Y
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    * K: p1 k5 z0 Y: n/ e! R8 b" x; f4 ^4 g. {. F4 d5 F5 m+ G, D9 I
    代码实现
    2 C3 J- q% P7 Z4 {0 j8 Z6 h3 {4 C! [# z- k) V
    void MergeSortNonR(int* arr, int sz)1 S3 r+ V5 m3 L: d- z
    {: z8 @$ d. k8 c  Q
        assert(arr);
    # a! x; a. J' O0 `* m) s2 E5 t, R& ?. P
        int* tmp = (int*)malloc(sz * sizeof(int));
    - E- w. c3 Z4 }    if (tmp == NULL)
    ! r0 _. b( r2 e$ i! r    {
    / o( B. _' B0 M        perror("malloc fail");# u" F/ i0 A8 b6 M% r
            return;* s7 U6 }# o* z4 M( b4 k
        }; Y  g. \7 ^( O5 R
    2 a) X/ n; y' [, `( u
        int gap = 1;- h. j+ z. f# [7 Z9 ?/ a
        while (gap < sz)* A$ c1 O" }. U1 j# e: G* u2 F5 B
        {1 `2 d2 O+ M& m. }
            for (int i = 0; i < sz; i += 2 * gap)
    / \/ X! P' r( F  f6 @        {' P: Z% f% ]1 O! f
                int begin1 = i, end1 = begin1 + gap - 1;
    % f5 k+ J' {& h9 n9 @5 G& u2 r4 n5 P, ^            int begin2 = end1 + 1, end2 = begin2 + gap - 1;0 u$ y' ?5 F" A2 R8 h6 T
                int j = begin1;
    ) P# i7 A4 m* l" u% ~: n( h% I' N6 r' J: M6 ^4 Z- T+ R$ G& `
                //归并) ?7 R* _% A8 |1 G3 f/ a
                while (begin1 <= end1 && begin2 <= end2)
    5 {- J3 Z- G7 n3 q0 \( }            {
    0 _* ^! y0 y$ z# P; {: X: j                if (arr[begin1] < arr[begin2])9 Q# |# B3 e/ T0 S& S5 @! ^
                        tmp[j++] = arr[begin1++];
    % n+ T% B) p: Q& ?- I                else     + U: }4 E2 B$ u5 [. o9 C3 q
                        tmp[j++] = arr[begin2++];
    3 @& Q; i9 c6 S) w            }
    8 ~- j4 p' L5 A' E! w
    5 r, i! n. n2 E            while (begin1 <= end1)- y/ H; O0 @2 |1 A
                    tmp[j++] = arr[begin1++];
    - k2 ~/ b; D4 r( ~! f6 x$ h            while (begin2 <= end2)
    0 h* [5 h! w, q  w0 V& H6 t3 a/ {                tmp[j++] = arr[begin2++];3 ?3 ]* k) b% N. `6 \

    ; Q% A' E( W: P9 F7 p2 N3 R- W' A            //拷贝回原数组——归并哪部分就拷贝哪部分回去& P1 o' f. t: ~6 o7 E
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));0 z( x4 Y- s/ g2 j- ]5 G  ], t
            }
    3 G0 t$ A; K; `$ t( u8 A' {/ x0 W        gap *= 2;3 `% \( c% N+ I, C% E9 f$ C
        }
    : }0 ~1 c/ X( A( s$ r, D* d, |. b
    7 `- |3 P2 ]) A2 T, _+ H}. o8 B! r( j' J' x/ T

    4 g$ V( }; t+ W' W9 z5 v, d18 ]* X9 W/ ~" D! u% Q6 [
    22 f7 P9 H8 M% V
    3- k2 e( J) b  p8 w$ @& J+ I' N
    4: @4 e* m- s! l& R: v3 C
    5
    . X' ]& n9 E, c8 v2 ]* o6 f6
    5 b9 y) Q: [  @  c7; Y& E& ^7 a+ Z3 B
    89 r( X: g! N  A
    91 h0 t) r. M! e; z/ M$ x5 S
    10
    3 j- ]/ J5 B' v! K* E11# w; m" r5 ]% u1 u# A: z& }
    12. J9 `4 B7 V; e; N
    13
    + i; b$ Z7 f0 O# C! n14
    , `# Z$ Z( s& Y15+ y8 R% A; W. c! R  m, f" E: L
    16
    8 O1 W! }$ i5 q172 _  ~2 t' [, }5 C9 }2 Z
    18, K$ e1 t' x. r1 l9 ~! ]
    192 J! ?0 y, }1 R3 g* N
    20& C$ b1 F! M, I# f. J/ Z1 \& ?
    21
    , E5 N! B. U7 `/ Z# N2 a, J22
    * x- o, j; D. y2 b- Z/ s! Z: @/ s236 T, u' F. S. o% P6 S# d2 Q
    24
      \/ f3 W5 s( M" D25
    3 i. v  L9 Y: q' W0 o# z6 q26; P. u+ N9 f+ X4 S( a# g
    27
    5 i. P' i+ g" H$ e28" [& {- f6 Q! I' I
    29
    " l1 z3 [6 M0 [) H/ F302 s0 M' {, o( \2 ^" F( r
    31: l. p  g. O1 ^: u4 |9 ~! v
    32
    0 C3 ?. W3 P1 m; T33% b" e! q5 h% M
    34
    ' y( @, C  b( f+ W. A35! d: q9 \) q1 I$ V& v
    36
    " C+ ]: s( Q% Y/ s+ Q37
    ! V2 I$ @6 I7 t38, d7 p3 Q) u# N# ]) S  c* M
    39
    # M7 {9 r+ X9 U8 `; l( `40% A  u1 u. W* L4 d4 y+ @
    41
    ' T" h: N, u' [5 C边界问题" c: _1 o6 c0 K/ r+ i6 W
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。8 O1 ?7 i& G8 H7 b2 u/ m

    ! ^* b5 l4 n, d; O举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    . q; \; N/ W8 K- V* N* G* }6 l5 Z4 L$ H, }" w% @

    - r; G+ [4 g0 Q/ g, z5 l
    5 U2 X( W6 N% _5 A' Q8 K由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    & L$ m& h$ \: S( ?1 M; ~. I
      Q1 q* D  z, Y4 @5 h9 z/ w2 U第一组越界(即end1越界)3 V& M7 @3 k  N* E# Q0 |
    0 ^/ u8 L, x/ |8 q# v. T" c
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。! _; z- b5 W$ S( W' L2 t
    ' n8 {) Y& d) g" W2 o: ], ?3 M
    第二组全部越界(即begin2和end2越界)
    * ?; ~$ _  X- K, g8 Z8 J9 i- s
    $ Z, B1 _( \" C8 S- \. ~9 N0 y应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。: o. g4 I5 v" w% ~: C# }( }. M0 O

    1 p2 R$ n/ q, l第二组部分越界(即end2越界)( A' e$ j" e8 E% A7 C

    * a6 T$ W, e1 I, M1 e+ ]  p应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    0 R$ m! g1 ]4 V1 B
    # z- W1 m3 N9 E0 k6 G0 t8 d4 f​ 其实第一种情况和第二种情况可以合并为一种情况,原因:. b) i) `, @  I* C

    ! `3 [- E# L. g  K6 J​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。0 e) s& m2 U; f+ Y6 e1 G

    3 _) _/ f# y, ~$ F​ 拿两个数组试一下:
    ! J  F' i* p3 m7 B. L' @
    ( O- |& p0 t! u" W( v9 g. y: T3 v5 }( o
    + w4 U% |4 m% g5 d; m# s

    % {# b1 i, }9 g- `& N" _0 P, F) ~, `/ W3 h- X
    代码实现) {' `" `- O3 Q, O9 k* c
    " m0 d; ?4 R) {5 `& `! K- c; o
    void MergeSortNonR(int* arr, int sz)0 ?  z! p$ S" o4 Y
    {
    , C) p+ ~9 o0 H9 h  k# W    assert(arr);
    3 J& e+ V$ b* V" G: K$ V+ n
    & d7 H- z; x# l6 w, M    int* tmp = (int*)malloc(sz * sizeof(int));
    / ]) A. w  A; d+ A    if (tmp == NULL)
    ' T6 g' Q, g2 x; o6 I* ]' m2 e    {- G. r! ~, ~$ r0 K7 m9 v4 s* d9 Y7 L
            perror("malloc fail");
    ( ^4 d! S0 T8 j! }4 t' @; j% T        return;
    ; j4 a5 Y5 Y/ Q    }! Z3 E! P! d7 u$ A" Z  A' l
    " d! ]( ~& x6 w# \( q$ H) c, P
        int gap = 1;
    " i5 n6 u8 k1 x: n- M3 B* N1 Y    while (gap < sz)
      _5 l6 m: L- d) `: J* i    {
    8 @2 J5 b! [7 z# n' n+ H        for (int i = 0; i < sz; i += 2 * gap)1 Q( G, W5 T& S: R
            {
    ' \+ S; k. Z/ W$ L$ W  F% C            int begin1 = i, end1 = begin1 + gap - 1;* h1 i: y; V+ N3 O- p: {
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    9 A9 M$ `8 a; T+ f9 E7 C            int j = begin1;
    * c! Q" B0 g& k* m+ ^* X+ R! L. V                        //越界检测( {. {7 a+ q& v8 M' h' e7 R
                if (begin2 >= sz && end2 >= sz)
    ( O/ a0 J, ~) W1 t                break;
    # C! M$ t/ T7 E6 {0 U: X            if (end2 >= sz)
    # P; H  j1 W" y8 }; q                end2 = sz - 1;
    0 i- m1 }4 p' c            //归并
    ) C! K0 v3 z* F/ ^+ B            while (begin1 <= end1 && begin2 <= end2)2 V3 L1 }0 a7 W+ n
                {! V; D2 l9 q4 T0 z0 l
                    if (arr[begin1] < arr[begin2])( E' q) w. n' h- I. \* \
                        tmp[j++] = arr[begin1++];- P; [/ d" i: S2 }7 z1 R) M5 e
                    else     
    ! |& b+ U% A% R. @                    tmp[j++] = arr[begin2++];
    9 {6 E) j4 z3 f, k# x: @0 m            }0 B$ g# }% C' w5 H& T
    2 G6 e. w7 ]1 @) U" \1 N( x
                while (begin1 <= end1)
    4 A2 J9 Y% y" |9 A% h+ z                tmp[j++] = arr[begin1++];
    " Z4 k0 I) i$ ]  M8 \1 y+ H6 `* r            while (begin2 <= end2)
    7 E/ L4 y/ Z4 g                tmp[j++] = arr[begin2++];
    % y7 w2 x' |* w2 m) s( U7 m8 b* Z/ _$ ^1 M# K7 t" A1 D) i
                //拷贝回原数组——归并哪部分就拷贝哪部分回去4 ~+ f/ h! b+ m7 ]! h
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    3 ~9 j/ c7 b1 Z. a" v2 `        }7 V; ^6 n6 J4 e9 E- h5 h) y
            gap *= 2;+ `! p+ h" r/ c" G: k* \" l) X* y; ^
        }; t( G& v  B! x: ^- z
    8 R3 ?1 b2 c4 k8 \5 D$ O( Z
    }9 d6 e( b0 z& }( H) J6 k$ ?7 B1 `
    ( ]' h% K& W/ h6 F5 B
    1
    ! V$ O. v9 ~( I2
    9 r9 ~7 I  q# Y& N- ]3 |3
    ( z) q1 B' R; @42 f- f/ ]. ^6 O. c7 R. x1 {. J
    5
    + R' `3 k, [5 y+ C: L6
    , L6 Z9 r4 S& q; U. y73 i& Q4 }' }+ {; b$ U' V# i4 G
    8
    5 C& @$ X; e" O% _7 G; Z# H) _94 r- n! b4 S* N" H- O0 h, j# _
    10
    0 T% z) S" y, J% }11
    9 `7 j' N! V+ Q, Z  J125 v. N7 v; w5 U( W- P4 W9 j8 B$ v
    13
    9 Y; \6 I% t6 l  X8 j  j4 R140 a. G2 B6 V3 U! M7 M; ~! c/ A
    15
    : f* P: S! c6 h( w- w1 H+ w16: @/ z* T2 q& B# b. K/ W: P" h
    17# s$ j1 ^5 K! ^+ Q; l
    18
    : w) n) U6 [6 H# T0 s" e0 O* t19
    . t7 S; d- n. f; w8 ?% z20) B/ V  U6 W* i$ v1 o$ f$ f' F
    21
    6 y+ r1 H& ?1 W) [( T" h+ [22. Z/ i( k  l6 B4 @9 K/ I5 f0 ?+ ?# _
    23
    1 j, ]9 }7 U: q+ X+ H0 Y24
    # B  U& G% ?5 v; j25, F2 _/ a9 o2 M- S% R. n3 U1 F
    261 ?7 y& r2 H$ D- L4 J# p
    27, ]: v$ A& E/ w
    28. q) ^* k9 t# e3 O/ O1 N
    296 V8 j; q9 k" N- T
    30
    ( v7 L# q6 c* P" L31
    ( {/ C/ X2 a) @: f4 z+ D32
    2 d6 o6 e9 L! f- ~! `/ G3 f33
    $ f7 J4 Z6 ~: p* K) S/ \7 n7 M$ F9 [34) t( ]: b7 R( ~% d* F6 [/ D  B
    35& b1 e) k) A% B) J" E
    36" `5 d2 A3 T+ |1 _6 _8 m$ _$ b
    37
    ; k4 R7 {* O8 M. _38! o5 u0 s8 m$ O3 D
    39- |  D8 {& t: Q* N
    40& r+ o5 e# K9 w; F# ]3 |
    41, M* j: O2 I5 {; Q
    42' Z# ^; ~1 n& m+ i+ T1 h$ q8 Y
    43
    / m: I( f. Q8 ~- Q44  k. ]9 j* m0 r
    45
    - C7 H. N/ r; ]( G# ?归并排序的特性总结:
    ' I/ O, E/ f& w" R3 x4 @
    . n; y) _: H$ Q% E归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。1 }  t6 V+ v- @1 D3 f; p0 J
    时间复杂度:O(N*logN), V. g, q# c" ?6 A7 e+ z; B* t
    空间复杂度:O(N)* D3 C9 ?, y5 ]. d1 d2 g
    稳定性:稳定
    8 H- C/ r: n4 _1 R8 k* b& F" b* p" g# v4 ~
    ————————————————1 L% H/ X$ _: E
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。0 M9 j6 ~! M1 ], V
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/1267966571 v7 Y8 F( R( s; j

    - i$ r9 \, r' \( O- t, o
    ! ~& O0 @; f7 m0 t3 D4 J9 x% r" J
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-13 06:25 , Processed in 1.218415 second(s), 50 queries .

    回顶部