QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3337|回复: 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的排序算法】归并排序" K; H8 {5 O) O% u- V" ^  f; U: F, m

    ' ~" f- _' C; J前言
    9 j, S/ F- K( _7 ^& L+ g! W  k本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。" O  H3 n) m: x6 Z; d0 U
    ( c2 ~1 s- i  N" j
    归并排序6 k' E. d8 j+ ^
    基本思想/ L' N2 p  e& F
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。$ k9 k/ n0 m# Q2 y1 n8 i, f: ~
    8 R) G6 u4 A6 f9 C2 s- p
    ' x: {; h! R9 A" p
    , N( T* k1 Q5 ]  d
    ​ 合并的思想其实和有道题目的思想如出一辙:9 ~( n1 U- c6 w0 T' s$ `" `. r

    , A" c8 Q* z/ @7 K  D0 @6 q+ s2 w4 z/ H' S& r- H: A: c  \

    0 c' ^, N3 t# \1 g​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    / J0 _( \6 V9 p5 s& A* {
    / X+ G# n9 O6 s% ?& X7 o# f[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    * {* C; c+ A, X! J
    : _# c* d! U; Y& q, fint* merge(int* nums1, int m, int* nums2, int n)
    0 ^0 a+ j( E- i4 P' v2 k9 E! C  v0 ?( _" \- \{
    % g( y. G' m4 t$ c9 ^        int* arr = (int*)malloc((m + n));
    : x0 Z) F% `7 q8 q0 v# r    if(arr == NULL)/ Q2 P/ I2 I: H8 y
        {
    " J9 s6 a" h2 D1 ?" m; H        perror("malloc fail");& U, F  E" o9 `: n8 k/ {# j
            return;, W9 i, }2 b8 b8 x4 G/ Z7 u
        }
    7 V$ q. E# ^# M+ p+ U* ]! E+ L0 x9 p% j8 t+ ?/ P) r# e) W$ O; T0 H
        int p1 = 0;
    6 I4 z$ O6 g0 \. l/ j+ Q( t    int p2 = 0;* b' |/ |4 {+ b/ W, `, v. E
        int cnt = 0;
    ) t, |" z8 r2 o' R% n+ |    while(p1 < m && p2 < n)
    3 Q; [2 ~; I- `+ w$ R    {
    ' k: I: Z$ l; ^" G        if(nums1[p1] < nums2[p2])" \7 [: Y+ s) L9 g  A
            {. Z: D* H& l) M0 m
                arr[cnt++] = nums1[p1++];3 B4 T: l+ r0 g3 A
            }; B2 D- A: j) \3 u7 s1 _. x
            else8 P' P! G+ a' {0 p# W
            {
    ) d6 U, [4 `3 N1 @; B+ O3 }. s' V            arr[cnt++] = nums2[p2++];$ q; A8 r1 y, R% A2 a
            }. {4 @8 G% d) ~; b; v$ W4 `
        }
    ' [: c+ l, r! i4 R4 ^    while(p1 < m)
    - g# A/ \+ Q1 ^7 X5 I        arr[cnt++] = nums1[p1++];  t* t1 L0 ]3 I, w1 }9 `! q

    : N  g; t1 [2 B' e    while(p2 < n)) [9 C8 u/ f# F% K5 u& V
            arr[cnt++] = nums2[p2++];. R+ K. K4 u8 [9 i0 q# S

    $ S! G/ c! T2 M( h' Y    return arr;4 J: a& t2 X. C2 j7 P0 K0 j3 @
    }
    4 ?9 T& u. \' r  b3 v
    ) ]8 p9 o# d0 ~  R# D1
    ! d, D$ H* w& E) e* j2! I0 I4 L- ~! Z: p
    3
    7 a' _: ^8 f) l1 k. p- ~! d4 Z+ L4( f, |% m& m& J0 h
    55 @" b/ F4 G0 Y; `
    69 m: M4 _2 U' a1 R
    7
    $ ?6 U- Q5 U3 G7 o) S8: ?; h9 g8 A' Q
    9* j3 Q* ]8 ~4 d( u6 p
    10
    9 f- w' g4 K7 Q, N$ N11
    # i* f8 @( U4 |! T0 \7 f# ?12
    # @3 ?' @4 S) r9 I* g132 A! N5 V* j- @& W8 `1 q
    14
      D  M: _$ \* t6 I; ^15, |$ X$ G; ^) z. U1 l) }8 }
    16! c% B, y- ~* e/ Q! \* U
    172 q; L* }$ r: P6 T
    18
    7 w2 G/ r2 D" _3 T/ K7 |* C0 c8 H19  S. W1 l& |$ ^7 n
    204 M4 i" q+ v) i
    21
    7 \4 p8 `, ~# o# s, D1 y22( t- v" A* D9 g+ Y' v
    23" y$ A$ D+ T; f' A4 ^8 \
    24
    . R2 c7 T* ~% u+ o8 H8 v0 H7 p251 o6 d$ z: Q, `; r7 g
    26
    + R' E" @- P* s( o- E! t27" G  p6 S( }: O6 U4 P# L; \  C
    28
    * G( B6 ?' c( Z9 Q/ n. d, }1 Y1 ]* d29( p. }, s$ }! A# i* L! [
    30
      p( u2 Y* G2 @2 @6 M" c$ `  k, O31, Q/ G' }/ m/ s$ J# x2 V- W5 f
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。& W6 K6 x% `4 p1 b

    5 y  I/ g, d7 ]# n$ L& ]% C* T递归实现
    8 N. H, s) h- I* L​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。: |  i  ^/ m* _$ H+ e9 t
    * [4 {& X  q7 ?" n: v2 ]( M  T, }

    ( b! m' Q+ o( x
    * L4 p8 C! _# E' x" \0 E' N0 B+ N/ F; Z, ]" n  G9 w) G
    # {5 z6 E: A" m* T( w3 _
    void _MergeSort(int* arr, int* tmp, int left, int right)
    & d9 w* y5 H: y$ Q8 U& [{! T2 {: Q8 _5 c3 |6 y/ Q
        assert(arr);6 A0 }2 y' L7 d/ F1 w

    " }/ O" E, Z) e2 e) z& K/ |5 X, `" t    if (left >= right)//递归结束条件不要漏了
    2 ]& r0 T; d5 u        return;8 Y- g# i7 `5 k' x# G
    : f3 I! s1 i+ G  z4 y$ w
        int mid = (right - left) / 2 + left;7 O7 _) a- U& F1 ~& A
    . B3 E% z7 e6 i; G
        //划分左右子区间[left, mid]和[mid + 1, right]4 u5 x* r) L+ S7 G) I( @
        _MergeSort(arr, tmp, left, mid);* d9 @1 S8 U' T* e9 G
        _MergeSort(arr, tmp, mid + 1, right);4 Q- F, s+ w9 _

    * ^0 G" E" |; S/ X    //归并
    2 K+ S. g& S8 H: T, ^. c& ]    int begin1 = left, end1 = mid;: ?; S" r1 L% x7 e% E
        int begin2 = mid + 1, end2 = right;
    & t- u' C# Z5 Y$ a    int i = left;# D: F2 w: @) q0 P/ ]. m  j9 f- \0 r
        while (begin1 <= end1 && begin2 <= end2)3 Q, i2 Z- f$ U& d& ]; G
        {' O0 m. l+ w0 |& D
            if (arr[begin1] < arr[begin2])! j4 g  Q- F* F% f$ F* o9 ~
                tmp[i++] = arr[begin1++];9 G0 w  u! E3 C9 K, O0 u
            else
    & v6 O, }: _9 k6 \. w; v: `+ R+ _! h2 d8 u            tmp[i++] = arr[begin2++];. y% V3 H3 Q& k  H$ E# d
        }2 D+ `# ?: f' k  r

    8 @( l3 q/ I6 [! T# D$ s    while (begin1 <= end1)7 b7 h* H* h3 c0 J0 K# K) |
            tmp[i++] = arr[begin1++];1 D9 `2 ^$ r4 \# _2 t
        while (begin2 <= end2)
    " Y5 w1 S$ D8 |7 z! ^        tmp[i++] = arr[begin2++];
    1 o: _1 n5 T; `4 c: p( C        . t: d* k9 G) @+ u9 Q
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    / b5 ]  c+ a. ?& X! `# U2 v: l    //而不是拷贝整个数组回去& O) E$ \3 m3 {9 g( A: e2 U
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    * J3 y. |/ k( D8 D# ~9 T- Y6 c}$ C+ Z% S6 z% e6 `, ^; ]

    8 t# Y/ |0 H2 u" h4 Uvoid MergeSort(int* arr, int left, int right)
    $ h( i- s* d5 I; T: |) d  `{
    ! [" ?) Y: @& {2 Z) ~    assert(arr);
    % G3 v0 I9 t( z$ A% i+ V* ^/ T; Z6 T9 e; d! |/ E
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    " s5 Z5 w% }+ h  X3 G. F* l& v    if (tmp == NULL)3 Q9 P8 C/ T3 l/ ]% ]
        {
    7 N. z% z6 v) g( T0 j8 A' d6 X' I        perror("malloc fail");
    7 o, c3 m7 Z' \2 {        return;9 O9 P1 G" i  `0 I4 `+ D7 ]  P" }7 A
        }
    ) R: ]5 E' _6 H  H# y& R+ g7 v( y- h! ?
        _MergeSort(arr, tmp, left, right);
    - R9 ~0 Z, [) U7 E
      w  P  E- |) x- d1 D! E    free(tmp);
    , i4 P5 v  e& v0 V6 h8 h    tmp = NULL;4 T  K9 \' e% h  v: f
    }8 _  L8 G$ J6 C' i

    ' f; Z' X' j% E& O& x1
    , l% g4 Z% R+ }/ b2
    " f" a. A# q+ D. S- W3
    + c0 k! `+ n! P4 A1 K+ g40 }9 W1 |' e8 `9 r& e6 B/ ~4 m. X! L
    5
    & k, c4 d% i6 R8 M, T; a4 _# J6
    # J+ J$ e/ Y( x5 v! ?. Q7+ }6 x6 F/ f( a. P
    8: ~- M* C  G# \( b7 f
    9
    8 f0 }9 `0 L5 D100 B" i' j) Q( X9 Y/ @  L  l
    11
    ) m; v6 S- P6 O- I3 f! j$ ]8 v12% x: L1 B2 B$ e
    13
    5 g. X$ r9 F* {& v9 I3 G14
    ) j1 g6 Q# U* K5 {/ j15
    * Y5 |" a+ {" t% [7 ~! j16
    $ o' J1 ~: ~: j17  M! y- H: Y( C, l* c! T$ O
    18
      t* C  n# v* P$ D+ l19
    ( @. l% }- B& o4 b) q3 W" D, m20: P7 R4 x+ R; b$ @
    21
    . z( L/ K$ [4 h# [22, y7 f% a* D$ g8 `& Z1 K. s! S
    23, z/ `) C+ l# A  U
    24
    " I2 h$ }4 n/ L9 D/ k; s; e; H$ V25& p9 {$ `, z' l) |' z9 z4 O4 K, D
    26
      [  S0 }7 I$ K; r27
    0 Z' s( j( T* _1 G5 d28
    6 o# y  }0 c* N& F# u' p" E8 p295 L7 W! e: m4 `) n+ h3 f
    30
    0 Y- Y$ y2 m7 P0 J& H0 Q2 g31) R' {! q, }) y0 g# w
    32
    * S- j% W* p3 Z5 L3 L& N33
    ' Q9 u$ l1 d1 F3 a) g34
    + \8 J7 B, \) p353 h* ]# G! d$ D+ q3 m) I( W- F
    36
    2 q% d9 F" O3 V% e7 S/ i* C37& W9 F/ x0 a9 {2 Y. y5 Q
    381 A  x0 p1 S0 z9 k9 [
    39
    + d& m: ~) k6 E( b2 X3 L40" ^  i; e! v0 @5 o9 O% R
    419 Y6 ?' Z) V! S
    42
    - ]4 ]' f7 l: c432 J2 ?# C) o  d: x9 N( s
    44) U9 m! r" d1 q* {' F
    45
    ( h7 T7 D) K: f9 ?' G, _* |46; `( @& u  V( V, T7 u
    477 G; G/ [& t' {5 M1 l3 S/ Q
    48! w- I6 [2 [8 B9 i
    49
    ! c0 m4 n9 q& Y) N50! e& j6 L' s& G1 E- h. x
    51
    6 k/ \2 p  `% E1 k: a& m$ A- t; N, I非递归实现: E# d" @0 C, T
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。& b& E. _% Q( J& q+ W

    ) w- g* \7 s  B
    4 t) G) a2 B1 [; t' A) ^+ e- y. I, {, Z* @$ I
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    + `* [! `: V" e# ]( b' R4 V- a. N# a& l9 m$ q9 ?6 A2 U  d
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    ) l2 S, q9 T) z7 U" u. P, g7 W' w1 M2 c9 u0 f2 x. N6 G# ?7 b
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    + M( i5 L5 y; W" G
    + e. X; y- u7 }6 m9 q- r/ X代码实现* K1 ~, I; c/ V& Q& c& ^
    4 ?) n0 p# K3 W+ |) r
    void MergeSortNonR(int* arr, int sz)) _' d# W- k4 D2 L8 h$ L, G0 _
    {
    4 Z1 a( h& {4 k. L( p6 V& I    assert(arr);
    % v+ m' f  J+ E3 S# q$ |( ]8 n! @
        int* tmp = (int*)malloc(sz * sizeof(int));
    ( E# l, L4 i: @! ^$ @6 d5 T  P5 U- g. E    if (tmp == NULL)3 N' P& }1 B. h4 ^% L" S- E* u
        {
    0 B! o% I( P$ K1 k! |) o2 q        perror("malloc fail");0 s2 ]1 T9 ]1 c: V0 v
            return;
      I) g* f/ z9 T! T/ b    }2 \3 F8 }# }7 R8 z( d: U* e8 Z' N5 D! ]

    $ I' C! I! H& h5 _- N    int gap = 1;( h: R4 r, I* V  L' g
        while (gap < sz)
    1 X$ J+ W0 e, b1 D0 k: [! J3 }) _    {2 G5 x8 m. X: |, t
            for (int i = 0; i < sz; i += 2 * gap)" m! d, Y% Z7 ?1 X
            {
    1 K# w/ G' B3 k& ]6 d  }            int begin1 = i, end1 = begin1 + gap - 1;5 Y- J- w/ j1 @0 E& |9 Q& H0 A
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;# N% v3 C5 @4 _4 E
                int j = begin1;8 k3 W/ `% q3 ]- V

    4 T& i9 V- |0 ?! [            //归并! s9 B, x2 m/ _. q0 K! m
                while (begin1 <= end1 && begin2 <= end2)
    $ c6 S" _; n1 ~$ d4 U            {
    ! B' R( T- C3 g6 `* Y6 Z                if (arr[begin1] < arr[begin2])  ^( S4 I& i8 y% I+ o5 i
                        tmp[j++] = arr[begin1++];
    / ~' a9 w+ a" f# T9 n                else     
    - Y8 ]( R  }0 B; G3 e                    tmp[j++] = arr[begin2++];+ w* l" L* ?% Z
                }
    9 s: [4 M$ q- L5 D3 Z% v- F0 W. m6 H7 i, V1 i+ e" Q/ q. R
                while (begin1 <= end1)7 H" j1 J* y: S0 W, Y
                    tmp[j++] = arr[begin1++];/ a3 B( h* b3 P: i2 P# @5 {
                while (begin2 <= end2)
    0 T  S" ]8 X* H                tmp[j++] = arr[begin2++];
    1 p+ c, [4 M3 L$ V. m- `* y
    # R) T6 Q# [5 I% g            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    , x; a4 V; L# D0 T3 D# r2 G            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));  G2 i. m4 ]: ^& e) Y/ v% `, t4 |
            }2 d+ `+ T! |1 }* t, B
            gap *= 2;& Z; H1 B( o+ o( E
        }
    ' ~! j( V4 k5 |) ?& Z1 e& `4 O7 F- R' L5 ~: u
    }. `% D! f9 ?1 o* s# p9 J- K% @; Q
    ' i' H$ i' O" g% _3 G
    1' y5 [1 |% O) j# w
    2) H- r! a" X/ n0 x
    3( p; `. x# c! U9 H5 u' @
    4
    9 y% q, w& N" Y& L8 ]5
    ) z- G$ N8 y# M" ]6# P9 ?0 S0 ^, S8 {1 U& j
    7
    # O, x' Q1 U$ A/ P  D% ?8
    6 i7 T# R- _2 C5 U3 [+ h- z8 C9$ ~( d7 N! C$ Q1 g+ y
    10
    * }$ }3 j( }: d+ k# U/ M11
    3 I, u) b+ j, f* N* {! |( N0 D12
    7 ~% L1 g  x3 v' I/ u. ~136 M% |! h, v' D0 p" Q" V
    14$ o# i* z' a9 W1 k
    15
    ; p1 @4 p2 y1 F& W2 E4 P: ^160 \& j4 o. l. V' B+ g6 B5 q
    170 }5 P9 A- |# s% h( v: d
    18- F/ p, s- n- {' Z/ p& V
    192 z, u" g& z6 P  x0 j
    20( l$ Y' o9 x0 ], {! c( W1 X% g
    21
    : Z; r% y" j' n$ X( Y# r5 u22/ ]3 H. c' r1 Z/ @( D* o6 U4 G
    233 Z+ g5 b: c4 r) d3 x
    24( [8 L4 W8 i% }7 ^
    25
    * e* W$ c: [( |9 [  _26
    + ?& f- R* n$ p4 m" K: a2 y) X2 i3 ?276 y- ?/ X0 X" {' G3 q
    28
    8 M, @5 E- [7 y  y29
    + w. W% ~$ M% h+ Q6 U2 L1 R* }' \30
    ( y( Z) {5 H+ Q, Y31
    ; C* r5 S7 ^7 D/ u32
    % {/ x3 C9 t% m* o3 a- |33: f- d! @, D! F1 |8 O$ ]7 y
    34( C3 y" p2 J$ F2 ]
    35
    + o3 q; \. ~$ @6 N" O/ W36
    " d6 Z1 J# B4 N; l( N2 a2 n37) _2 N. g& n5 V+ J9 H3 {% M
    38* z! b* j, z  I# ~! x% ?* O
    39
    5 w5 U0 ~6 B9 \408 W% |3 [- U& j( l
    41
    4 C; y5 v( R+ ~! {5 b边界问题# H$ d# w" w7 x9 J! F) w7 G
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    " |% U. ^) n8 ~
    0 q) q5 D' c6 t8 K) z2 a0 [举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:% j+ K- ~) Z8 }2 J/ u

    0 J& o& W' Y9 |# k- A
    7 J. s$ `; }9 |( Z# n
    5 T1 D2 f9 G! n# z- F2 o' m由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)3 j" \! k* y' n# a( L2 T
      C) |3 S4 {5 k5 v" c4 ~- H
    第一组越界(即end1越界)
    8 P% J$ n1 @; K
    8 `, U( M9 A4 ?( ]  I/ U应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    & S5 M+ H3 ^* V8 f7 s# Z! n
    8 \2 @7 h+ q; M. o+ [第二组全部越界(即begin2和end2越界)) D+ P  h& k" Y" S) u
      R: `# u4 s# Z: D3 e  q& p! o
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    + t9 W" U: o  S
    ) V# a* o4 V$ I, E& }* r" s第二组部分越界(即end2越界)
    9 |2 O0 P# s* ~2 T' p+ z0 |! X: |( Y4 q* `' X2 P6 ^0 s+ P
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。& C( k% C# ^% G. }6 ?/ @& {
    3 T- ]1 d* z+ \; E$ G9 I
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:; s  ]9 i0 V3 w% A9 r

    - d. J. X; U0 r+ c+ M% \4 e  C​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    4 u+ r6 ?# B* |( z
    $ s5 I8 n3 o7 w0 H. f; {/ |  B​ 拿两个数组试一下:
    8 g: d$ S: I; w2 L7 _( |/ B" l: }# {1 G" B$ K
    0 F- @% n1 O" e

    - n6 V8 Y+ u$ u
    - R6 B$ a+ _$ D; [( V0 [2 e( u% y2 b6 F% L1 _4 y$ k8 }; U
    代码实现4 I! S5 \5 T/ ~
    1 \/ s1 Q! h* f8 i# V8 K
    void MergeSortNonR(int* arr, int sz)* L: q( Q8 E1 e$ ~3 S. n
    {9 z# K. I" U5 M2 ^& u
        assert(arr);4 J$ u2 J! d, w4 q; I

    ; T/ X' F; l9 g8 C$ J3 Q7 k2 m    int* tmp = (int*)malloc(sz * sizeof(int));
    6 C2 e7 }* g/ |9 h+ f    if (tmp == NULL)9 R$ G: v7 _) {; F" O4 q
        {- V+ \: k8 H  ~7 {$ _
            perror("malloc fail");
    9 ]7 }( d7 j& W( _+ y        return;  t, F: H0 }6 ]5 R
        }
    1 u. |) O9 ?( u! g" G- I8 {' X& r; ~1 R; Q9 Z2 W2 w# N
        int gap = 1;. _; V. d* q1 T  R5 E$ C
        while (gap < sz)
    # x* M3 s# q* ?; c7 F# W9 L! v    {
    / u) P; ?' S6 C% k! V, q        for (int i = 0; i < sz; i += 2 * gap)
    ( R- h" K/ D$ L- o        {0 x& Q' C, W; d  j6 ?
                int begin1 = i, end1 = begin1 + gap - 1;" {! N/ Z6 K- g9 v! P
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    8 ^# `$ J6 H  D3 ~8 S- K% G2 \+ C$ T            int j = begin1;! B% a" g) O* D2 b
                            //越界检测
    9 S+ i9 S% Z: j. G3 f2 w& u7 J            if (begin2 >= sz && end2 >= sz)) {8 |% V  x" t) \
                    break;3 h' _8 e6 V2 d  q
                if (end2 >= sz): i, Y! n/ {4 X% E& r) S% [
                    end2 = sz - 1;& I8 p, k- {7 C0 k5 t7 p4 z
                //归并0 G9 u! G3 h# R  _
                while (begin1 <= end1 && begin2 <= end2)
    ! o1 H3 v; S& {3 e            {
    7 `  X# O/ A* X# [1 @: x                if (arr[begin1] < arr[begin2])
    + v4 A2 B1 m1 V) S' y! w                    tmp[j++] = arr[begin1++];
    ! L9 I1 j! V6 ]; I- K                else     * e, V% }) \  Y3 D. i) i% e4 U$ x
                        tmp[j++] = arr[begin2++];
    1 y2 ]8 R8 n, G5 h6 ^+ e% V2 a7 R1 \            }
    4 a+ Q  y% N, x4 q. O6 \* T
    ! ?% O, D/ b7 x1 k3 C. ^& c            while (begin1 <= end1)
    * u) g; t! m" }8 q* S                tmp[j++] = arr[begin1++];& N; K, b- G, F$ a7 N6 E( q( X( f
                while (begin2 <= end2)
    * R; S  G2 X# c8 W. G+ @                tmp[j++] = arr[begin2++];+ @% l6 x2 H; u) P; c# _0 Y" E. H! |( q
    $ a9 i8 ]  y' n0 o9 K- K
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ( [+ u5 {1 c1 _) E            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));" t! t3 {  X0 I& F
            }
    * H0 w! T" }# M& s5 `. C        gap *= 2;" y! S0 F% R% s, |2 g
        }
    . v  ]  T3 ]7 U: W$ {+ I5 M. ~9 r6 Y( S- T
    }4 W  H; M' P4 W

    ! Q0 m1 H9 o4 x1' M/ k% M( Y; R% }+ v
    2
    & ]0 b8 i/ I5 T32 r+ C9 w( t! R9 }6 D2 l, v
    4
    % I5 q7 D2 ]4 F: d: m* o6 A5
    * J* Z2 j4 i  O( f! K" v6 H6
    0 R$ _! i  L  b1 Y1 ?( |7) c# I1 a2 E% V' X
    8" N8 V: O* r5 w7 Q: f
    9
    1 V  V0 B6 Z9 ]* H$ l- w% A10
    + m: f, T8 ~) K3 d( X0 C. n: s( H110 _& i4 y) o! U( N% s: _3 G4 Y7 E8 K* P
    12
    3 o8 X; X7 ?3 D0 \7 J13
    6 S/ d% L1 M! a- F# E147 ~: }( H+ S0 A
    15' h9 [" ?2 d3 [# D8 A! O. k& `
    16( I- ?' `+ _. t% n& s
    177 r( r/ v9 w  ?0 E
    18& }, u  m6 Y+ T# q3 `1 u8 b
    19
    . K" t  Y% I' Q0 G  Z3 [7 w20
    ) h' K. h$ \% D' W21
    8 A  ~7 ~; d  U22
    4 C8 J4 p7 q$ r+ g8 b233 L' S0 ^& g. l
    24
    # r$ q- p) t2 W' W3 l' n25! n& K' _: h8 @2 P& F: o& t4 Y
    26
    ! R  [- a8 r2 U! _. a7 W9 [3 R27
    ) J5 `' J+ ^) u28
    ( e9 K  j+ u& q. i- p0 S29
    1 d% o+ \0 n' p- ]6 A5 A30
    7 D" {2 [' Z+ M318 k! p1 Y3 _; h$ ?( _
    32
    - R# e8 y3 R9 r9 W& u33
    / K1 H, @6 T; i7 Q% k# d8 I34, F9 M+ p7 p9 i+ @* H$ D
    35
    9 ~  A/ ~. ^  @4 L0 {5 j* Z36  n* X/ s) \& k2 i9 I2 c
    37' j# }' Q( _' }5 J) B
    38. n1 X1 h4 ^3 N. K
    39" A1 q& v% @+ v0 R1 ^/ G6 Z
    40
    , V0 p! I) x5 f1 k" H41
    ! x( ^/ g* V: f. H$ O429 y* e  q3 C. c# h& i! t) p* z7 U
    43% u  y' l+ S2 }
    447 X/ T2 N2 C6 W7 g: a
    45
    4 `8 X% \! P# K" g! o# Y/ \' l归并排序的特性总结:  S0 h/ h+ L3 p5 Y0 }. u
    , s7 [. E* b/ @
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    9 q9 s$ Y+ E5 V: D时间复杂度:O(N*logN)
    * C! s7 W5 M3 h: x1 @& @3 ~( f空间复杂度:O(N), y1 e: q- k+ i, p4 S2 S0 B
    稳定性:稳定
    : X7 |! P) l' K. I; m; W$ ?4 M; \/ L% _
    ————————————————
    / y# J( u# H# S6 c$ `9 e版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。. f0 C5 B; ?; ~
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657- \  r6 x( @5 w4 I
      m3 R" _$ B- B  K1 a( ]6 U
    " o' ~- }; f4 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-8-24 04:04 , Processed in 0.622912 second(s), 51 queries .

    回顶部