QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3325|回复: 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的排序算法】归并排序5 S0 h/ j6 _, }+ ?

      n0 ~3 Z, s/ D+ p4 ?' C. a前言, \4 q/ w1 [4 I. \8 X
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    1 d  u$ w. j. o7 y- r
    7 v3 s, t' z2 |6 }1 h6 R归并排序0 m5 l- c7 n$ T* d2 N. ~7 o6 Y
    基本思想
    # x9 P: C! g) J5 l, ^​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。% N; ]* d0 X$ x) J% v
    ! B; l0 M+ k; T$ N( {

    : s/ s: ?! G% g5 l+ i3 T
    6 o$ t- M5 i) ^​ 合并的思想其实和有道题目的思想如出一辙:
    # y7 l2 O& a6 \8 F0 H- W1 {7 N' p" q/ [" q7 q

    6 b0 I7 H( ~; `6 }7 C
    ) V( z( j  U. ^( @​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。) X) N$ u3 T* F3 S. l. m
    7 A3 R3 s0 a& F/ d
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    ) |/ e8 K: B+ {- w) o* C
    ; v& Z+ C$ D0 dint* merge(int* nums1, int m, int* nums2, int n)
    ' H+ p8 L6 l' m. u' R' e) D{
    ! m7 Y. w# p) E0 o( p" N' C' p        int* arr = (int*)malloc((m + n));
    " g/ _$ Z( ]4 R& r- C3 m; r    if(arr == NULL)) c6 D; f6 O( e/ W6 U4 }4 l
        {
    8 M' D* h0 Y1 a3 k  J% l5 n        perror("malloc fail");
    / A, H: C8 b  }  y+ F  S4 O        return;
    & V- H" ?8 t0 p    }# |+ j( L% c7 A7 h+ j
    - E5 {9 e& R7 |6 f" O
        int p1 = 0;
    * ~4 [/ m$ f, S' X' g, i$ h- a    int p2 = 0;( A- h: N% ?+ V( f$ A) g; p
        int cnt = 0;5 f9 i0 e. J3 C5 B1 B! y* k' q
        while(p1 < m && p2 < n)) n; s( n; J' @8 X) g! p1 X
        {
    + w4 E% J3 N+ V: x/ P  c        if(nums1[p1] < nums2[p2])
    " n, k2 u3 }9 s        {, X5 [1 w4 c1 i1 M5 ~
                arr[cnt++] = nums1[p1++];2 b/ `% E! s* E5 }
            }
    2 Z: v. V9 s- N( g6 Z        else
    & w% w+ }% X: J0 P+ W5 W        {: R! I1 R6 f% K6 h
                arr[cnt++] = nums2[p2++];2 h  v  [$ X  O) s5 J( _
            }
    0 }0 Y7 r6 O- |" J. O    }
    ( O; t& Z/ S/ {0 Q- G    while(p1 < m)- H% k0 q5 |; A
            arr[cnt++] = nums1[p1++];% a% v8 _, C' Q9 O

    7 y/ r6 x: B" l+ o    while(p2 < n)/ b% B& s( C( A5 }) T) V- r1 k
            arr[cnt++] = nums2[p2++];# L; e( d# K  P' j- [/ y& e

    ; p6 O6 _3 b% K/ N6 o7 C    return arr;0 w. x: G6 n+ v
    }$ K, Y$ ?" n+ F2 I
    , s# s+ ~9 |: e5 r
    1  o# J. a) g6 {( g8 X
    2
    ; Z7 q3 y* D7 Q: a3( q1 F! I+ y# p3 G
    4  p+ z; n! L9 j. n! r0 w8 Y
    5
    , }, S0 v: B( Y* c6% B) e* ?0 w+ |9 o- T- J; C* g
    78 Z5 O# t. Z  v5 K, F9 w
    8; w! J0 ]3 U" w; _3 b) ]/ V# @
    9
    / U5 O& U$ G2 G& w: n104 @4 g% b8 d& o1 K: l9 b
    11& J2 F+ v5 I3 h$ y" ^
    12
    ; F6 b& @# K/ N3 C13$ e: S$ A4 I/ c
    148 A. S5 @6 ?+ K$ _9 ~
    15
    ; K* n- l  g4 y& S+ `7 ^5 b9 W16
    6 Y  x" J1 S9 w5 E+ y17* m! T: S( V! v5 u$ j5 s# E- C( c
    18- K. L  ?) Z. ?
    19; M0 ?4 M/ m" V# E1 b  v5 H6 B. F
    20/ N1 ^* l5 \1 z2 N) B
    210 @2 S& \7 v7 U( S& X7 j, H) p
    22
    8 K$ l1 N, }( K2 ?4 X23
    6 j; E+ k; A3 V24( k( H0 K" D8 V
    25! l6 B  l/ `& ?7 s: z  ]
    26
    * c. N8 |3 }, Y7 l' R% k8 W* O27  C+ G! o- I5 J
    287 M5 h& C$ P( b+ U
    291 Q3 b1 O7 _" X- G
    30! h" T' w  O4 Z1 w& u* q$ a, m
    31( ?! ?5 ]+ @, p
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    + F7 c8 X, i, r7 N% N1 P( }. ~6 Z
    * p, ]! Z* L# X* H, K3 p递归实现' f; y: `" h. m! T: u# M, `
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。; `6 c* |' w5 X. \+ I

    & i! l$ u/ u' g9 |7 Q/ M' i5 |8 i4 p
    ( W) G7 P! v1 z' z6 O
    " f8 |1 T# [; m+ s( n
    % E% P- L0 A$ ^. Q
    void _MergeSort(int* arr, int* tmp, int left, int right)
    $ L# ]7 k) }5 ^" ^9 T+ S( Z{
    8 k7 {" {' O! q0 ?) X9 M    assert(arr);$ @- ]6 A) \( s% q0 _3 H5 K( i$ }

    , }; R+ t( {- Y    if (left >= right)//递归结束条件不要漏了/ O- i, O: U2 Z# p5 L5 N
            return;
    0 n3 a4 ~! R( K" {2 [  x7 k; h6 A) J) p( t. @( }2 @
        int mid = (right - left) / 2 + left;
    & q1 L1 p- A- o- w
    8 G# o" O( d2 i    //划分左右子区间[left, mid]和[mid + 1, right]
    ( Y( ]% H$ H7 H: u0 q    _MergeSort(arr, tmp, left, mid);
    4 V3 n- _9 |1 V" Y; k    _MergeSort(arr, tmp, mid + 1, right);# ^, z$ h/ z/ x! `/ V6 \

    2 L7 |/ F4 E) @0 y4 A: P    //归并
    ' [" v2 v' |8 b$ @9 t    int begin1 = left, end1 = mid;
    $ I1 o% x8 U. J) `0 C6 `    int begin2 = mid + 1, end2 = right;
    " N% U! L# m8 S  i    int i = left;! l1 B! y2 r4 m1 }
        while (begin1 <= end1 && begin2 <= end2); W2 w) v9 g3 V5 R0 @1 f9 x, \8 |% m
        {) [6 ]/ L( I  s4 I6 T" `; `; W: y
            if (arr[begin1] < arr[begin2])
    & G: g3 m# G' s0 Z6 H& f            tmp[i++] = arr[begin1++];
    6 B& j7 h. C* g: Y. d        else
    & q1 b8 J+ z/ D8 n            tmp[i++] = arr[begin2++];: J! M: U3 u. ~, F( Z, w1 P5 Z
        }& {" P0 E/ S  N; o9 U

    % C5 f6 H% n4 O3 c: s, M    while (begin1 <= end1)
    6 w& w( H* K& B" {0 n+ h        tmp[i++] = arr[begin1++];
    1 \4 i6 P7 k5 }  s( m2 `    while (begin2 <= end2)8 H. Z0 [$ Y1 ?7 P' q! X- f8 h3 X1 i
            tmp[i++] = arr[begin2++];! R8 ~0 @* E+ ~
           
    8 J9 F2 E1 L% m' |    //拷贝回原数组——归并哪部分就拷贝哪部分回去% c0 ^: L$ Q6 L6 x1 A
        //而不是拷贝整个数组回去. x6 q9 `' [: L! q6 l2 {- k, t
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));. W) D$ H$ |1 g7 P& q9 r6 h7 l
    }
    4 s/ ]" B: ~/ z' p: `4 w# A/ e; }
    6 \* w: E! R+ L6 |8 k; Evoid MergeSort(int* arr, int left, int right)
    ; k: r7 k. ]2 A4 P{( \$ ~" ~. n) h
        assert(arr);
    4 k5 h  f' \; O: t) R7 c
    9 d7 A! K1 r& n, b+ a; ~' X4 e4 U    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    4 s- G3 q. G& w# r$ {  U" h7 G    if (tmp == NULL)
    - G, M8 l4 Z+ y- B# [# B$ y+ S    {
    . _! d' j% {# r5 L# |( w9 W3 L        perror("malloc fail");
    5 {: n$ A" u# P5 {        return;) c$ I' ?1 n3 S  a
        }8 {' l7 U7 k/ H2 @5 T% M) L+ F) H( E" j# A

    8 U. Z$ u2 l3 H, F9 L+ ^    _MergeSort(arr, tmp, left, right);" Y9 X& h# @5 K7 D6 q

    4 L7 J6 ^6 U7 D" `    free(tmp);
    9 H- k; k3 u+ O) k; i5 Z; C7 }    tmp = NULL;9 P8 `2 Y8 A; ~& i( a
    }8 [3 p3 P- J2 S6 E3 f) j

    6 I7 V7 m' {) S$ R1 O1( o: {# a( w, T" w( `5 t7 Y
    2
    ) O0 O) D* ~2 Q- A0 J( H3
    7 S/ g5 V( E' L% u  R; j; W, d$ c, b, I4# O1 d+ r; ?9 S: Z% x
    59 a; E& j7 R' F# S( g
    69 K$ p: w7 T: M3 a8 g
    7
    " [% n# S6 o' [7 z$ C( b8
    % k9 h' u8 u! f2 e, J+ d7 W9
    . C$ w' _* L% y& p7 W+ f; d101 p( S7 M2 y7 X- L; I9 N
    11( W2 W( J6 T" r6 V: _+ E3 R
    129 J( J! Q- ?4 b/ V: s/ N+ q
    13
    + J' h0 Y3 M: E5 D# \- P; n14
    , Z; v* d1 ^+ c( \% N( c153 I9 `8 G) m5 \& o, _. }7 z
    16. E; K4 C8 q$ I/ U. @
    17
    0 P) l, S! t5 q! r18
    " R6 F* T% A* _% H7 I7 {19
    & Z) U( ^, i0 _% W/ y& V207 _/ d2 D" P4 \
    21+ n% x8 X6 K* Z8 n% t
    22
    , P& X# Q: e2 @" O( @23
    6 Y$ |; \' Z- E5 V  f248 Y$ R' _7 o* r9 c4 d
    25
    / E# m, g) R; |' p+ \4 y6 V' q  r% n/ W26
    ! I: e* Z9 q9 k3 b27
    / M8 }6 j% @: h$ {& ?; T4 A28
    ; ?" e7 X! e% |& w+ E# d2 k29# Z$ a4 V2 c8 _8 j( j9 x' K: s) n
    30
    $ U  W8 @7 k$ J6 W6 D( h31; S/ |4 L% X% T% ^) ?6 g4 k: z: E+ |
    32
    $ [8 \5 i' Y9 T7 Y& {1 H33
    . M# f/ q* g- E' g9 \6 b  e34) p& e+ F) [' K
    35
    " `* n5 J/ j! R36
    & I' R" O0 u# e2 h0 U/ J37. X8 S5 Q7 m" V0 c( z
    380 b. V; y4 v: V$ ]& M- @
    39) m7 M4 I+ w6 e3 |
    40
    & L# t* ?- y5 q+ J* h. Y4 g41
    : J# O" y8 P% f: o- @9 `3 B42" L  X0 z5 Y5 o2 q; D
    43
    ' e0 R/ S. ^! z; Y( v. d44; O8 K' @3 c! M
    45
    ( i; ^5 H5 x( J- }' {" c' u46/ M# u1 h9 l. ~4 s% _
    47
    8 K$ D& H: _( r4 J/ l9 h488 E1 m$ T  h& J8 z
    49$ k8 U. [6 u7 G- P  N0 w/ {
    50! }1 b5 h1 x  }- O6 g$ p: S
    516 k  Z3 s5 n- T: `7 j
    非递归实现
    & n3 I1 V5 a  r' v5 a; @​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。6 [; D0 j% G4 l, d4 Q
    4 t( ]" ?& F7 A' h/ t2 `+ `3 s

    8 `  `- M+ Q  Q: }* M6 w  ]) d7 t! e; V! O2 s1 Q
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    , H' o8 g) S: E" t+ m' H0 N* o3 Q) `$ Z: C: J
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。/ i$ Q( L0 C) Y  w
    % D: N5 R* r8 k) A, w( g
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。6 F- d0 k2 K; e- }
    + h& ]6 ~3 w: l# c# ?
    代码实现! T9 M) L" V. o* Q; c" L

    9 w' @, ]1 K; Ovoid MergeSortNonR(int* arr, int sz)
    ' p3 N% ^/ o$ b: }8 X" y! B{7 i! Q& O7 g$ I+ B& q3 E% O. w, ^0 s
        assert(arr);
    6 `9 }. R' w3 U0 S2 n5 T5 y" A  F( c
        int* tmp = (int*)malloc(sz * sizeof(int));" M8 M/ K# m% u; L" s1 y) N
        if (tmp == NULL)4 ^. m- _5 f0 F0 K
        {
    ' M$ I0 [+ K- q8 q# Z7 k" R) e        perror("malloc fail");* `2 }; f1 b) d; D. P0 M& V( X! W
            return;
    ; k, f) ^: d  J5 D0 c    }1 e# D3 f* }' R: K9 w
    1 I; o4 G; S7 W/ u3 |3 t* Y
        int gap = 1;
      f' {2 j; {) V, d    while (gap < sz)7 X2 w  t9 q, N/ I* J. l
        {( d& m; ~6 S+ ~, n$ P3 T( @: U
            for (int i = 0; i < sz; i += 2 * gap)
    $ n( V3 Q3 D) e$ a        {
    + S" O/ m5 a" E! S, [6 ?            int begin1 = i, end1 = begin1 + gap - 1;
    , R: Y& t6 C* J: I            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    . L3 [# h- s+ A            int j = begin1;/ O; b( ~6 B. e- I6 O8 j
    6 B# I2 J. g% f! D
                //归并( @  [8 G7 T, P# z: i8 U) A
                while (begin1 <= end1 && begin2 <= end2)$ T3 S  R; k' `. K+ F' q% r5 b
                {& h) r6 B" [% Z  V, ?
                    if (arr[begin1] < arr[begin2])
    . Z  n7 P3 p$ v5 B                    tmp[j++] = arr[begin1++];7 `1 ]& x" M) t( w& c9 ]$ Z/ Z
                    else     
      x7 b5 K! I! n# D1 x0 _                    tmp[j++] = arr[begin2++];
    . k# G* q& f! ?            }) t' Q% H% S# i! q

    * A. J0 g$ w0 _7 l            while (begin1 <= end1)
    ' W; Y# J1 A/ i- w. ~4 e7 g6 m+ U                tmp[j++] = arr[begin1++];3 t& w/ {. n+ A1 `& }+ K7 p$ u. V2 I$ n
                while (begin2 <= end2)
    7 y4 m1 N6 p7 D& ^. d& d3 M                tmp[j++] = arr[begin2++];
    : D, c; |! ], n0 [( N, O+ V; `$ u$ [9 ]! l# r
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ! f7 ^- c7 C3 w            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    4 l- g3 Q6 j5 j$ J& V8 x        }6 B/ [' J& k$ ~% F# A, w
            gap *= 2;  a  h! f4 X; Y+ v/ Z  M; [
        }
    * J/ `( t9 x% P! u& q1 K; G* d5 w4 @% d, m" w4 I" a' f( B
    }
    * G* o9 ^% j7 k. n6 }) }0 n
    6 f# K, s4 ^. P1 V! x6 b4 u% {1
    2 {/ d" M2 I, b' B9 G2# J( H! A: u* L, v$ e
    3& k& R' ]5 K, q- Q3 U/ }4 x
    4
    8 k+ r" k! W/ e5 ?5" R* _- M9 N, I" ]/ R" F9 z$ H1 e
    6/ a% K5 j( Q8 E
    71 _9 L7 Z7 }6 }( j
    8
    2 \% F: {+ H$ r9
    4 w% r& k' k4 [0 e6 |10/ H. ?( O9 Y0 B# s/ a( Z; l
    11
    # V# d+ N, g) s  j, D2 J12
    % o: ]5 _, H3 `: P0 E9 l/ f! s133 z& q. R, J3 {; O1 m) H
    14
    % G3 u# }! e$ n( W: Y& T# |15, R* W3 q# o" g) e
    16
    ' U$ x9 _" H! |) y( `17
    9 N- F+ J8 m! d+ Z% q- e18
    ! w/ P5 \. Z* q2 ]19  a' A' i: d0 r8 {5 ]% t
    20" }+ }& E; l6 \( r/ p6 }
    21
    # T8 k4 @3 @# H224 r+ e) x1 e& K. _* i% p
    23& R2 O* v/ w7 f3 W/ W. I) m7 W* v
    24
    6 x* J. v. ], ^8 }+ A25* H( r  L) n$ r4 J" U" l
    26/ Q9 T3 {0 R8 n" b( ]5 ]4 k
    27: b5 G' T3 z* W# k1 v4 x
    28
    ) N, S8 J2 f" n$ r7 G: B3 L29+ d" }' ?. i! s2 C( Z% r
    30
    ' E( V3 L" |6 x- ~1 _$ a6 d4 F* i311 y( _2 t$ J' V
    32
    : C* q, L. l; R2 Y33! s2 I' n- z; e  e7 a2 e& C" P, i
    349 W! F: U8 A! b; e9 }: j& W
    35
    " B: A2 J7 D2 e# S! G36
    # ~1 _% Z$ V; Y# ~8 M37( R% A3 J& W, E  A: i4 [  M
    38
    - M; Y* I1 Q+ W$ N: s2 n$ ~; ^% `39
    " {0 R" W% V5 m404 P% z* H' X1 g" N+ ^; ?% }
    414 Z4 a' d2 e$ Q4 t) D) ^
    边界问题% p7 Q# y1 [0 B9 T* d8 f4 A
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    ! v) `, {9 I$ }! S& n) X& `3 K8 C
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:* }  n% l' i4 k- P# e
    ; p1 e" M( i5 w# p. A. }. H: I

    & S2 h$ B! j# ?' a( V" |0 W, D4 v+ {& V. Y) x* X& Y( A% p
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    3 L9 j3 {* x" Z6 y$ z5 |/ b5 h5 D8 p5 i8 j  G7 D5 H
    第一组越界(即end1越界)  Q4 A( A+ a1 f& }1 e& E

    ( N, m: O- x# Y3 e" H) E; K应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
      f& g0 v% i' ]: X' G6 y
    / A8 N& k# Y4 N. F) Z$ ~* A第二组全部越界(即begin2和end2越界), D- C' W; C7 r) }4 t3 P: U

    0 ?  S' }5 I) Z. e$ N3 D3 E/ D应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。; \- o7 L  `7 V9 a
    - ~, z$ q: k2 S" ]1 ~& v( B# [: C3 ^. D
    第二组部分越界(即end2越界)' I( F6 T) o6 p$ ~7 P2 {+ `
    * k' h3 }* _: x2 V* a* `
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。- }  ^6 Y/ m" L# Y/ @; q. Q

    : j1 Y+ Z: m! N' C​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    5 C" |0 @8 O3 Q/ d9 N+ ?& d) |$ x
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    9 F; L( @, j/ ~* _1 `) Y5 f" f/ m+ }( T# q/ Y4 r, L5 J" r% p$ C. B# p
    ​ 拿两个数组试一下:
    3 [9 b9 [1 j/ T$ |( |. P: A
    ) c8 Y+ p) S) G9 Y4 F
    : j; G' ]6 }9 K5 u' `9 q
    ( |- w4 }7 k% {9 K" o# Q+ z3 W1 C4 N9 N
    + U! i' B5 ]! e( i0 @/ c' g2 a4 W- e2 V
    代码实现2 Y) T* c- p8 R7 ]
    6 f, I6 a2 k! L" l6 O
    void MergeSortNonR(int* arr, int sz)
    5 F7 L% z- Y1 V7 Q4 N{1 i) E8 S/ i$ A' ]
        assert(arr);4 [5 C5 Z) ~( [- C3 X
    7 k# z8 [' ?  P# V, M
        int* tmp = (int*)malloc(sz * sizeof(int));* D/ Q! g2 N- f4 G2 D8 G6 e, q4 t
        if (tmp == NULL)- A* V+ C* U' i5 A  p' b
        {3 ]4 v/ R- {2 C' Z
            perror("malloc fail");
    : @  [: ]' ^' D0 X        return;. z$ u% n. H" t) m
        }3 X% D* z; Z" G% Y5 A! p
    * I  S; V, e2 M+ c! @
        int gap = 1;
    2 M+ h3 ~+ s3 g# Y; ?) w  D9 C1 N    while (gap < sz)
    ! Y" t. E' c. L8 M! a    {2 \- a: A. F5 U) Q. j. V  ?
            for (int i = 0; i < sz; i += 2 * gap)
    . g) O1 U( Z; g( A* b        {$ ^% J4 V" ~2 H. z
                int begin1 = i, end1 = begin1 + gap - 1;9 M. ^, o6 h7 m0 P4 ~* [0 z$ O5 w. J
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;: b. o, k- F/ ?* x
                int j = begin1;: A; i& B% [1 s: k
                            //越界检测
    2 @1 y& H9 {* N. a; ^- h" A9 W            if (begin2 >= sz && end2 >= sz)
    3 [  X7 c9 B% ?6 S7 F2 E                break;
    5 {5 c( g# ]1 [! Z            if (end2 >= sz)* N7 X8 a% R8 f  o+ Y4 U8 y8 P
                    end2 = sz - 1;
    / P# I4 Y& @$ L            //归并" ?& ~- \* Y2 f) R! G% S1 R
                while (begin1 <= end1 && begin2 <= end2)
    - x4 J8 t( ^3 g' o" F- F            {1 D1 a  S% m" T( `
                    if (arr[begin1] < arr[begin2])
    0 b) j: k9 {# K" Z: t; \                    tmp[j++] = arr[begin1++];$ s" H& X$ M; w2 B
                    else     
    . {5 |7 G, |* P$ o' _3 r                    tmp[j++] = arr[begin2++];
    ) N7 J7 ~: V/ ?- l* e            }
    ' u% L. c& t, }3 m0 f: k% R1 L* A( n5 d1 ]' W. |' c% x
                while (begin1 <= end1)* M1 R+ A  m% v$ u4 R6 k' S
                    tmp[j++] = arr[begin1++];# b* L$ ^" q- Z" A: O! B& r6 ~
                while (begin2 <= end2)
    % c4 r. n5 m; `( ~- i0 o                tmp[j++] = arr[begin2++];2 r( l: _9 |& s
    0 @0 {9 R, c& V4 l
                //拷贝回原数组——归并哪部分就拷贝哪部分回去" M* v) H8 p) E- |# C# o  A
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    . Q1 y+ W( e+ z# c        }% l  c( w: X: Y9 D0 p! |# d% X
            gap *= 2;2 q, b' s) e+ |4 Q
        }
    4 q, N' C4 s+ B" d- d7 V2 }: a
    # a7 r) o3 A9 n}
    * T6 X' p8 F% V4 f; y3 _/ w( N1 H* P- e
    1
    6 G/ c: h0 M  m+ e( I8 ]1 |) v2$ I! E2 J" d* e- S; u$ H- `
    3
    6 v. |$ r) e, [: L! x44 Z, a7 p* t/ Q
    5
    1 V& s- p+ |) F6
    , z; `; l% t7 q; Q7 ~* z  Q7! U# N! i0 h3 I+ ?. _- ?
    8% g, E) c# f  e
    94 \1 y3 c1 m4 E! S
    10
    7 }3 t; H8 l7 j  y, S. q8 x115 V" h: ^# `# H4 @6 m; Z
    12
    . @" x) C0 I- Y  D& f. N! I2 }: Q8 d13
    . o# G: p3 @6 r/ |* ~) s3 p14' A3 q2 U/ [0 O# a$ z
    15: {9 i& }3 d* D3 p
    167 q3 g, P9 N* A/ V2 H/ ]
    17! l& o: K6 b7 |! A
    18
    % ~  ~+ S1 J) T2 |5 [; w19- O4 W0 l4 c' w1 o! O# Q- X. H
    20
    / r; ~0 B4 }7 i, f211 e" s( C6 n4 r3 M
    22# y3 P/ W  R% `) ]+ B2 {$ H7 g% I
    23
    + p( X# \, ~& V3 E* q; {# g24$ g* A+ r/ A+ f! `1 K. X
    25
    . H) Z- M. t4 c& y265 K" T) e5 A  H% K0 e
    27
    8 v2 w& ?- i: C: l5 O28
    ; l+ x8 J$ y, r+ B4 }29
    2 e# G# B0 C( I30
    ( `+ m5 G2 [" C3 d) r3 i+ o31) o* G( @% `, S& @2 S( _
    32
    1 f7 A1 E7 @: g- Y33
    ! x& U* \( k( m& q: |( d7 U' O34
    5 \6 f# H! L4 V# n; T35' r4 `, A* u9 M' C1 R
    36$ O. g0 n! x# h( q$ r
    37
    ) U  B: u0 X( T" q9 g9 c38* T: q* ^+ e! M% o7 D# a" ]
    39; g+ C: Z- }$ Y
    40
      g/ e! B: @+ V/ t418 a2 f: n) L+ J7 N' w
    42
    4 D% |  L' B0 j; O43
    8 S  m1 S: s. v44' F' Q5 m' d& D9 c: t" \( Y; |
    45$ a. c4 d! E" N' h9 L: |
    归并排序的特性总结:4 l- M7 Z* |- \
    , ?" P/ E' _2 E; e2 I5 U/ ]9 j0 `. ]& `
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。2 `& Q; p' g  o5 ~
    时间复杂度:O(N*logN)1 h9 s; c0 X6 A# a; y
    空间复杂度:O(N)5 K% ?% r$ i+ S
    稳定性:稳定
    / t$ b! t. P4 a# K* j1 y% C1 @* ]6 R' U
    ————————————————
    5 p# h: ]! X4 Y版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    . d/ {* h" P) X* C7 ?原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657% Y4 ]$ S& P6 C8 B! ?- w
    + Z1 F; X* X" S' a
    & q' [9 L$ |1 A- m2 c# X& L
    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-4 20:16 , Processed in 0.567474 second(s), 51 queries .

    回顶部