QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3391|回复: 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的排序算法】归并排序9 S+ g1 n; g1 _  a* W& N3 p; q

      H6 c; G8 k$ M7 c" j' Z- k6 A前言
    6 K; A6 t/ C- d本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。3 L' J& g3 K/ I+ Z7 w" Q" f% w

    $ p$ i& B1 H! p" O  w5 v7 ^9 ~归并排序
    $ N* E2 [; F" J. q7 q; X, c基本思想4 r! d* _5 b8 Q1 y% c; v
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。9 q, `4 S% X2 M; G
    4 B/ V( M# N. P$ Z: O+ L4 j8 i
    : \; b& K2 ^' @, D

    6 C4 l8 J. F* e& j0 H( P​ 合并的思想其实和有道题目的思想如出一辙:
    5 ]& e" |) R3 z( k) J( s" z' [
    1 n4 x9 y( q4 K% n
    & v: E4 v) a+ o9 g( R( P4 r6 G! s7 N5 _* t8 @+ I' b
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。7 U. \4 c' X$ j# @- W
    . s$ W' @& O3 l: f' g" i" K; L* B
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]0 P9 s8 h7 e0 t

    ( s. X8 V" m7 q& s+ h9 vint* merge(int* nums1, int m, int* nums2, int n)
    ( n& I3 c; K0 n- i1 @{5 J; t- L0 v& n! ~
            int* arr = (int*)malloc((m + n));
    9 m6 k/ b. r* |: b1 ^    if(arr == NULL)7 |" R2 D3 F8 p; L- c+ M5 D
        {$ W* ?) |. L9 z! L
            perror("malloc fail");1 [1 f& R8 P; L! t- X8 M
            return;
    9 K2 b1 h) A) \* C8 }    }2 C" j0 n+ H9 C6 g  \6 X  p

    7 u, n$ r$ ~5 _2 o4 N    int p1 = 0;! W! V$ ]1 z- r' B
        int p2 = 0;
    , u- P" J5 p% w. R, z: ^# s    int cnt = 0;
    ( h0 A0 z4 ^! y# Z; Q4 D& i    while(p1 < m && p2 < n)
    3 M0 s, b" G3 M2 C8 }6 G4 l    {& [, @+ q, ^/ E+ K/ g
            if(nums1[p1] < nums2[p2])) p1 @7 f! T2 @8 H& B
            {
    $ T8 y0 g3 a% r6 D( K+ w) y% z            arr[cnt++] = nums1[p1++];
    ' E2 n1 g) @2 L$ V5 ^+ x  |. Q        }' X  ~3 F+ e# ^( ]: V" Q9 y6 z
            else7 j' b3 u0 Z. x
            {
    2 z6 K9 u  n# ^) E! Y            arr[cnt++] = nums2[p2++];8 a* V5 H' E& ]# c2 n
            }8 \: g0 B6 B1 ]
        }- x  C/ H0 ]# v+ Z
        while(p1 < m)
    7 W) P* u6 U* h) G3 c1 h/ J3 \0 l        arr[cnt++] = nums1[p1++];: L& n: W/ r# `+ Q

    & z3 W5 C: r! B+ g, x0 R; ?! g    while(p2 < n)/ G* Z+ v2 ?4 I, Y+ ]% d
            arr[cnt++] = nums2[p2++];
    ' X( K$ N  f; Q6 q+ C+ V1 [3 z6 c
    3 m# ?8 @+ l: Q    return arr;
    & ]9 v9 I1 ^! z2 U, K. ]8 A1 q}% H6 ]4 L* d1 o
    , n+ \5 o, Q. ?% G( f9 K. _( s
    14 c, v0 A5 K; p/ `9 ^
    2
    3 a' D+ V: E( d+ W' U3' d) O) _7 A4 t! {
    4
    ' N0 c' ^9 M2 n4 t56 P# t- S* [7 U
    6$ o9 p: a* R/ x% a
    7/ Z, C& Y. P% N7 ^3 G
    8
    9 ~5 k/ g4 Y  G3 D/ Z% @9: v/ O: Q* m7 ]) a
    10
    - o' T4 t: q! ~, t- R111 ~) x1 \& d$ y' W, U7 m
    12
    9 V1 P& t3 E/ N+ g: s& f13
    ; i1 s: c, g, s2 ^/ q14
    9 D, T; W. h0 @( k3 y151 a# t0 s( b+ f  a( `+ n" e, S
    16  b4 d+ K% T5 @8 V6 ]
    17
    # l; Q" C; ?# C1 R6 |  ^( x/ M18
    . t, @1 d+ \4 U192 h9 `8 V& f- M0 S7 T$ D
    20$ h4 G! `% a2 e5 e* A
    21* ~9 o. N8 B: m9 G6 v+ Z9 {
    22
    + b; F! V! i3 G2 Y1 R23
    # \: P* h/ o" X4 M  ^3 ?2 i4 L9 B24
    0 x/ a) @3 r( n1 U; J1 ^- \0 P25
    ! r$ k3 J+ X+ G/ ?7 v26
    2 _8 n& ]( {" C: ^( O( Z; M273 {6 I" _1 h% t6 n4 V
    28; M  j/ a; b( x2 Z. q
    29
    $ j$ g) |# o) Q30
      E/ z5 t1 c' ]0 B! _& ~31* @% d3 K4 z! d* l8 H4 N
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。; }$ `" i8 H& r2 ~/ |
    % K* K( t  Q( s
    递归实现% n5 b3 O9 V* t( D2 O, @
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。0 e, e6 H; v! v: l- h& p

    ) O, }0 Q7 Z! q; ^3 x! K- v
    2 v( Z; `8 c, m- k! V
    8 }9 I  R  B  {. a2 f  R0 F: |- x5 J5 F; N

    5 e; g7 ^& U. z& @7 p" F& q0 yvoid _MergeSort(int* arr, int* tmp, int left, int right)
    ) _: Z7 g# J6 ~9 y9 c& z' n{5 n. E' a% u; c0 T
        assert(arr);( x1 G3 Y1 ^: J2 ]0 ]+ C8 ?; U

    - v+ W% Q3 k" p; F- o) Z    if (left >= right)//递归结束条件不要漏了: c6 {! x1 d" g0 L+ D
            return;& [  C  v: ?# [9 O- ~

      n0 j; e2 E; d8 N# i. P    int mid = (right - left) / 2 + left;( z/ ^7 t% _" y- G
    9 l4 ?1 K( ^1 z5 S7 F' j7 `
        //划分左右子区间[left, mid]和[mid + 1, right]
    9 N3 Y7 P3 V  i7 u+ Z9 J" M1 S    _MergeSort(arr, tmp, left, mid);# h5 m9 s, m- p( V( ~/ G" M
        _MergeSort(arr, tmp, mid + 1, right);
    . N- \' B# s8 m; \
    3 P* [8 b  b% K* O    //归并
    2 x0 }! D2 |+ Y( U9 A    int begin1 = left, end1 = mid;. @3 m( p* t" Z. R8 `
        int begin2 = mid + 1, end2 = right;
    , _" w2 {, }3 U! ]    int i = left;/ \1 _: K; r% |8 n4 ^) N* J
        while (begin1 <= end1 && begin2 <= end2)0 C  ]$ {+ w9 a+ n/ N) t
        {
    6 l: q7 s& `7 }# E7 I6 J$ f( ?+ b3 z        if (arr[begin1] < arr[begin2])
    ) K% I% |( o. m; w  ?            tmp[i++] = arr[begin1++];
    5 H) ~5 J! _4 r0 J: D( Q        else
    ; P4 Z- b# l; y  a- W# Z; a! G8 @            tmp[i++] = arr[begin2++];
    " |+ ?, G' O, k$ o+ S1 A; Y. d    }) D# @2 I/ \2 w- x$ A
    0 I7 _8 X3 u9 n5 E; j, K( h
        while (begin1 <= end1)
    8 @- q: M" N6 w4 \% a$ z$ o7 l! L' G        tmp[i++] = arr[begin1++];
    5 @$ r* |3 Q7 X    while (begin2 <= end2)
    3 N" _+ u5 Q. ^. m/ N. F# E1 G        tmp[i++] = arr[begin2++];
    4 N% F) K: n+ e3 q8 g        7 ~3 F2 T+ e) k4 j0 C
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    * C0 w/ g$ G: b, z$ E; k' J    //而不是拷贝整个数组回去- E4 F' j0 n  j
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    $ U$ N+ n8 m. V1 B) V& n}
    : l8 |3 ?) }) r5 i; ?" f+ u4 ]
    , L9 k! n# i- o2 Jvoid MergeSort(int* arr, int left, int right)
    ( e+ o6 ~$ S2 U{3 X+ l( p$ [" ?
        assert(arr);
    & F! x6 L  B: B' I1 F; X
    $ O1 q! H5 T4 Y# u$ U( f) W    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));3 q2 G+ c3 v- {+ B
        if (tmp == NULL)
    / Z& J- H; N2 f1 t8 ~5 Y: f    {
    4 w2 ~# e! B7 e4 ?% T        perror("malloc fail");2 s9 {6 d$ {# z) b4 _
            return;# }, ~2 Q5 _! n: }1 ]2 _! Y& A
        }
    % ~3 z5 g0 E/ W+ B+ m) c
    7 ^& }+ c. m' R8 H) ~( }    _MergeSort(arr, tmp, left, right);4 g% N) H! |% t0 U! j+ g( `
    4 l# B% p4 Q, l5 P3 Z( @1 W  e
        free(tmp);' I7 }* Y0 \+ f$ i
        tmp = NULL;* o; g8 a3 {! Q* p7 H7 T$ G( u
    }8 `# c; t# V( _& A: r' D* y

    7 J" m- V6 ]  H+ p1
    8 Z9 f9 [1 I- z6 S2$ T' }3 D# J3 ^9 i/ i
    3
    5 D. `) F- I% U0 r. A  h  ]4
    $ i2 H6 h" m4 z) |9 Q7 D' v$ x5
    ; [" |: e. W* L9 p1 n6
      F: e$ o. k5 `+ L' d, |2 O6 q7
    8 l* K5 f4 {! ^4 ^  T" \8# b9 o6 _0 o* w( P+ c8 U# a7 |
    9
    6 {( j* P' b' {6 q/ ?. l10! n! }( d( q! B; J* N3 S, d
    11
    5 X: e9 W0 [" \! T  L8 x, r# X9 F12
    8 b2 \  ]1 v/ e) x6 [$ y13$ v9 C) \8 a" \
    141 G( Z- m8 V3 L' D: m& v1 _5 d/ q
    15
    - D: L! n" j0 G4 c) M16
    * w$ n. b, q- X- `17. o( {; ~; _8 @  [5 S  U
    188 s9 h; \4 _4 y- U( f+ K: H4 Z
    19# @0 A3 |' b  t1 ]; ]2 H
    20
    & n" B, K& S. \+ O2 A/ d6 g21; `) x$ q$ p3 B9 Z" q! E+ x6 W
    22
    . `4 S) ^! g1 B8 M' E( n1 [, q230 J, v4 _3 b3 |. F" c
    24$ I4 S' u& [: {/ @
    25
    ; V5 u" [3 L# b$ r! W/ P; g26
    2 N! }9 `2 |( ?27! G5 b3 f4 A& G! U9 k- }
    28
    % |/ E, W3 S2 w& J( z6 W295 B! D7 F5 e) \
    30
    4 K' v5 U, u" o1 y7 j- x31
    3 r* X3 {4 \4 B# x32! f; o, \) d) R3 k7 m5 i
    33
    , E# q9 {2 y6 s, L8 ]34
    : Y: @' `# R$ ]7 f4 O- J1 D+ W35
    - w$ p' k, F0 ^2 R8 n& ~36& e8 n7 Y7 P6 x
    374 W4 B6 Q; r  M0 Q- D4 U; L9 m8 [
    381 t. t$ t" b- T3 b# w2 l
    39& N4 l. y  r, Q
    406 U( F# j3 |! }$ {
    41
    7 I4 W4 w0 B- F- c5 J- @. m5 P42
    . N; t$ J, {" G  [5 r4 b# L436 b0 f$ M' X+ r7 C  k
    44- i, n! B+ g5 c  R
    45
    ) h" t+ E2 x2 s5 \6 w( ?46
    , |. S4 t& a$ A& s- U47  D" }  t$ ]; _  P7 Q
    48
    + R, B( C, \$ E# o, l* S  v* a5 O; Q49
    ; d  Z  p  A) ?50& `1 F/ o" C0 t  Y- J
    51
    % D5 p; T( v( ?1 ]6 D非递归实现& x' @  x9 C8 X2 p& E0 _
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    9 p1 a- X2 J- g. Q+ Y8 q8 N( F
    & Q; ^  j  ?4 V' H, ]" S. o4 z+ p3 p3 W5 V0 v# q
    7 W" K' l% L/ q, v) V4 K! w0 C
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。  z. R( M7 o+ n: g4 M: z
    - L1 B' X- G$ E2 Z- k) l
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    - g7 D: O4 A" R/ d- X9 M  x, ]  r1 `: A$ N# t- g$ X
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。' F* ?! J3 a" @

    5 V) _7 G! i+ {1 i. g# N代码实现1 F; m0 J6 i& S$ m  Y

    2 `8 G" U/ ~" m" l, A" Lvoid MergeSortNonR(int* arr, int sz)/ v" e* P+ Z! p' g8 C/ R# ^* W- K& C
    {4 P3 B! q* [' Q+ l+ n6 X
        assert(arr);0 y) a1 B# W+ v; f; z& X

    & C8 L6 e* L2 a8 \7 [$ _+ T+ `6 n  @    int* tmp = (int*)malloc(sz * sizeof(int));" `, H+ V! b8 y: I1 [
        if (tmp == NULL)) i' B7 T6 o: b- Q
        {
    . u+ t( A' K7 E, m" W+ Y        perror("malloc fail");
    ; d+ w! F1 Q( R, m* I' O: h, W! x        return;/ e, z% o* X( J" g; L- r+ I
        }
    " B" ]! e) B- K7 E2 M6 H/ S0 O2 c! v
        int gap = 1;
    4 x( n+ ?7 [$ m% H1 p9 x9 o1 W, N    while (gap < sz)
    % s1 q8 }/ m1 s# [  f* s% d: @    {
    : ^4 P2 @  d" }0 K: ^        for (int i = 0; i < sz; i += 2 * gap)8 P7 h$ M! f4 U# K9 C( e4 S' N
            {; u' k) a$ _$ F1 x- T% n) f. v6 D
                int begin1 = i, end1 = begin1 + gap - 1;8 S, o/ R+ M, @" [8 O$ K* Y
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;: H: G$ t: O' ?+ O6 Y: Z
                int j = begin1;
    3 s) m+ \" _6 o
    . _- Z2 p; i6 B4 N" V6 i            //归并) ]2 u$ [0 `1 i7 I+ W- T9 x
                while (begin1 <= end1 && begin2 <= end2)
    / W9 f( g' `: s  n            {+ T2 y3 a& a4 o& m* _
                    if (arr[begin1] < arr[begin2])
    0 P( X( L! Z" J( `: W                    tmp[j++] = arr[begin1++];$ T" [1 K6 A7 a2 Q
                    else     
    5 A, y/ ?) V! x7 q                    tmp[j++] = arr[begin2++];1 [. v. U6 A0 {6 ^9 G, T/ b
                }
    $ k/ m# M7 k9 n. c# Y* m
    4 p) n. F/ `( ]% N+ q            while (begin1 <= end1)
    ' T2 ~  e# s/ p- \: v                tmp[j++] = arr[begin1++];8 m6 @5 `4 _- L9 L
                while (begin2 <= end2)
    # h! m3 B- N+ m9 q6 u                tmp[j++] = arr[begin2++];
    + K4 {3 F4 k& K# o1 c
    4 y9 x' i1 W0 }2 v6 C( m& ~% P2 ?            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    : m; f8 I$ N+ |* W7 c+ z% ]3 D            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));& ?5 V1 }  U& j* ^- D" }) ]
            }
    1 m4 _6 i. F* H- x        gap *= 2;7 D  g6 R8 N5 V$ F9 g# j
        }/ H1 G$ ]. L, V. u: s
    * x" |9 ]* z$ y) r3 n. E  q
    }& P, O* x1 a+ V* W, j3 N; K

    3 h5 W4 o+ S+ H% B* u1
    % k8 ~/ h5 g% [( c& g2 p, r9 u2
    4 t; L8 n7 u& r- s6 K+ K( r: U- z3
    7 [3 q: Y. a' p0 W47 c. k) C9 l: @! @
    5
    1 l" ]# d8 g$ W7 y: _5 f6, _6 }3 j) R2 X4 E1 Z/ f
    7
    / {* A( B3 r+ I8# v3 T" Q& r  K# ]" D. S# I$ \# t( v
    9
    4 g) k/ ^4 X0 L. h10
    7 M' M9 m2 I8 R! b7 W113 b6 \5 R: [' a3 s
    12* j) Y4 I1 p* b4 H
    13
    # `( g3 f& Y" H$ B" ~8 U146 ]9 b2 ~+ t. V, O
    159 h+ x9 q# ~  c3 t6 J. U* t2 I
    16
    6 h- c; a7 b* q0 ~1 ~17
      m! m0 g, E/ o+ R' K18! }# b! y, e& Q7 d1 J
    19
    . B/ P3 |9 t5 t/ \( ?208 B. H" b! K  d- L- ?
    213 ?. M' J1 P) q- Z% ~5 Z$ P
    22( U5 f* D$ C3 U$ s: q* e6 d! j
    23
    6 v% z4 e+ F4 `24
    + c7 Q1 [/ J( ^. s* f5 m" q1 O25( {2 _3 `. ^+ B2 \2 [, p5 ~2 K
    26
    0 p6 G: j% [4 F6 Z27
    ) p& Y; d3 D' a28% Y( {5 w) ~2 C# y) [! l. i
    29
    . Z7 x& f8 }8 _308 i0 S1 c+ f: l% j9 G
    31/ F7 p6 n3 j/ c! A; N' P% @* E
    32+ N! B( Z; Q, q
    331 H3 b0 x& l0 Q& ]' f
    34
    + `- ]6 A4 V7 k7 Z5 y& i) T4 r356 V) q# }  O; V9 s; J( c
    36
    9 y2 }: u  h5 y% s37
    " M6 }5 Y7 [9 g8 h- x, g2 f! [5 R38# B; u( b3 q4 F( c3 c
    398 C. G, ]5 H1 D! y+ |" }
    40
    7 Z: D* u$ T% g1 ?" |$ t+ F0 g4 J419 A: W* j9 l" A7 q, k- T2 C8 m
    边界问题- }  I* I) K1 V$ t7 K5 M
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。9 v) V3 H( `* }) P# v
    4 Z5 r! ?. Q0 O# |+ @" N6 G% B4 F
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    0 v0 B' ^8 k( r1 a5 E* q* O  r& k! E8 e: X" f

      j# k& b- ^1 I, Z$ W
    $ G' r( |+ W3 y+ ^& u" w由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    : Y" u* p' J  i. E; `8 `4 \  _
    : W3 h  b" w9 P6 V, [( F. M第一组越界(即end1越界)
    2 h' W$ H0 d& t8 @- f+ p
    6 M) b; S& E$ T6 k- u' m应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    ) a: F3 V6 x, @0 [2 c7 S: f5 _8 I+ D- `8 o
    第二组全部越界(即begin2和end2越界); A. @! \1 m1 d5 j
    0 J8 \# s1 f& e; }
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。9 \* Z4 ~6 K: ]$ q# _5 P
      ~, ~( d* q" `& {8 `. \4 O
    第二组部分越界(即end2越界): \( g2 T0 A& M
    * c8 n) R1 `$ m4 t
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。" n! i8 @  [7 Z! c" S

    / F5 P' n* k. u! _1 s​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    6 W4 ?. g7 b# w2 G
    ! v% h9 v9 ^! L2 E8 l7 L: {​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    1 M! b3 J3 E( b: k; D& c6 f  P$ S/ g) L3 w. D
    ​ 拿两个数组试一下:
    & J  M/ I' z- {# E
    ! Z8 m) `+ F, z& m0 _" l' p; g( }7 r7 X1 _# |! W5 Y: U4 k5 W

    8 ^  h  V2 o4 |% T7 }3 w% b" {, t
    6 c3 Q/ K4 O2 c$ k* A. q, B6 U" `: [9 g0 h* P" d
    代码实现/ J2 f3 I1 n0 K; E7 [
    / D. w% l+ Q1 M
    void MergeSortNonR(int* arr, int sz)
    ( J2 [' }# V, Y! E{9 i8 F' D' {3 A$ Q, l8 t
        assert(arr);
    4 e8 \" q  d3 S" M. L$ G( @1 J; [2 Y5 x0 m2 p' v
        int* tmp = (int*)malloc(sz * sizeof(int));
    1 f- W5 Q% r* r& {6 ?    if (tmp == NULL)6 N3 y" ]: ~/ X- y  H
        {, a' b. S3 C# W6 M( g
            perror("malloc fail");. b0 _  @" p! r9 J+ @4 B. v
            return;5 I; A" L3 Q1 m- c0 e! z( s
        }% U; ^( h1 s& F. {7 e: J
      j; g; Y" Q! d& X
        int gap = 1;
    7 @. C- @$ B7 o) e; W# x: T" b    while (gap < sz)# f& O& G" {0 `4 V. u- ~) m! @
        {
    % h4 M% @4 E9 V        for (int i = 0; i < sz; i += 2 * gap)3 \, F3 r( J1 [( j& W3 f
            {
    2 @% c( E8 X+ E  T1 r            int begin1 = i, end1 = begin1 + gap - 1;
    * A% [# m8 Y% }            int begin2 = end1 + 1, end2 = begin2 + gap - 1;& o4 d2 y' j' G; ~, ]: \
                int j = begin1;' m1 [/ a" ?, S
                            //越界检测! l- s# ^1 ^0 E0 j) j
                if (begin2 >= sz && end2 >= sz)
    + s# q2 n5 J* e  _) L                break;
    3 C$ b- F: e5 I+ [, U            if (end2 >= sz): n; V! ^* R2 k4 p0 V/ d
                    end2 = sz - 1;3 W7 v' b  }! k- \
                //归并
    & L* h, O' [4 V# d7 c" ^            while (begin1 <= end1 && begin2 <= end2)
    ' h4 E+ r* {  P3 K            {
      ]- ^6 y2 L' V# q: f3 h                if (arr[begin1] < arr[begin2])) ]8 \/ B- p9 X
                        tmp[j++] = arr[begin1++];7 R4 H5 J, x$ s; M9 t) a
                    else     
    5 m9 K& K* V4 _: ^                    tmp[j++] = arr[begin2++];
    7 W* ~; j, c6 \; W            }$ R. I( s6 B) V( _; r0 Q5 b' }* H

    5 }, b, X1 K; S( d5 U            while (begin1 <= end1)! Y3 I( x# e! i, I. L" L0 u8 y
                    tmp[j++] = arr[begin1++];/ F+ n' f0 J9 k& ~  Q( d
                while (begin2 <= end2)) S" C; J) A% n  `+ D4 J0 j
                    tmp[j++] = arr[begin2++];0 w5 V' s& _$ m+ l8 l+ K
    " O2 x" w& \3 Z, P
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    5 [/ \" @1 S* d- D' N0 v            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));. G' [4 _2 L# u& l, T$ D3 L
            }$ w$ X, r6 Q6 H+ C
            gap *= 2;1 B4 P2 x0 v: j1 U# a( X
        }1 ]3 \0 i1 _% z, ~
    1 t$ ^1 G3 H$ h" k8 }( O( W2 ?5 g
    }1 [  s% }$ Q7 Y; ]  J* B) _

    . }. E! }5 ^# _: r3 E1% R0 [8 V: J1 w  J, z8 a
    2( W+ S$ `, T: V& k4 c/ v/ G, s& k
    3
    9 ?& o7 L: ]. e, P( L4
    # O1 t& K/ V0 ], M" P9 U5
    ' m& L4 x2 k. a5 E5 d6
    5 ~) G% L6 _# ~$ ?7: [: e1 u, v. Z- o5 }" \
    8* [* e$ g' t5 e  f
    9
    ! ~7 ^. }; m2 G- ]10% L9 V+ N. G9 t+ V  l9 q, x. ~( L
    11# C4 v. X) B' f, T1 c8 l. _
    12
    2 Q8 y: h& P2 X: b, ]13
    - Z, A, L4 S! B, x" o6 O148 y( t+ o' O5 `" S
    15
    " {) U% X, a" w5 `16' L5 l; o1 g, r* S! U/ H
    17; U# Z+ a$ n. m8 B6 J( l/ g
    18* S; O5 n, y2 O4 J; T
    19
    0 D4 Q$ ?& m. D/ O  h7 D# ~201 z4 Z/ C8 s( z+ Y
    21
    ; u: m$ b3 T4 L' C' D- m% M% `22
    . U4 O# f% c1 B: a23& C3 p9 ^' r" r! p
    243 s( [' d$ q: |7 z8 L' f
    25
    2 j8 j, V; T! t+ v$ Y* p26- {$ p. _3 V3 \. {: H) u
    27* f. u* {8 H: W5 H" q# C; z$ W9 d
    28
    . S; ]: M% M( {29- h) ^7 I+ ~, t) U4 ]( D
    30
    % C4 P/ C5 X. c3 b31
    ; ~  C8 i9 n" H7 a32
    . o8 m  u$ K4 O( U6 A) }: r33
    ' d- R) x  k) a- P4 v34
    5 M% N$ o0 o! ?35
    7 m! B! \- x* B5 `3 k360 g3 _# N; K) P' M) o6 B7 P7 s
    37/ F0 `( q0 Q. C0 b" A" x% p6 \
    38
    9 s: O8 g9 e% G7 Z39
    ; h. K" l: p! H% `40
    0 r$ P, z( D2 m: z6 G41; a2 J9 \  o# e$ r% p
    42
    8 J/ o- m& t. B) m3 U7 o43& ^. X: `+ q9 {/ @8 j6 P
    440 E( ^) J/ Z. x0 B# W) r
    45! x( }" @: H. Y9 G
    归并排序的特性总结:* I. h2 v" T% @% R% q/ i' s
    ) [4 v# B$ U1 o: Y- B& W# v* \3 _
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。* X1 G- S' U  Y" H9 j' k9 [6 i
    时间复杂度:O(N*logN)
    : y2 A3 Y& h" i8 b空间复杂度:O(N)7 l$ p: _! t5 g; J: \3 o# z: \
    稳定性:稳定2 y6 T+ g) R. N" m; c

    % v, f1 B) j+ S* f* @————————————————- }2 M: {# ?/ n  x
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。; P/ F5 t# [+ H( K  n! T, v; u
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    0 H' X# l( w) Z" j9 m
    $ {) s! @5 C9 l  C7 Q' z7 ?, ~9 Q3 J1 q  P& V* U2 x
    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-10-9 02:16 , Processed in 0.544045 second(s), 50 queries .

    回顶部