QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3295|回复: 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的排序算法】归并排序
    & h2 O! S" Z4 a% a6 {8 W" B) l8 B6 B9 d7 X  S: I$ i
    前言- T& |1 }5 q9 y% U; T2 h  f8 I
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。% C! [! O* M# e9 M8 O5 [9 f

    0 ]; q. h, N+ N$ C  @归并排序* q! J5 |$ t/ W: B* o
    基本思想
    0 e  \& l1 W- z; k" e​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    " F: y* n5 |/ n, _
    3 l* f) F1 I8 F! R# \
    8 w3 O1 _5 h! v5 j
    * _# T/ e: i  Z& L​ 合并的思想其实和有道题目的思想如出一辙:
    & C$ u& |/ O& O4 p
    . X9 v' P9 v- r, m3 Q2 ?
    ( c% ?, z: G5 J& }8 p! l( z
    * }/ P- c; u5 G$ p1 K; j​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。% @% w6 f1 ~: O  x  K

    ( Z4 O5 E; z: V( |7 q$ w& l[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    2 @; M0 q* C+ f" P) |) K+ U- e
    : p9 n, \8 C2 a4 g: eint* merge(int* nums1, int m, int* nums2, int n)+ \/ J# C4 J, `9 z& A+ i
    {) `4 t& E& b% s" B) Q! a
            int* arr = (int*)malloc((m + n));% p- t( O6 |! h2 Y0 y
        if(arr == NULL)  E7 ]4 G9 W+ \
        {
    / L* P; d; w% i7 b8 }0 p1 ~- C        perror("malloc fail");
    ' i; @& x# d( K% A0 N0 i' F        return;5 d+ t* g" B0 c" R! i) J" W
        }
    % p$ l! t" F6 i" {% R6 @( g) b  w! ?5 f0 `& E! N9 X
        int p1 = 0;0 ^' D2 M% I4 r( I+ a) y8 P
        int p2 = 0;$ u  j3 x2 Q+ v/ b7 G
        int cnt = 0;
    4 X$ z/ H- s# v+ I9 g/ |: R    while(p1 < m && p2 < n)
    . A1 X! \$ V5 \9 ~' m+ v    {) P: z" R+ D- @  H
            if(nums1[p1] < nums2[p2])
    7 w5 O4 i0 j+ V, X: [) B        {* ~- w  r) F* w% V
                arr[cnt++] = nums1[p1++];( x' m; U) w& E; G* F; h
            }
    2 h9 P: [4 m, ~3 _+ x        else
    1 b& u) G# Y% Q( }; N        {7 Q% E1 v% y* ~$ `  u1 q
                arr[cnt++] = nums2[p2++];
    & r0 [$ I8 h5 }3 k9 x        }
    % @: [$ Y8 {( n% m# b3 }    }- {" }2 g1 ]; r( \! ~% B. _
        while(p1 < m)
    1 y% K" K/ D- _0 }; T1 q        arr[cnt++] = nums1[p1++];
    3 W  Y( Y: p8 V( X" [8 J
    " T; A. ^$ d/ T" `$ m8 B9 L' s    while(p2 < n)
    3 i# \2 `& S9 c, k& o7 D. G. m        arr[cnt++] = nums2[p2++];
    ) r0 U9 H- z! t: [3 K0 a3 T7 k. _) w! i( _
        return arr;
    1 Z. m* p& e5 y7 R1 ]}
    ! y7 ~; u+ G# z, W# v( R- u( C# g6 T6 v! o% V  D1 j+ b6 ^& y
    1
    7 x7 U# y' H  F/ P2
    - ~& F1 @! o5 M2 `1 \3
    8 E8 n, e# J, h/ z4
    - M$ R- h% u+ z: ^+ p5
    $ _+ U, ]4 e! ?) O8 p8 R3 u6! [" U# J' b4 F7 t
    7) x% r5 _+ I  o) c
    8
    4 D. w! N6 k% \2 \" A, k& ?9" I* z  m" r0 z' @7 [/ ]
    10
    . B% w9 p/ S0 e11
    5 W! z" Z* T1 p3 w: ]; C5 O9 u: m12& _0 e* o/ X; f5 E% H: V
    130 h2 F5 ^5 x  x, I
    14
    + J( j# {! y( Y/ y' N15* [8 {' `8 ?& N$ M) z- w3 s! a" B, l$ ]
    16
    # R( V1 t1 k; f% k7 j6 l17- Y; {4 o5 u$ v2 Y
    18
    , j3 O" x7 P5 T+ K+ @- n19
    ( U' O! k  V: w$ \+ @20
    1 I7 X- T2 s( G# @3 m21
    0 d7 \% p$ g1 q; h1 G* g; D22
    8 P/ g) `6 c5 k0 w23" D, F) u+ {0 h: d
    24
    ' U; f5 U2 O3 N. V7 v25
    ) O( T6 |/ k* a8 E, S& t% \+ l26
    0 }$ k/ K( q) @. @' Y27- g- p; w; t% g
    28# o' e3 i6 F/ R7 k
    29
    0 W* ?! \. v9 d# S30# J& _$ N, y8 p' N
    31. h3 Y9 B, x: M! Q; Q
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    4 r- i7 ^/ u: _6 L6 a( K0 {. _
    . Z& }) n( M0 |递归实现! K3 s* q3 U0 w1 J5 ^* o6 `
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。9 A% s) k/ R% i) y/ W

    . M, b4 t' |) L* c' R# U  j% U9 K

    " c  r5 R* k/ [8 r8 K' d+ M; a& D( j! [* b- n7 t8 [5 G) \
    7 O1 j9 Q8 T/ G4 ^- I( x+ \% K
    void _MergeSort(int* arr, int* tmp, int left, int right)
    0 G# M% y$ J4 a% W/ D) Q5 a0 A{
    9 A# J5 Q. D7 x% B    assert(arr);
    * f% p2 d" @/ S$ c; z
    4 Y! w+ l) v) @: r' C/ H7 O    if (left >= right)//递归结束条件不要漏了2 u8 Y4 U- S# p" h7 D
            return;0 Z3 G0 K, D2 C3 R$ y4 B# i& N% L
    . t% `) ]/ W- [
        int mid = (right - left) / 2 + left;
    ' }/ |! K- m7 }
    4 Q8 _- q: }0 j- m- Q    //划分左右子区间[left, mid]和[mid + 1, right]% v7 N6 G) t1 o2 Q
        _MergeSort(arr, tmp, left, mid);0 }+ L. \1 e/ J# v* d
        _MergeSort(arr, tmp, mid + 1, right);
    # p; R$ \3 H3 Y" T2 h6 |0 Z( `" v" \
        //归并7 q, O3 T; e2 A3 s5 S" C3 ]
        int begin1 = left, end1 = mid;
    ; k$ X# f+ E; N% G# O    int begin2 = mid + 1, end2 = right;
    * h) @' N( U+ M& e+ s    int i = left;
    - d/ Z, i9 E. F6 Y; U( g: l    while (begin1 <= end1 && begin2 <= end2)
    : L" Z, ?( r0 S2 [5 u    {0 O; }( g8 x& Q: h. w! v) Z
            if (arr[begin1] < arr[begin2])
    ; c+ L8 l. K: H. l& a" e! E( s            tmp[i++] = arr[begin1++];
    2 {6 I$ }; i; r7 ^        else
    % j4 Y* I; A0 v$ Z. i            tmp[i++] = arr[begin2++];: e, l& a0 `. B- [6 V7 }7 Y
        }9 {8 p" s2 {( q8 z

    - w; k4 B& P( w% `! [' h6 M, q    while (begin1 <= end1)
    ) K+ U, S0 \; ~3 P" R9 G        tmp[i++] = arr[begin1++];( l  V: P4 X, H- R) U& Z* B( g
        while (begin2 <= end2)
    " K$ n  G6 i+ ?/ t5 _        tmp[i++] = arr[begin2++];& K$ Y  `' T% b, r; c  F
           
    6 v9 H7 E) u" u& a* ^3 |3 ?    //拷贝回原数组——归并哪部分就拷贝哪部分回去) r# T! E6 O) e
        //而不是拷贝整个数组回去
    & E; i7 Q& L+ ]2 N  d% z    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));  m5 v# m) ]5 I0 s
    }$ _9 w" g$ D2 ^  L+ Z9 v
    $ _! _( {+ v. P1 a3 |# G
    void MergeSort(int* arr, int left, int right)3 F* b+ a5 X( w$ O$ V3 A( t
    {: Z$ s2 [" W6 d
        assert(arr);
    ' Z3 ~9 {6 l- ]% |  _1 d. _+ P
    & v% j2 m: d1 ~4 X( v    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    1 q4 _" l! Y* a    if (tmp == NULL)* F/ }( v" K6 P' M
        {
      `6 L+ O3 U& H9 ^: I8 s& O        perror("malloc fail");9 P7 K2 p; l  Z2 G+ n3 v* o
            return;
    - p! c5 a, B% ]/ [; t6 d3 L& ~  q    }+ U! B! F  Y/ T

    5 l- `/ C) M* V# b5 g* }    _MergeSort(arr, tmp, left, right);. H2 w% n3 O( [4 B! u

    - G6 p4 D( B# j% t    free(tmp);+ z2 r3 Y8 X3 P! F
        tmp = NULL;! @; s1 y) `% s. l$ X7 {* }. D/ l8 l
    }
    ' Q5 t+ @7 b3 P$ `3 k
    & V7 j. T; \3 T1 S4 B7 N, V1
    " x5 M( u) I7 E5 l6 \& c1 m0 _/ g$ ~2
    0 @8 A/ \2 G" i3 H1 I* V1 d3
    1 a+ u' s+ T% q* _; Y4
    " K- Y% h; r- i* D$ ]2 ?* v5
    0 T' L  y3 A7 C# B8 P- z6
    ( V3 X8 M  e  T7
    " l- W3 v$ y- e! E8
    0 A4 |4 H) H, R! \3 @0 t' _: x( w9
    % q% C; }, d* B4 n3 ~* t10
    ' z, r/ g5 h6 B4 x+ ]+ s11) @) s2 M# `0 h, a5 G$ L" T" p% @
    12
    / m( M2 r6 |/ R: r& y13: y& N. A5 E. {* _* W$ Q2 Q
    14
    1 n7 G" Q5 H  G  `) M- h15
    ' A0 X/ f: k7 {6 |16- ~: l6 i  u7 a
    17
    , h1 w6 p/ h# ?189 J' j, E$ b+ y1 {1 p: P
    19% x$ A5 V$ f. {' Y& e
    204 Q7 F  S" Q3 [. P
    217 A  [- j7 ^  c: R. X  F% \
    22$ r4 e; c, x- `& {6 N/ y
    234 _0 u9 g! Y$ X4 f" O; |3 W
    249 S( q# K' a- |% N7 D/ j
    258 e+ \  ?! B% D, C+ ~
    26
    - K' t2 v8 G# e# G! p. z27) I$ d: K2 ^" Y5 L2 N
    28: ~1 D+ _; Q4 `. q$ `; M+ {
    291 s  x' U/ @; X+ i' s' f+ S
    30, [4 p0 |- s. P+ e
    31
    & g0 V0 O7 V& _$ K! b320 [) o+ P: U7 q! S! M/ ^) n
    333 \. E& ~1 Z& c
    34
    + s1 ?6 _; y$ f- U! h5 E35
    ; {1 s- c% z- W! [5 R3 M36
    6 E/ n, B0 q. S1 b% i2 h379 @( k. W4 {2 Z8 g& |/ t  {
    38
    ) l) f, I* }( X* F  x0 {39% U* D( E6 L2 x" e* d; X: j  l
    40
    $ L4 x# V! G' L( I% n419 l9 c+ ^5 j+ ^1 U( p
    42# Y" m6 w& z5 L7 _
    431 B; E' q) u$ k3 g$ G0 Y& s8 `5 ?5 n/ E
    44
    1 r) J. N( f' ?# s2 p45( m0 w0 L' b4 |/ w/ A2 K
    46" z2 p$ S* n6 j) m$ C! B) G( D
    47
    6 G9 v( ]9 S# f; Z; W, |; |48
    & v" e0 r2 U" d. [493 l& A9 V7 X, @  |) _# x
    50
    ; g* Q6 u( u- Y! }! v4 r7 t* R51' R7 Q' W: B) v' p$ p5 I( q% ~! }2 _" n
    非递归实现$ [! x" _: o$ g6 q4 P5 e
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    / M8 K+ g* ]2 S7 \: e. n
    ) [( S5 o* d9 Y, \. y" ^7 I( s2 i- V9 J) v" l' E, F
    / I5 `9 ^5 A$ c& _9 a
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    " F9 Y- b: M5 B, M; B/ |; E' X7 M. Z! K
    5 {1 E5 y7 `) c$ f: r9 U% z​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。/ X2 D" \2 l' c0 b& c

    & F9 [& _, f% i! I​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。5 y5 R2 d+ C6 g4 d: y3 J# i

    ' ~$ N' }: F7 F9 A* H代码实现
    9 p. @9 @- L% X: k* {& U5 F
    ( C# u" p& f- j' X9 wvoid MergeSortNonR(int* arr, int sz)
    ! [' A" w+ d. Z& X{
    % J5 j% {, g3 r) [; `+ q    assert(arr);* d% l& p# X* h9 Q: j
    3 k+ O( i/ m2 f/ i; i
        int* tmp = (int*)malloc(sz * sizeof(int));
    0 p1 w* p: B) \2 `- B6 L- c, y& h% ~    if (tmp == NULL)
    3 s9 n8 u+ C" z( q: ?; K4 B$ W    {! O0 {% j7 ?  ^# l
            perror("malloc fail");) Z# R. f3 l) }0 D$ d, @: }
            return;
    9 q4 z5 g, U6 S5 j% J' P    }* ^) X- z: N/ ^- h
    7 L' Y  Q4 }7 ?" l
        int gap = 1;# Z/ N4 l: a2 z
        while (gap < sz)
    1 T7 m) d* S5 M0 i    {* l* W( b2 y. |7 u3 K+ d0 ]
            for (int i = 0; i < sz; i += 2 * gap)
    9 I% W, G* P" N4 D        {: A7 G  g: @' z( a, N7 I
                int begin1 = i, end1 = begin1 + gap - 1;
    # D2 e, ?% Z; J: z- y; p            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    4 X# N: V0 k1 ?5 C            int j = begin1;( E9 [- m1 L& J( g
    - V2 U; g. T" Q
                //归并
    6 W  `( J5 e6 N+ q            while (begin1 <= end1 && begin2 <= end2)0 {5 W/ G7 G! y; @# I$ }
                {) W5 y/ u/ X9 U2 X& g+ X) [! ~
                    if (arr[begin1] < arr[begin2]): Y3 h0 w5 k% }' ]
                        tmp[j++] = arr[begin1++];' r- N5 X$ _( e7 y/ A
                    else     $ \0 N! p0 {( ~& G0 _% r
                        tmp[j++] = arr[begin2++];
    9 g2 }2 C# C' K$ ~1 [- f* _            }3 S0 J8 ^  _7 u. y+ t

    $ O% m$ t3 r+ v5 D% S+ c% `            while (begin1 <= end1)
    ( v! K0 r5 Q3 E( N& r                tmp[j++] = arr[begin1++];! g+ F! ]% z1 ?, B8 M; j' J* I
                while (begin2 <= end2)! C3 A: `+ S+ r/ s. n6 v) k" Y: \
                    tmp[j++] = arr[begin2++];
    & p) j- G/ g' v+ b$ ~. z9 T
    ' V) T' R1 u1 r# I# Q: }. f+ c' [            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    3 I& z1 m9 D7 _            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));1 P$ G" p: ^/ H: I7 u) p% I
            }
    ' T; H5 _7 _& n+ B, ?$ B" y/ W        gap *= 2;! B% e9 O1 A! \- i
        }
    4 m: J; t! j2 a! ~% Z; y2 h( a1 _. V' M! a! j5 p
    }
    " v6 _! L. ]  \. P
    0 b; r8 f1 @/ k1 @1
    6 {3 z; z- @" z) d/ Y9 [: ~. I2
    . m/ a. N; M! M& o& C0 F* T3
    9 s7 e0 K, t( W' Z0 G4
    9 L: ?; H% f: l5
    2 [9 q% W% q( J$ J6! \) Y1 q# |/ o' z
    7! r/ Y3 }. o3 }$ ~7 F9 D
    8
    ' K9 p" c8 i. W4 Q+ |) o8 K6 w9
    ) v1 _( I* e* K( U10
    1 n6 u5 d& Z. a. e11
    # {2 k3 C+ t- t6 K12) b# t. D4 i6 p& N
    13; X3 s6 h+ G. f5 Q
    14+ F3 f! O' q& `
    15
    3 M( z0 n' G+ Z3 U9 L# d16! z9 U! g9 b  R& o1 A
    17
    * T+ `! r. z7 E18
    & O2 `# t9 I' r190 s) _' \! K3 y, c$ D4 _
    20
    & j7 [! v1 U- P3 P210 ?  ?& A: ]& K3 @! `
    22& S( i" V0 m4 c/ ~5 m7 J3 A
    23# \% _" x8 ?/ h
    24
    * G, }- O7 z; |25% D: n3 S  ]+ ~. L
    26/ Q3 g+ s+ C3 t
    271 _% k! |# @" w7 Q+ n5 _# T' \
    28
    ! A5 \, n* o5 I' D( k29
    1 V6 b$ X1 h. R( J& k303 g+ O* h% a  d
    31
    5 w( I- J0 C2 ^7 R, V& x8 c' ^32; w  y7 N, Z% c& O
    33
    ) F# d5 Y3 A2 C* M34
    % @1 i4 W7 V6 I: Q4 A: }3 V35
    2 H0 b- w) U3 v) H! U7 q  K36% H' G  t8 U: q0 W
    37! {8 i' `5 a' i. _
    380 I  |: X4 P  q; K& Z. D' V' O
    39
    4 j2 ?: ^, E4 V2 O1 C40, t. U8 }& I, W+ L3 {3 n7 ?
    41
    , _3 I! L$ R: \; J+ C, S2 }. i边界问题# {# q$ ^6 Z" j  r) w4 i
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。9 @6 ]+ T, j2 i6 U
    # J/ \7 b# m0 U! I7 s8 W3 c/ O
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:+ t: A) z% n' U4 l

    5 g9 y  C3 w' a: X
    ) H2 a' }/ O8 J* S# K. M
    % u8 W  {' }7 D( S4 N由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)5 d$ e8 T' m1 P6 v* T' h- G0 R' m3 ~
    9 D3 v) Q# Z8 {, B
    第一组越界(即end1越界)
    , O( T( |# F8 N4 C5 n1 a; ?' G$ A1 N# Y$ t) ~5 x9 N% D; J
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    . U) r7 E* Z1 k' j% U+ F
    & q  Q& ], _1 u* U6 P6 `第二组全部越界(即begin2和end2越界)' V. l& i3 T( D$ O+ ?# T6 I
    ( q6 Q4 }0 T* R& r) Q  X
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。: I- `' r! w; m: O0 T, R' J* v3 y  ^
    & u4 ?5 j5 [+ f7 y3 ?0 z. `' `
    第二组部分越界(即end2越界)  Q# P, p1 u# w9 z- [6 H

      z* N) H/ B, w; @7 l4 |2 Y' l应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。6 \' H: Q, t7 M' v' w1 X  Q
      G4 W  e& G% c
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:) d+ x) `9 A( Z2 A' i: |$ x1 f( h

    6 [/ ~8 Z9 G6 D0 f) z% c​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。+ x5 V* A( J( e$ T9 y+ q; g

    & D+ e  h5 Q9 r1 Q' V5 n5 o4 f  `​ 拿两个数组试一下:
    ! e1 z# m; V' }: K+ ~
    3 _6 H+ y2 R. n8 ^) v* W! _7 W, n) d9 k9 w

    " q0 \* W" R8 I& K2 ~
    , }& Z  ?+ m, g. ^% S/ j
    + L+ g; s2 K7 {% x, E' l代码实现: N4 r; J; Q* G) Y6 ?9 a
    & g$ C, Y( \6 \1 ]7 p  g# [3 n
    void MergeSortNonR(int* arr, int sz); A1 r) T9 p1 t8 k# ^
    {' D: ]7 k1 v  ~. x7 Z
        assert(arr);+ h# M2 H! b1 P. C
    " m5 Y0 I- o/ S4 i  u  J" W
        int* tmp = (int*)malloc(sz * sizeof(int));: f" V  K! n3 J6 ~5 p% a' e# U" k" g
        if (tmp == NULL)/ {1 F$ p7 b( y. G. {6 |( o
        {
    1 j  o7 e" n' D+ l+ e        perror("malloc fail");' ?8 h/ i* K- ]$ a, a9 r! `: {% n
            return;
    ! x7 n; y5 k3 }1 }/ l4 w    }
    ' A- y( ^- C9 t9 i7 ~  L" F8 r8 Q' ]  Y1 B' @! L' F
        int gap = 1;: c- I/ n- l) V6 n
        while (gap < sz)! P' E' l2 q" r9 ~3 ~
        {" Z* J1 o$ q- \0 b) w4 j, T
            for (int i = 0; i < sz; i += 2 * gap)6 w- ~! ]+ h7 a
            {; C# b$ o; G( T0 E( \% l0 `* ]
                int begin1 = i, end1 = begin1 + gap - 1;
    & t7 h  t+ _2 u# i; g% y- L9 N            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ' v. R0 i" D3 \  y' S5 w5 j            int j = begin1;
    ) C! N' E; S) }. a                        //越界检测# F' F/ Y+ J9 d& b) E* K) t' G- P
                if (begin2 >= sz && end2 >= sz)
    3 S  ]$ f. I" ]/ |                break;6 y) b) b! R( W2 x/ _4 }- x+ f
                if (end2 >= sz)$ E7 g0 b) p& o1 s% C# Z5 W, x
                    end2 = sz - 1;
    ' G: O. k6 j* _            //归并
    ; }  ~. S5 q' ^- Q$ P3 \& P( `            while (begin1 <= end1 && begin2 <= end2)
    7 L4 A. W% M; F0 }& P            {, p* c; o# L2 M- i* t! Z
                    if (arr[begin1] < arr[begin2])! N0 a+ @5 @$ P: Q
                        tmp[j++] = arr[begin1++];
    5 v. H* R  u" u- E# V7 g                else     
    $ d0 f, p6 o4 M' H( R" u4 W7 L                    tmp[j++] = arr[begin2++];+ m/ E3 R6 Q( ^/ t, P
                }
    7 @  M3 q  R% Q: T" w
    4 g$ G# X; x/ w            while (begin1 <= end1)0 a* x& t! |- }8 N# \3 c
                    tmp[j++] = arr[begin1++];
    # o. O2 G( U# ^4 l            while (begin2 <= end2)
    ) b5 ?" |( Q+ b3 a! i8 e+ `                tmp[j++] = arr[begin2++];
    1 [- o# C9 ]7 n& ~8 L( @
    6 g* D* S1 D) I& P, q# ^            //拷贝回原数组——归并哪部分就拷贝哪部分回去. U/ Y3 T2 E7 e- E' G# R
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    4 q, p" h& L- s! u( x4 P! f* S        }
    . c" s* G4 Y2 r! Q/ y8 o# E: r        gap *= 2;
    ) z% d# O/ f( v% ^! ~" |& q5 x  M: E0 y    }0 @6 x7 H% o+ {9 m1 K5 L2 g" F9 M
    9 a" q0 @8 R6 X" \& w
    }
    1 h. ?! R& @  y4 i' m( j# \
    ) M% G, N# c2 z. @/ Y1
    ; t6 {0 d& U' }" N7 W24 w2 R/ X; f0 A3 G4 g$ n2 I* e
    3
    ( _; ?! {; x4 m- T3 q2 z$ V4 s" S4
    3 p+ r: A' g. ^5 C, w4 C0 d3 o5
    * Y; X- S  k, d1 {. s6
    $ J- C; f5 c; D7
    7 v+ k; e0 v/ N: S& {8
    1 K5 n: X2 p; o( |, x9
    - G6 G. E' ^. z2 t$ M10: P* T& h' f" K' b' Z5 u$ P: o
    114 D$ _8 X" o/ y& r
    12. {5 w2 H6 @% w" {
    130 S6 |' _/ K1 y& B
    14
    8 L. W& U  ^1 {# E159 ?& J: F8 }1 \) v0 I2 ~
    16
    8 c9 R8 P/ t9 B6 w! x% i0 D. m7 G17) t0 L) E, Z- a+ ~) N: A( E: v% e) r
    18
    7 z5 s2 j2 Z7 X6 l19% l" d! F; _7 K: T  V
    20
    0 c+ _/ a" t+ j) }21' O- X; X# w3 I- t  y3 \8 t* J
    228 F. t9 B* Q/ x6 u: C9 g
    23
    . z6 Q! Z) f  A" m240 I4 s8 ^. f/ U
    25* L: S; n3 r9 m8 l' f
    26
    , _. h  T6 _+ `$ Q# h1 d4 L27! P9 q: [3 l  [' k
    288 s8 h  V9 D) {: {8 T4 q, K5 W, i+ H7 z
    29
    & g# {8 }) \) v3 s30
    ( r; b. v* e- v. W2 [0 T31
    $ D! S9 T/ R# R6 G% C& z5 L32
    - b" K! N6 e  i! _/ i/ ]$ d33
    " F" U4 W0 f+ Z! S34
    2 ]$ s, R! X4 ?1 k35/ U, \$ w$ ^, a% H' c
    36
    # R+ ]9 p$ f. H. y8 C$ x37- v' t* `# P; v
    38* ]) r* Y0 [, C; e. U: [& D9 t
    39: [( V3 A$ v* Y9 Q- Q0 t
    40
    4 H' Y6 K  l2 ?% E4 ]0 @( Y41! y7 P, }) A3 E* ]; a) Q
    42
    $ T7 h8 ^7 h7 R' t' y$ `* Y! w2 l2 K43
    7 {3 _; g) j- I& z44
    ' ]6 [  S# e; T4 O' ^45
    / ?# R- O; W1 z归并排序的特性总结:
    2 ~8 S. g. O+ B7 U( v7 y
    # ~! j. T0 [- n) ?2 t% H7 m& w; U7 y3 _! Q归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    $ K  b( S2 A9 o# H# F+ G! U2 m" F时间复杂度:O(N*logN)
    2 p# s# _% F, ]8 K空间复杂度:O(N)5 ~' b  }0 H  ^! }
    稳定性:稳定
    8 n5 X6 r, g7 X# `7 A1 v$ J8 h; c; {$ Y
    ————————————————
    0 ^- M- w+ N5 E) B- J1 m  d  K版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。. {- Z6 _( c# s) E1 d+ q) D% A# ?, U
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    . d. D$ I, l1 H: w( i0 V8 |: j% G6 E+ h$ k) m9 ^9 g

    & a& K( p8 _* u% Q8 ?2 g
    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-5-25 09:22 , Processed in 0.336087 second(s), 51 queries .

    回顶部