QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3270|回复: 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的排序算法】归并排序) n% i; u2 z' n9 _, f; }
    9 A% g. U$ Z# r7 L
    前言! `! d; c  b( t% J7 \3 G
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。; @" ?) @  U4 k

    , b6 o! R  H/ K. p; t归并排序
    ; R, `" z: k1 e. f/ S2 P9 ~8 ^基本思想, s- o4 \  G' o- \" T
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    2 f- T; d0 d/ g9 Q  G4 r
    : d% a: J  B% B9 u4 d5 h0 }, t" G$ P1 z8 W! C0 o; M

    0 W5 h% o8 X2 z) D/ s3 x9 J​ 合并的思想其实和有道题目的思想如出一辙:
    , P1 R) t8 x) j& v2 {
    : O8 U% J. F' p! X: M4 C
    0 a7 F/ z) @4 U0 g, h! B2 H' }" k! U) z! `' K. X. ^+ M
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    / b! ~1 h1 G7 b1 j2 f% D" ~2 r+ c* Y# w3 j1 G, o. U, z8 _; s
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]( U9 Y2 r, r) R  A

    : n$ t4 E7 W, t. s8 p" a, P% m+ Qint* merge(int* nums1, int m, int* nums2, int n)
    5 j+ Z  e' K; A) ]5 ]4 N{9 j5 _. `, d$ m( g! b7 B+ i
            int* arr = (int*)malloc((m + n));$ N2 \) f# l" {
        if(arr == NULL)
    " I- H: g/ Q" c9 X    {) Z  H# E0 {7 {9 b2 H, u; O$ h
            perror("malloc fail");
    ) O. D9 }& r1 u3 o  P        return;; ~* ?; ^: ^$ p
        }$ m0 \$ \- B0 q- z0 L  H8 ^
    6 p! h$ p7 i6 V  p' U
        int p1 = 0;
    $ D+ a* e& I% m( r' \6 o! l    int p2 = 0;5 m! M" C2 m$ Q2 p
        int cnt = 0;
    4 N( Q7 M- h, ^! ?5 n- H% T    while(p1 < m && p2 < n)
    3 g7 M, g' \1 Q3 b( n    {& W# q6 N1 A# W/ i# V# P
            if(nums1[p1] < nums2[p2])
    / c+ ^0 l0 w  ]8 l; |3 |/ }# I        {* s& L7 w2 M* K% q- k; {
                arr[cnt++] = nums1[p1++];0 T/ Q6 \( s- N
            }6 _6 Q( @5 P, X' l# R, g- V& I
            else
    ( ^5 a: X' |, x  y3 G: m        {
    + h' d* j6 ?& j0 Q2 s+ f" e            arr[cnt++] = nums2[p2++];# k% y* }! X6 O
            }6 j% \0 {" q3 I- X
        }3 l* t; X+ K4 p) Z0 H4 z' _+ }7 F7 x
        while(p1 < m)5 O' V- y" w. H
            arr[cnt++] = nums1[p1++];& f( o. v8 a2 w  {1 T0 k! O

    # j2 y" V7 P8 C. x; v, S4 Q0 Q    while(p2 < n)9 H3 m3 _' |$ V$ i) R" b
            arr[cnt++] = nums2[p2++];
    + O3 `! ?$ s  O! P
    # j3 g( t% w( n; A+ j    return arr;
    # i1 _* p5 T" k}
    : a/ |4 R3 o( p8 M: `, o! V
    % ?' v* f5 q5 A# y1
    ' l6 l1 a8 ~" G3 n  y; z23 T1 g& y2 y  [& q4 d9 \* T* p1 {
    3
    . F9 z# P# n- q9 G9 x( I: R0 X- w4, I0 v5 C0 q! d, j9 u' E. l
    52 ~0 n4 w2 L/ {
    6: t4 {8 A* R5 x& u4 @6 r2 {. U% H
    7
    ( Y! |: U+ @6 O5 a& l+ ]8
      x  }! P+ i/ l% \  ^# j5 o& A8 V9
    2 |5 k3 D. B! ~, K9 l+ p1 X+ V10
    5 b9 L, R3 R( A- w) b114 }; p+ [. g0 M0 Q* }
    12( Q- W- F3 i9 c
    134 v1 W6 v5 h4 o! g  L+ A; E
    14
    ' J4 I) G8 w; c% U+ o2 K' Q+ L15
    % G1 u) l' S1 b9 i7 q' `0 ]16$ ~* ]+ `# e4 ~: h) I# M% w9 q
    17
    - x& ?2 l1 W8 G3 h% J, c18
    ( d* \# j: t: w+ Z4 f9 ], V* t19; y, y: t0 o( t1 z# u  w
    20
    5 k0 Y" Z, L  k8 O21
    9 A8 A" ]4 I0 C' n* u, X2 a! s8 k22
    ' D) Q3 U- f2 x! z4 A2 h! |/ l23, {; U, I; h" e& M% c- d; k' ?
    24, q, Q& F+ m& L4 W2 e/ `
    25
    1 ~9 W$ m# D% I26
    . r, }- ^; l  w27
    0 i# Q5 l# ]/ g) M! D9 [/ I/ j28
    + c- c, |- l' Y8 y3 x29
    4 }" V# C4 \- E+ _6 x30* j" ^; C/ r% S% {$ B  N
    31
    5 I  {+ m' h. y  o0 W. a​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    3 }- ?( }9 s4 \$ a, g  y
    6 {4 R* Z2 O1 U1 ^( N9 O, |4 |递归实现
    / z9 T" z$ \% ^+ S+ a​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    4 n% W" N. |8 E" {* A1 A. N) X* ^1 L# ^. T! d, @: L
    # M/ b3 ]: a0 u8 _& J1 O, N, R' D% \

    $ g, Z% y1 l1 a2 W% G9 z; S
    7 Z! j7 O4 r# n
    / n: V/ h( g' p. `+ {$ E8 b1 ivoid _MergeSort(int* arr, int* tmp, int left, int right)
    ; Q0 M$ R( R8 Z5 Y9 M{
    4 B4 G1 {9 g: ]0 S, x+ i! U    assert(arr);
    ) |6 {5 H& ^: L) B; ~- F2 i8 V* h4 ?. C7 b7 ?$ b
        if (left >= right)//递归结束条件不要漏了
    ! T2 ^# {! K4 `$ t        return;- V5 h( c4 G) n2 A( w

      Z8 W8 E  w$ x7 E! X    int mid = (right - left) / 2 + left;8 L; s: \+ F. Z# B

    + E6 {1 ]. o* d    //划分左右子区间[left, mid]和[mid + 1, right]! b* u9 `3 w' ~# t% G$ n
        _MergeSort(arr, tmp, left, mid);
    & {+ w+ R: E/ ^1 L5 [    _MergeSort(arr, tmp, mid + 1, right);8 w/ m5 o$ h# h; E
    ; H1 \& {; c* A$ ]8 y6 F
        //归并
    0 e( D  }# e( @6 s0 Q1 \& v    int begin1 = left, end1 = mid;
    ' ]* b1 U% M, D( E    int begin2 = mid + 1, end2 = right;
    2 k% _4 {7 d8 y: I    int i = left;
    ' Q7 S# Q. [  o% C    while (begin1 <= end1 && begin2 <= end2)
    # r7 [: g+ @% D' s    {9 Y7 M! l/ u; n" B+ s1 M5 i
            if (arr[begin1] < arr[begin2])' i+ w% e8 G! [  P: K
                tmp[i++] = arr[begin1++];
    . o6 _3 S" E( Z$ ^5 e1 S        else% {6 {3 ~  a4 m; C; k
                tmp[i++] = arr[begin2++];
    6 b  r) y: U  v: E& j: R4 z    }0 ]* i! l2 V% s) T# L
    4 [3 x5 _" D9 a, {4 L
        while (begin1 <= end1)$ P7 F+ r  ]+ I& D  y
            tmp[i++] = arr[begin1++];
    7 F; u8 z2 Y* M4 C6 e1 ^    while (begin2 <= end2)
    % V8 {* _- Q' M$ R( k        tmp[i++] = arr[begin2++];' A, W" a# V' Y* {
            % W; M% r, U7 q0 t3 _) Q
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ) a$ \& h( ^4 H5 b( W; a    //而不是拷贝整个数组回去3 ?% i5 F1 ?# T# X
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    $ N5 _2 Q5 Z& q' c( r- U0 j}
    4 l6 p: A( e3 A4 k+ ^2 A! Y; p
    & U: L; y+ X, _) S! T+ p1 z$ p( \void MergeSort(int* arr, int left, int right)8 A4 c/ v& J) u5 r  ~
    {  X  ?- F. \1 G: h
        assert(arr);
    7 `* ?& ?" s$ \9 |4 a- Z2 G+ A% k) ~0 A& p4 S. `
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    ' m0 \1 h; N) d8 o% d. M2 w, n, t+ z    if (tmp == NULL)$ z4 `, L- Z( q% c
        {
    $ N, q: l% k' E% H  P3 \        perror("malloc fail");  ]# v5 @3 ~! d9 T4 J  X* t
            return;& s, P! G. }1 `. B2 X( O5 l
        }
    $ R% t: t) B4 ], Y+ T8 ]+ I
    1 L2 ?  b. @2 o7 _    _MergeSort(arr, tmp, left, right);. u! Q  f6 z+ Q! j6 {7 x! R
    ) S( x3 L. e, C" N4 P; g/ H0 A
        free(tmp);
    : g: B1 u. o$ v2 V1 m; w. F% l6 w' P5 p    tmp = NULL;
    : c6 _; A2 |1 R# B, }% I}
    $ t; v( F2 I! {( G6 ?5 `) h* @  x9 ]* i$ h
    1
    4 [  S9 s% Y1 S/ _" i: {2 e: M+ [2* t" z  l% a# p- R
    3( @  [% R1 C$ _9 G0 u$ K) |) s
    4+ J( J. `3 b# H1 L( D: C
    5
    * c1 m0 m3 D9 a; f9 _0 T, Z8 |63 c8 A6 o) e! d
    7
    ' h% Q( w& `2 K- i3 [. y  I7 p8! U' O* W8 e& ]6 z1 v
    9
    ' d- G. g$ S0 ~* H* {10
    2 c& v. @3 L  e11
    # D* a! m) n2 \: I: Y, O8 v! G12; z$ x- N& p8 D& D: E7 P5 |8 v
    131 h) S2 @* Q% J
    14
    2 |, b, N2 B9 z, v& e15
    % ]0 Z$ F: H6 e% e  Z& L6 M: F16
    4 x6 Y7 [0 `- u4 \/ ]: |1 r/ a17+ R( X9 v) B1 ~, n. f. |
    18
    1 c  Y% _( H/ G5 U3 p( d3 N! H197 G7 ~7 C$ K, C4 Q
    20
    # Y* t1 g7 M: s  f# g# v' j8 Z% k21( }! @+ T9 [' Z6 i- {; Y1 Z
    221 {' P2 o5 L& ~! H. p0 B
    23
      ^$ _2 \0 V& {# }8 E1 O6 K24
    9 s6 A) Y& g5 |8 ?9 _$ F3 F25  F3 s& |7 w" G/ x: {/ I' [
    26
    ) b7 b* h/ r5 y, |277 S- ^0 [6 J& l  \4 N
    283 O+ f$ m2 s1 A9 j+ m: @
    29
    3 ?/ n" \" S; l1 x30
    , {. J& v! |4 b0 I. q$ a6 t31" J. j2 H2 U7 {
    32
    6 m; K% E6 ]/ v1 }9 o332 D$ i7 o. ^, N  {
    34
    7 C5 E! P6 K) C( C358 g3 n  {& s& y6 B
    369 X* t$ H+ ?$ D" D
    375 ?1 F) i- E0 T0 U# x: M
    38! E0 ~+ I  y4 }0 e
    39
    5 Q+ |# l2 ~+ R, S9 d  y40
    7 ?2 a+ l2 d" r$ f8 O; F3 k) g# m41
    3 f( t  `8 E; Y( m& c8 o42  g5 ^2 m, B* z+ b! ?
    43
    ) l! h4 F$ I8 |. ^, _* |44
    ; ], P8 W. d* @5 q$ Y45  z7 w) O9 w0 f& y, U8 I, O8 B
    46
    , l' ?) s6 P* ~# ~' {1 p7 B; x$ i, O475 v2 g: [: n, B& H; V- d
    48+ x6 ?' a5 t/ g+ B: J1 A2 ~% T
    499 J; j0 s- Y' Q  L* S5 Z
    50
    4 P" M1 ]; Y0 d# G5 q3 E51" D' w2 I. Y9 s' o. s  N
    非递归实现3 Q2 @! N, _; g9 w) Q
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    5 G; v8 L/ G" [7 g) Q2 n
    5 ]; j9 o2 u% o' g1 X0 z4 a1 c
    9 ^4 o2 e+ }# d7 u( D
    % N' l' ]. }% a; ~* g: p* A​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    8 X$ N# S9 x: ?$ \4 X  Y" h
    % p8 _2 q* v$ O  [​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    $ K! H: g1 j7 E/ D3 H
    ) }) H7 a0 C% J9 @' u​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    ! ~- o/ y' Q; y4 Y) e; Z6 n  V; H' G+ u% y; d4 I2 n- i
    代码实现! S& N6 S  I; |0 ]9 X
    8 B* ]+ o8 c. B9 v1 ?' z1 w
    void MergeSortNonR(int* arr, int sz)
    : l  d% m) I+ s2 s; \0 b% K{8 n3 u. B) B; u% f9 `9 ~" w; P
        assert(arr);
    , u$ y! m- W+ H1 A& g. Z1 N3 m+ I2 `& Q
        int* tmp = (int*)malloc(sz * sizeof(int));
    , ]4 J+ U) t! B' E) S  D) R    if (tmp == NULL)
    7 T8 `; d; @5 W' x& L1 b    {3 }! D! V) S+ P( ?! j
            perror("malloc fail");
    2 b$ |: ^/ `' O9 S6 }+ _& w4 @        return;
    ' t$ h+ G. y$ U" g! y3 T    }' n! b! Y" D' \5 M3 H4 z2 F' \  V

    2 p# t! k: ]% |7 x- A5 |. E8 k" I    int gap = 1;
    4 a7 y3 }/ v: [5 @" F: p- h    while (gap < sz)9 `; R6 F- o) j2 G& q' x) O
        {
    & w8 p& s% j! W  g        for (int i = 0; i < sz; i += 2 * gap)7 y! X- f! g, y8 q0 {6 p( H0 ^
            {  x1 `$ p# j* V  W
                int begin1 = i, end1 = begin1 + gap - 1;' c$ j1 M( m5 D4 q
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;5 v8 o/ M. u1 [& ]# G
                int j = begin1;
    7 f. p8 Q) z- s
    + U, C8 L7 E# D+ I" _! C# j  M            //归并
    ; Y+ Y& t( n: f" ?8 M" t            while (begin1 <= end1 && begin2 <= end2)
    & S- |# p6 \8 `$ D5 V            {
    ( m$ D& f2 U; A; b                if (arr[begin1] < arr[begin2])
    ! O, a+ ~9 H0 u. E+ O                    tmp[j++] = arr[begin1++];% o9 W) ?1 v+ k
                    else     
    : y9 Q% Y+ E* L+ a; _) Y  m                    tmp[j++] = arr[begin2++];
    : _* L) k: M( p- k/ s            }
    . P9 l$ G- ~* X# I5 H+ A- ^" d( z% s# T' g& S
                while (begin1 <= end1)
    2 q1 o3 K3 f; [/ l7 @6 r1 b! R                tmp[j++] = arr[begin1++];9 t( e0 x9 v' `; x1 R8 L
                while (begin2 <= end2)  ^. {+ D. s4 q1 k) D
                    tmp[j++] = arr[begin2++];
    ) M$ S0 ]& r9 Q1 z0 h) W8 D
    " q  C7 ]; t0 Y5 X/ V            //拷贝回原数组——归并哪部分就拷贝哪部分回去8 _+ M* n8 r& Q5 [
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));2 [) n, s6 }8 h4 E0 L* `2 }7 A
            }( ?7 S0 c. U+ Z: R4 s
            gap *= 2;, d7 [4 ~% Q% @* I% o
        }
    # S/ k1 {* h1 E3 E& o& F
    ' j$ Y+ l! o. n3 a7 n6 Z5 I3 f}( y7 A. ]9 O$ R) m+ J

    ' r1 j2 u3 ]; N1
    & g: L) L( U: z2 B, P, q0 N* h2
    4 t; _; y" q- M; j4 f9 R2 E3% ~7 r: Y; a8 F' J* l5 w8 Q
    44 U8 u6 w8 u( K
    54 T2 ~$ u$ L6 t1 z' }
    6( k& D% R8 I* y7 }' l- }
    70 M9 j& u/ ]! s4 C
    8: u& [3 L6 j8 E! A6 A& b4 ?: T( N
    97 P) f& O$ `7 u: X+ i9 r/ D
    10
    - u  S& b4 G9 _: e0 d11
    * M$ a: E( u" X. n12
    ( b3 x/ K$ e. r/ N& S13
    / t0 {2 x: s, j8 ~; P14
    ' E% W( ^4 H' ?3 K/ Z15, ?" I2 D, b7 K1 k
    16* Y* X$ I. J" M( h8 R* W
    17" U4 G8 P8 q! ^' _# D8 R
    18
    9 u! R- e. V, x* L" e5 W& v* W& H: |191 {8 a9 Q1 Q! r" @" V+ g: e
    20
    & B: V! |/ S/ I# {+ k21. [. s- d. A/ F' |% B
    22
    ! |* V: A. S2 m- \( w( b9 O1 i/ i1 f23) O' t( q" ?5 o) ?+ L; Q) q3 b. M
    24
    ! g8 ?. Y1 @6 x9 G1 v25
    * |. d* f- P7 I3 R. L3 F26) U3 L% B9 S+ Z- G; k4 z8 h
    27
    ' y! ^+ L# H/ A" a( f) h$ M28
    ; Q$ j+ s$ R) x( h29# v8 z$ E& M4 U7 _! a- _5 L% Z8 p  ?
    30
    # X# F6 |# s2 ~2 a: _+ w31- q5 u8 H) N. N0 ^4 U% Y( Y
    326 L2 ?7 `2 I+ u7 _+ Q
    33
    ' B5 ?6 f! z* C% O# k% h  m34
    , q7 [  s' k1 e; q( v- H35% }- Q1 r: B8 ^6 d! e* d1 s. A
    36
    . c4 M: Z3 c% [' j  U; W37
    4 K& n) i/ m# R0 C, b386 I5 |+ M3 x+ J& f: Y$ L
    39
    8 h5 }$ H" l4 A+ R) ?40
    / ~: a$ L/ I3 P41* G3 [3 s" w5 d# p+ e# O: q0 a" V: b# G
    边界问题
    ' E' f* e3 u) S9 r* d( t2 d​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。/ @" }! ?6 S" D$ m/ y/ F( Z& S: z6 l
    ' z: k: r8 [- l2 X$ X# i
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    2 m( T, c" \, d, E$ J
    ( O3 s; h7 t3 k5 l6 L# [" P; I
    3 V2 R' O& U" U" r
    ! J. i# I* A$ D/ v: D由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    5 J. p# p2 N. w6 l
    0 L4 I% P. K" {$ `' U; |: V" G第一组越界(即end1越界)0 X0 h2 k/ i% u% l" Y: o; n$ R; O

    # `% r- U# H4 P应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    % ^( T3 k8 t/ c$ V, Z6 W/ E( Z5 X6 f9 v5 y. f6 [; e
    第二组全部越界(即begin2和end2越界)
    # k& w9 y; c; b! f! h% C0 K" k( l/ k# ~+ W
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    5 m0 z7 t. D' w  G6 w& S. w) M! Z4 ^8 Q  @. Q' M
    第二组部分越界(即end2越界)
    2 |; |) @% ~( s9 c* A7 D: z2 {% w+ w( b2 n7 h$ K
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    " [. }9 t  ?5 Z2 v7 L
    + N+ u. Y0 u4 x& I) y9 N​ 其实第一种情况和第二种情况可以合并为一种情况,原因:' T5 z* P" O# G

    * P1 p$ Q4 }( T/ ?1 S​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    ' W2 @) M0 e* P( N! C$ v
    ! c- _; u( B! ~" U+ T​ 拿两个数组试一下:) N, _- j- |+ c# ]) m$ T1 q
    ) h8 Z: c: _& ~) d
    5 y# }( n6 A  c* h; z" Z7 l6 v5 H
    ' m9 Z; {  S4 K5 h% |$ `: a  w" \

    $ m7 ?3 i- h+ S$ n  M
    7 Z6 W. M; _  }8 W1 R代码实现
    4 z2 T% m9 P- C4 W' D9 a1 h5 R# m. m5 D  X; M) v3 @
    void MergeSortNonR(int* arr, int sz)5 q/ W5 S' }2 w! d$ ^% W
    {  q( G: |& F6 m  R0 t- o! z
        assert(arr);- U$ p% l* V( [) i! P% |
    ( G2 K- r& X- c# t$ u
        int* tmp = (int*)malloc(sz * sizeof(int));
    4 N4 L& O" ^) i) u- x    if (tmp == NULL)
    + x1 Y& x" U* c, E    {
    # ?, W$ _3 h. o. V        perror("malloc fail");
    & H/ W% l- ?  c$ F4 c# |        return;+ T+ w# I% X8 J" Z, N- d( Y
        }9 ?( r8 d# e" F  g: y
    4 G8 x5 j/ ^; P+ f5 E3 j
        int gap = 1;
    4 H7 g  T$ S. A" W# Z8 W4 _    while (gap < sz)
    7 G) H% L' c' T3 e8 m    {
    ; `% P! |8 ~0 b" z/ P        for (int i = 0; i < sz; i += 2 * gap)
    0 F& J' u9 P7 H& q4 }) q        {: L, W$ }/ y- A- v
                int begin1 = i, end1 = begin1 + gap - 1;
    8 ]  D; }" _- ~9 `+ x3 R            int begin2 = end1 + 1, end2 = begin2 + gap - 1;! X/ P$ T- |# ^. D+ P& z. ?4 P
                int j = begin1;- i4 b0 p$ k6 p+ \
                            //越界检测& S4 C  ?+ _* z& U$ S1 W7 i
                if (begin2 >= sz && end2 >= sz)6 M9 G9 }! n) H
                    break;! ^/ K* e# ]( l% t, B+ c$ G+ A$ a, \- \
                if (end2 >= sz)7 ]& [3 O6 J  ^' b4 j1 ^
                    end2 = sz - 1;
    6 D- z/ |& A' g* V2 d            //归并
      x) I( V) C6 ^" s            while (begin1 <= end1 && begin2 <= end2)6 q7 s4 A0 }0 X' ~# d. \1 i
                {
    4 o: g2 Q: W2 Z  l; T* Z8 j                if (arr[begin1] < arr[begin2])
    - j- S  R  l9 }. T) ^1 o  b% T7 h                    tmp[j++] = arr[begin1++];
    ( s5 p6 j2 F9 V2 k                else     
    ' v) Z: j' f6 Y3 n                    tmp[j++] = arr[begin2++];2 D- G# J' P$ a% x$ j* z
                }8 a. C1 a1 R& j6 m/ v# p8 l: y5 }

    ) |; k- I7 e9 Z; X6 H+ E            while (begin1 <= end1)1 N; Q! ]0 d3 l/ w! A1 H5 w
                    tmp[j++] = arr[begin1++];
    , l9 l7 G! i4 g* q4 C( U            while (begin2 <= end2)
    1 Q# {# w& u  ^, h                tmp[j++] = arr[begin2++];
    2 a9 X% Z8 j& X- M9 J) b
    6 N3 S( S2 s: T1 g/ A            //拷贝回原数组——归并哪部分就拷贝哪部分回去9 P* H6 L! i* o1 O  b& i
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    " m" h+ X0 X" |3 _# K        }
    # A8 O8 B) L: \        gap *= 2;. n" Z: i8 z* n' J
        }: z. S5 s" M8 n

    5 `& [1 r7 B6 Z* U  O$ |( {}
    3 e& _- {- X+ ~9 F! P, D
    . a2 O& j3 M7 d1) C% w3 K: q# `" X* `/ |+ a
    2
    ( e( c, r  L3 p) t- U3+ l/ \) w0 Q3 Z
    4
    - Z) ~. ^3 ?* S) O# \; `, {5( b3 y% q. ~! t+ S. \% s
    65 K6 S" ]3 e! F4 J0 g  h
    7" W% c4 H! ~0 J9 W# E% {+ p9 B
    8
    8 a! B  |- r9 i. z3 D- ]# W9
    . X. I6 K- G3 H. n( t5 g# h9 q109 z+ J+ c$ s  \2 Y
    11
    7 ]0 L& i2 Q7 c. w) C12- d$ k8 w$ k4 m7 h1 D$ H
    13
    + K8 X* C+ |3 }7 [  v14
    7 Z  k$ N  N0 V6 d  A15
    2 s( ?: ?* C/ l' w% r, ]16( `& @  `4 u; y% [- M+ P$ D
    17& X) t( ?/ M  H3 d: f, F8 P0 q
    18
    * V# k, K+ ~6 E/ |! p7 ~19
    5 G  P5 I$ F; e  |20! B" [7 u9 S4 i# J
    21
    1 E! Q' w8 f7 o( R- J22* c3 r0 I- e; Q% [/ v
    23% \) ~9 h" |. w& n, u% k3 l
    24
    % O! u. l9 \- d( Z& V( n# Q25
    " Q5 @; Q1 W) V# X4 ?26
    * [- s9 \/ Y- o" I* L+ b277 n+ R' a2 B! u. c5 c
    28
    ( X  V- A0 z; D& M29* `- D" U& P7 v) q; Y! x
    30
    / X' u' B( [: u9 w8 y' N31
      B( f$ q( a" }32
      P1 X  e7 h/ r3 e- G) |- z9 @336 u( ?" D' p3 I2 b& P8 E' O5 R& J
    34
    / W  }% I# e# x2 T35
    7 ]/ @' V% q: p+ U368 Q3 C. p# ^9 n+ @  T+ \" ?5 A
    37+ T. F& U) E4 R0 C
    389 T" l* J, y+ G+ e  n
    39
    $ K; `3 r* ~8 V1 @405 S3 v* J2 S  K# l$ O1 u
    41# C1 L$ u4 q5 Q1 R0 D9 F/ t1 S
    42% d7 B6 M& B: z" t' `0 A
    43- X' ]$ j6 N' _6 N9 d
    44
    9 `$ U" ]; ~3 z$ f: n/ a45
    3 t* w4 `" ^' s' _, f" O7 \* w归并排序的特性总结:% [! u8 I1 Y- d; N; I

    " }) ]# ?/ `( o4 S$ v( |# d- F. O归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。% H$ `5 d' A) ]* o" F
    时间复杂度:O(N*logN)
    4 h' h( X2 ^6 G( _! v- W空间复杂度:O(N)$ \: C, w2 ]1 W( P( ]. t5 C
    稳定性:稳定' a' i' c, b1 w; |3 p

    4 Y/ k. G" i7 J2 Q5 ^————————————————4 H. S5 ]3 R  n, b
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。% b9 t) }" z6 N6 E
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    " {8 l( c2 A. O9 c% O9 j- O& L3 b. r: U
    , ^+ `4 Y4 F' m; ]
    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-10 01:31 , Processed in 0.402868 second(s), 51 queries .

    回顶部