QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3334|回复: 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 x  o5 E4 [5 m( C& z! J: B
    $ o: o4 a, f! z' @. v前言0 c: F2 X2 @& z4 x- \
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。: s2 S4 R: p1 n2 [9 A

    ( U7 p, i5 \6 e& A  n2 r; W5 j归并排序
    + R& D; G) c3 g/ L" |/ }基本思想
    % @* Q5 ^* k' T$ D" d​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ; R5 {0 ]/ ~5 z9 v8 f) q3 L
    # Q/ I7 a8 L, e! x
    ; ]% a4 |+ M1 @# }' z$ |2 p* r; x
    ​ 合并的思想其实和有道题目的思想如出一辙:
    1 v& o5 [2 B) D1 j
    # O* T" O9 T- Z( S  h4 G3 d, S/ q# e- ?) q$ q, m' B; a
    . T7 p' O& C' c6 ]
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。5 ^6 Q* a. L9 a# ~3 P

    - w! _0 c: z+ q& k9 k( ]) a+ b[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    0 C, J& C5 C+ a7 m
    6 N* _( _" @% ?" Q. H# Y/ Yint* merge(int* nums1, int m, int* nums2, int n)
    4 h- W9 K, H" t2 m8 N1 m{" E( \5 M# u+ [
            int* arr = (int*)malloc((m + n));3 ]$ E5 S; o( X0 \, T# L
        if(arr == NULL)
    ) O( w! t4 Y2 B9 [3 u0 B% T    {
    " L/ c# S# ?, K" b1 N) M        perror("malloc fail");+ `% c' m- ]5 z& J  s# ]/ \& w
            return;) D0 L8 B" p: `1 f, W
        }
    0 N6 y, q, ^" l& B) r: j, ~9 c" G) E' N8 N6 v' @3 i8 l* n! ?
        int p1 = 0;
    / }. B- }* q/ t7 K5 M    int p2 = 0;$ U' W' d0 F4 K
        int cnt = 0;  H) t- o7 t' A6 m& I( _0 u5 D
        while(p1 < m && p2 < n)( x: J- c! r- b0 C
        {- ]9 |- q9 t2 I8 h: f- s3 G+ X
            if(nums1[p1] < nums2[p2]), Q& O  a& _  h: N
            {0 [. I9 r; f! s
                arr[cnt++] = nums1[p1++];( U' q, k5 }1 U1 X$ n) i: t# s
            }
    + J/ ~+ K  M! X/ e! |( S        else
    ' B/ }4 P2 A0 u/ F- H- ^0 Z        {
    8 h, P8 P$ w6 ^8 t            arr[cnt++] = nums2[p2++];
    ( Q6 C# C1 ~4 E) z- }$ K        }- V$ I# I6 ~4 J' f3 L: Q3 ]
        }
    8 \, k7 |3 }% t, a% y0 E) e    while(p1 < m)! S6 L8 |7 M5 c0 r0 u* ]$ z' d
            arr[cnt++] = nums1[p1++];
    % r) J% E6 J  D! N  x9 i7 k. @% A8 \& E& y
        while(p2 < n)' @& |: {6 l3 u1 O' \6 C7 t, G" [
            arr[cnt++] = nums2[p2++];" O$ E  V' j- V+ L

      Z4 b; N; {/ X' |0 _    return arr;  x* x( M/ E5 `2 S1 ]
    }
      X, M9 o7 w7 e, Q
    % }+ N/ I- J( v  X0 g6 C. T/ u1. P; v. p. L. X$ G
    2. k# @. ~, Y7 l  R) v
    3$ d  g9 x  D2 x  Q
    4
    * X7 P0 b* T& o! d  O. u/ s  V55 {+ L* A, L8 R+ _  }. \
    6
    & t, W( Y6 ?+ C0 g7 ?7% J3 ~3 ]7 z  ^: q& D
    8
    % s2 q1 \( d/ y" V3 Q, W& |9
    6 I+ R. z6 w$ {4 v+ l% T10
    2 f, r1 ?/ T, ]11/ |  P4 T" {0 l! R
    125 R. Y; J) ~# O0 n3 B0 M. t& |4 \
    13# j( w( A5 z9 f/ }5 ?
    14
    $ H8 |2 {- |6 l; E% [15& r: T$ P# O) p. T) x  a! y
    16
    ; p* ]( D3 R% T1 K+ ?( d: w17
    5 ?6 ~8 s1 F2 _% b8 O! j4 L18- u3 R) i/ a1 ?) k) L
    19
    2 d. k9 l3 u- N" ~/ t3 I. K20
    - E  ~$ e& U$ z5 k. W21+ j: I7 p+ c" d3 w
    22
    8 `9 X& B7 q! H. E; O- m23
      N5 i* {5 ?7 v$ _8 M" @! M2 z24
    & t" ?3 R8 r% j3 ~25: \! ^! J( D8 H2 `, V/ `
    26& s" q6 n1 {: N
    27
    2 A' w7 Q8 W( [28
    7 i$ [8 W) F5 T0 U+ B! R7 f29; G/ W2 \+ s" s2 @5 [
    30
    ) R# }, A8 W1 j3 ^3 D6 ~/ [31
    3 r" [( ]& k- E1 u​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    3 D' v- q" w; m7 Y: G! F  ~
      p' _! b4 m* w' p  S递归实现
    0 `0 H1 A2 Q- v$ S0 f- c7 {4 s9 H​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。9 I- h# b: z. a9 ~
    % z$ _: D- ?5 @. W2 ?' ]  R$ G

    9 ~, p/ V$ ~- r( i: b( D! J/ P8 `2 Q6 I2 H- K9 r

      N9 N0 Z; Y  A  d2 X4 F  P
    , v4 S) j5 v. a& kvoid _MergeSort(int* arr, int* tmp, int left, int right)4 H) \- I. d' p5 s  U' j
    {
    8 R! m4 Y# ?; `& U* V4 H) C    assert(arr);
    & n) r& o+ q. f9 P9 c+ E
    9 }2 x! W. u6 H- l! G$ D( m    if (left >= right)//递归结束条件不要漏了6 C3 ^7 B, }5 D4 N' S( q
            return;
    9 g( u9 y! M" ~' j, ]  ?  q0 _
    * y8 W6 H* ~& j4 s( S+ l    int mid = (right - left) / 2 + left;
    7 @* S; H8 \8 m, @/ J) B3 f. X# o; W. q7 p4 ?
        //划分左右子区间[left, mid]和[mid + 1, right]' Q) G* D0 E. A' k7 @4 s1 c
        _MergeSort(arr, tmp, left, mid);
    ( n2 r* `! ~- Z) ]( Z. s' u5 Z    _MergeSort(arr, tmp, mid + 1, right);
    + [/ I  R. \: I/ o  T' F4 C% }
        //归并1 R5 n7 A# R' n) I- T/ x5 k/ S
        int begin1 = left, end1 = mid;7 A$ i8 M; r4 _4 E* }# E
        int begin2 = mid + 1, end2 = right;
    . \7 C7 o  N5 j0 ]3 f* W    int i = left;
    5 a2 s, y3 S, g/ z. z7 L8 S7 Z$ B    while (begin1 <= end1 && begin2 <= end2)6 ^3 Z; Q. ?& J4 f+ x7 E& H
        {  A" X) d; m. K/ `9 W
            if (arr[begin1] < arr[begin2])
    + s6 G" @7 f7 E+ d6 n- `) z/ G% g            tmp[i++] = arr[begin1++];4 Q7 u, r( a6 o# S& j/ E$ A
            else
    ) \' S' {7 z0 C) h3 `5 {            tmp[i++] = arr[begin2++];
      d- J& n/ \- N9 L    }2 O: ~: y: C: j  _4 z
    2 N' |$ S* ~5 T. Y  {8 `% H
        while (begin1 <= end1)
    & T3 V1 j4 N2 [. H        tmp[i++] = arr[begin1++];
    8 T* S7 c# H, y* T7 {; x) A    while (begin2 <= end2)# `0 J+ ~# j+ s& ?
            tmp[i++] = arr[begin2++];2 m0 Q2 I: N9 f- Z( C
           
    , A# ?" m: o" o4 O$ |    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ; @3 U9 g) n6 `- Q# I3 D    //而不是拷贝整个数组回去
    . B  l9 Q) m& W/ a9 r9 N0 B: I4 }& {    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    + P$ x' s* G# h/ H1 P9 o3 y}
    ' z7 a, V- X- [6 `, c$ r5 F5 K( |/ L2 Q# p
    void MergeSort(int* arr, int left, int right)
    , F! t2 d% R  A5 n9 `; K9 w{" E% j% @: b+ A8 i; j) ^0 ?7 l
        assert(arr);
    ' x6 w4 m) \( s+ E+ Z) J& U4 @7 b( w. ^
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));" u$ D$ ^+ s. H3 T
        if (tmp == NULL)' G0 Q* K( p5 w/ N2 _/ r
        {! T: p! J; Y$ A0 ~: J$ F' @! x# j
            perror("malloc fail");
    ' l1 f3 m, K" ]        return;
    6 O! m2 H4 ?! G0 {; t    }, I, g6 E: N/ S2 t! A

    $ \' @" p* I+ T- X' ?; L' X    _MergeSort(arr, tmp, left, right);& I6 w* I0 D/ E" h" x: ?

    1 U5 ^! j- U, `( |    free(tmp);  H% E9 l& Y5 _. r4 W0 W
        tmp = NULL;
    * `" a! X9 ?% q; v4 l* @* P" _}8 n2 m9 j! p, |3 H  K! U

    , w( B! z: N( ?# @1" q, S7 s& b6 Z9 R
    23 u1 e! m* ]/ J
    3/ ^2 l& G9 h! t0 H5 s) j
    4
    . p& u8 B4 B# y9 \! ^5$ W. P3 b) A/ S8 ^% q- C$ h" l
    6
    $ P2 }$ {0 x  H0 h9 q6 f7
    3 A& O, V% E3 j5 `# A3 S0 m8$ v0 {' z  [& W% J
    9/ X: W9 w5 ^% y+ t  K' X
    10: b( ]1 A9 S7 j1 R) {% \- g/ h& Z4 ^
    111 J1 c; k  @/ @3 f3 y" V
    12
    3 c; v7 M7 B$ R, n$ m. o6 f3 z0 s13
    2 R2 Z7 |# Y. W" X7 Q# |2 {# J14
    ; Q& j3 x* e# Q- c6 O8 I3 l% H! F154 }% Z( p$ v0 V" N2 v/ x
    167 ]! [5 D+ |! ?" B+ |
    17
    $ s3 U3 B! w* x) D+ q' J# l9 ~18
    % C9 V! |/ T0 ^/ \* P& T7 i19
    , V4 T& M! V" N) F/ b5 B+ }20
    2 l0 T8 E- }, q) m, r21- c5 J- S; `5 u& m0 ]
    22# ~+ ^* l* n" u: m
    23
    ) d9 c% B' s( ]9 \0 E8 t" v248 [# M0 p9 z( A+ @0 B
    25
    ' ]* A8 a+ V' h4 _26
    " I+ w6 ?  M1 X& e9 n27
    # s% U3 C2 B2 @286 [1 c/ B0 Y7 Y' |/ c& D( U4 Y
    29
    5 O9 p! j; [2 b" n30
    ! O; a7 j6 y: R31
    ( Y0 q" k, m& B. `6 F1 p" h. Q" w! R" y! P32
      {4 S% B+ W& j% ~& L) K33
    7 C0 Z* Z. q& e, l$ ]6 M: f341 ?* y: r. }; e* M. d+ a
    35
    8 [: a0 z: k: `  c/ Z* x6 b36  N( I) e6 s+ h7 b5 `7 p! Z
    37
    8 w. f1 b+ d" P2 E+ E38
    ( C: U% ?" t6 @! r" d" u, p/ d39! M8 d" C: R$ ^8 J) O
    40
    0 B6 z0 N" g% @41. x/ @$ p1 Y% s, k7 s+ D
    42
    ) e& t2 C) \! F/ @43
    ; D+ [1 J: Z7 e4 f2 Q# v44
    $ K# Y  C9 n+ U3 m0 A% M45
    - s7 z) Y$ I- m; x( i0 U; R. S3 J* s46. J8 q# l# ^* s, a' w
    471 P' l# [! G' w6 Z, m& ]9 q4 n
    48
    & t) o. [7 t+ \  _- _0 ]( u6 I% y5 I+ h: H490 _& ~* }2 T' Q7 w4 O) z0 u
    50
    $ \1 Y) r9 k$ c* q512 F8 d% y+ U' M! R3 ?
    非递归实现
    ; s$ Y+ a& ~# A. s​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。2 c( c! u" u3 c% ^6 _

    # r" Q6 k8 T% |# F* U( F1 C) D, A$ B# o% Z7 e# n% ?' \
    & N; N' x0 N0 j! ?7 L1 A
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    ) Q/ W  H, O- g. g' `$ O5 d9 p2 G- V/ f& K" p$ K3 s( i1 V
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    3 w( V& G# k$ N7 X3 Z; X! ~
      q; T7 y0 j8 I4 c5 _- ?( f$ Q; z​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    ; K% b/ p" Z# t! B4 n0 K. |) h# d! K# Z3 U* |7 \, ^' U/ p- A4 b
    代码实现
    ) P+ b7 c% j" Z/ J, e. v! |5 B" c1 P% K% e1 e
    void MergeSortNonR(int* arr, int sz)
    0 |. t8 G7 X0 x' U/ H/ f, t{
    - J1 i2 \( l! g& a+ D+ ?    assert(arr);
    7 n4 I1 I; N9 ]
    ( l) O7 g+ r- P9 A3 h    int* tmp = (int*)malloc(sz * sizeof(int));
    ( i* l' Y& S( A, e    if (tmp == NULL)
    3 m8 c7 n3 B1 ?, }8 i    {; \2 k4 _3 W: i: r/ w
            perror("malloc fail");
    , ]' |" _& I4 U* W% v; R/ P        return;
    " `  `- f0 U9 j% N8 K    }
    / \% i3 y4 m: ?. h: }
    $ B3 k; B$ D! t: y1 X& k    int gap = 1;
    6 h$ G8 c: W6 b% f* D    while (gap < sz)) p) ]" m$ p& u
        {5 C8 D& m. j# b. a( n5 w/ f- ]
            for (int i = 0; i < sz; i += 2 * gap)1 |6 D+ ]6 E2 k  B4 a' C3 E- r
            {
    6 F0 ?% Z- x" S% l) H, l) L            int begin1 = i, end1 = begin1 + gap - 1;* }; P9 y; A$ N5 J7 R. M
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    % @) D4 \& h2 \0 n            int j = begin1;( A/ ^3 d& K: s) B- E6 M
    " l7 H1 X2 B" N# W
                //归并
    - P7 I' H0 s. F2 a5 |            while (begin1 <= end1 && begin2 <= end2)6 G9 F# Y$ A) I
                {
    " q' b- {6 [  I4 z! ]3 X$ T                if (arr[begin1] < arr[begin2])
    , o( U) [7 G1 g' H                    tmp[j++] = arr[begin1++];
    / ~' E/ Q# Z+ M9 d% u                else     
    % H9 h0 A$ F( M' X2 a                    tmp[j++] = arr[begin2++];
    - b+ }- p" ]4 n+ W4 R3 A            }
    # M, p5 a! Z+ ~* n
    ! I- N1 k( u" y8 o) @' R4 D7 ^3 i            while (begin1 <= end1)+ _, j: w( j2 e3 d# U6 ^! g8 x2 j
                    tmp[j++] = arr[begin1++];/ |4 r  F9 }% F1 T' {
                while (begin2 <= end2)  S% [3 [, d3 j: w
                    tmp[j++] = arr[begin2++];
    , J/ J: P, `# ~( |! L& b
    / z  g3 E4 e& I) t/ j- r: ?            //拷贝回原数组——归并哪部分就拷贝哪部分回去! ^) i1 x  O) w2 r$ f
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));% u/ f& y/ l8 o
            }
    1 K: K5 p9 e" d0 G        gap *= 2;
    ( W2 \8 }( s) t( ], R8 f3 z4 M7 M; @    }  U  E+ |. q* K( a' h

    " I' q, K# O% |5 H  `( m5 Z}; [8 ~: ?$ x. ]
    : M% s9 g- Y2 Z/ k) b1 [
    1
    - p5 T4 }3 C$ I5 L2
    5 `& f! l' B8 X" e33 I5 ?, @3 F6 k8 \2 m, ^4 ^, B
    4; e4 e) I+ V3 b" B+ `
    5
    " ~/ {- O5 }4 Q7 b+ h) P6
    4 c3 p$ ~: h- W  I# j7
    . Z6 J6 w* V; W& ~8
    0 ]4 H( m* l5 w$ |9) ?8 a$ g7 t3 @7 r& T( O+ c
    10
    & P3 c! T- t3 ?  A& N% A! q11
    0 e$ n8 W5 G' J5 F+ X: S2 k12& K, {2 |6 P9 _# l4 u7 Q, n, y
    13) c0 f% R; u8 X& ^3 j8 H
    141 d- A- U7 b* Q: ~# O" d5 c; b" L
    15
    ; t+ `9 Y1 p( F7 ?! p16/ Y6 q/ e8 [* k
    17; n/ V; e9 M* r- ?
    18
    ) Z* w! O: U4 `  M1 v$ _2 Q192 I4 ~8 h+ V$ @/ y6 \: e
    20' j+ E+ `) J7 _+ G
    21
    4 r6 G6 S( A/ ?7 w5 G" T$ i  q$ _22
    ) r' O6 h0 R3 M0 U* n23' r8 s9 @+ n5 \- }
    249 x* B# w7 b) I6 L1 c, G
    25: L+ z% R, x& f) L# L
    26
    , G: s# u5 F% E& q$ ]. I; M27
    4 ]: n- s' e8 J& e% V" I" l) T28
    / X: x& i8 P& S& G29
    , ~  H9 P5 j& ]7 g30' t  m$ G& `# Z6 G/ k* k
    31
    ) w; u- G) e* b( q% }* U' t32; O& n' x7 m. |5 v
    33
    ( L  P% {1 _# @' Y34
    ! v2 n3 ?( N0 a5 j7 P350 w2 H2 U/ `# V- Z7 D, t8 R& S
    36( @+ O" @8 ]5 m' E
    37
    , C5 a( X2 r; J3 ^38
    0 V1 L6 T# o, t0 j* O6 X39
    ! Y3 h$ k3 j( }1 Z+ F40: y: K5 r( ?, X
    41
    0 [: R% R, V, m5 j& H4 [边界问题
    $ n; x( F. t$ j! K​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。' `# A& H1 F9 J

    - t* S, U5 o6 L! K举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    + i, r2 q) \3 d3 q" }8 x# d0 i0 ~8 [
    # \7 @' J: j6 y1 H5 q! @

    9 C8 F! P$ ~3 l) p由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    , Q1 P9 Z: t( [; g% w# P! ~
    6 F+ m! E% M; N! P! x( y第一组越界(即end1越界)0 g% |4 J) Y7 q& [0 |" @# a

    5 z& F4 T& Q* R; X' n, e应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。; l. Z) G2 r. M3 n- r0 o

    9 g* ~0 }9 G6 Y3 O; j& N; \6 n第二组全部越界(即begin2和end2越界)
    . V! n8 ?, G: `3 Y- s' f# _; f/ Y1 e% e% U% `
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。" u) x) i' p2 V; z4 H5 k8 Z
    # e8 g# b& |! w! S+ U7 \. R) x- L
    第二组部分越界(即end2越界)0 }/ ?/ q- w3 B0 p

    , l5 F) ^( d! ^0 N) l" ?+ J5 l: Z+ T应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    9 s6 C, h6 z& P2 B) s; P/ ]3 p. Y' h" C1 y
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:2 F" ^+ ~, M/ N. l! c3 P2 W
    / B: ]' Y3 M& r, Z
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。4 K2 ]( |% Y7 L
    8 V& h) ]" C5 Z  R: z" l" @3 k
    ​ 拿两个数组试一下:
    3 w7 t# `& o$ f
    ) b) \( q5 `# N
    . u: g! r$ }4 l* J( q$ Q
    , N  Q, r- H+ w' P
    , ^0 ]1 c7 N% E: r/ `: D6 K- u4 P: A( K5 Y4 c
    代码实现3 c! Z. u% p& M% I( Q! R& {( P
    ; W, @& @% |' F8 ]
    void MergeSortNonR(int* arr, int sz)( \/ j' d/ S2 K& ]. v" C
    {- H7 g$ h3 ]8 P* `: L! K
        assert(arr);' f6 W: `  p( P

    1 X- [1 x8 O5 W8 R4 w% r    int* tmp = (int*)malloc(sz * sizeof(int));6 U3 k6 A7 F5 i
        if (tmp == NULL)
    7 C- O# R6 _2 q1 Z8 e+ A& x( ?" ?    {
    4 H3 t4 `& b9 O        perror("malloc fail");  P0 @4 S+ O$ a2 |2 s& @; k( ]
            return;
    6 F% H# Q$ y0 P( h0 d    }
    5 L6 }! g" W, g0 ]( ~  d- G
    ( u- N/ G' i5 z+ q3 U    int gap = 1;
    4 M* ?7 T. a" p7 d    while (gap < sz)3 y' U  P) Z' k: U/ H4 c
        {
    / Q4 z& U1 e' N' S9 K' k4 S        for (int i = 0; i < sz; i += 2 * gap)
    - E5 H- M/ o$ b( @, E        {
    . q1 I/ ^8 m2 f/ U" e; J# I/ m            int begin1 = i, end1 = begin1 + gap - 1;
    7 S+ |7 x1 n7 o9 g- b, ]0 e# i            int begin2 = end1 + 1, end2 = begin2 + gap - 1;7 `( E0 g7 r2 i" R
                int j = begin1;! [' f3 R! d) ^& ]* Y" f
                            //越界检测
    / P" m1 C, e3 w            if (begin2 >= sz && end2 >= sz)
    8 C0 }+ A+ T2 q, l( J* k                break;
    2 v- Q7 z1 q! u' H* F            if (end2 >= sz)$ H) _- A/ I$ z5 f
                    end2 = sz - 1;, \7 \7 r5 b( I  f6 G
                //归并
    2 G# a* p, S0 l+ [% h( B7 q            while (begin1 <= end1 && begin2 <= end2)2 K! k8 E/ u) X4 J5 E
                {7 w1 n3 n5 I  V" h1 [
                    if (arr[begin1] < arr[begin2])4 c) ^# V* e7 U; I9 j7 E* r
                        tmp[j++] = arr[begin1++];, Q7 @8 Z6 H7 I- a; y
                    else     
    4 Q% b1 c2 t6 i6 ^% r                    tmp[j++] = arr[begin2++];! Y" u0 }+ }! R( ~% W
                }
    - Q" d, w& |2 \+ J! l+ ?. k
    # H% D0 T) y" `2 C2 v            while (begin1 <= end1)7 k1 X' i# ^0 U# i" x, G
                    tmp[j++] = arr[begin1++];$ _) Y! e" [. x9 D
                while (begin2 <= end2)
    2 p$ J5 o& v  b9 c$ F" |6 Z                tmp[j++] = arr[begin2++];8 h$ D8 e6 y; \# \- k5 x

    + x& O' ~0 R$ J+ Q            //拷贝回原数组——归并哪部分就拷贝哪部分回去; ?0 q4 n8 S+ C/ \8 K0 Q$ |3 L
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));' }( t8 Q# O" q, l  \; H
            }# c* u7 ?: _9 v+ p2 H5 P. B
            gap *= 2;
    6 l: m8 e' U$ n9 g$ i) }; Z    }
    3 i& c* K. p5 q9 f# C7 C, q
    4 X, U' u3 S$ b# R  w0 f}
      V: _. ]  f0 X  k" x. P: K
    : W/ m+ ]6 m6 ?1
    0 Y6 I3 |  o9 K) _# j2
    # W! x: [% n6 }( {2 e3
    ) ^5 M! I2 F2 g, i+ ?, @49 ~5 z) [' a& E* |' E. v
    5
    ; q! R: n! N9 x7 Y) V7 w# @( q6& T2 R$ E; r8 B, K. Y
    71 A! r+ q# E! @7 y- x5 {
    8; N5 C, N1 v9 O& n
    9
    ! |' n1 B4 G4 d3 X10# w; l) v0 M1 h! V7 ?! H/ m; T
    11
    0 i$ ^8 C$ B1 a12
    - [; O5 Y" ?9 @( ]. H- S5 K2 p+ `- T13
    9 g7 p1 r, g/ C' K$ i144 M- W- Z4 A: a5 e
    15+ v& p/ s9 d$ T- p6 j
    16
    & g% k- s3 ~% [" p17
    ' B# A% t* I: k; h18
    9 o' P! ]$ _5 j8 B19
    # t+ M6 J) v' H5 ^209 W  I5 {- j9 s0 e
    211 W- S# x( h& S; G' Z
    22
    + v4 R9 Q: x4 z6 H3 G237 V2 r( N1 t% F- k0 ~
    24+ d0 V6 A- }: d) ~8 r1 ]
    25* d5 Y' U  Z) _6 c
    26
    5 _; ~* p2 N3 \# ?% S3 B$ a7 S: b273 G9 m; y3 R/ Z9 {/ T* Q  \% [/ S
    28
    6 F& U* q1 L* t/ V29
    / i3 a3 k, E5 b1 l8 _2 j" o! m30
    ) B5 F. f  s* f, n1 _- _313 `4 [" E& f' t* @& K& A$ a, ~
    32
    ( }" _$ c$ R  @7 W( A+ B  G33% i$ C# m* k" \* @& R
    34+ k7 u/ O0 W# K, T- g
    35
    / a( G: F1 l2 b! ~- q9 O8 M# S: U36, P% y9 K3 y  }: Q( z. p* o0 u
    37/ b0 g/ I  ~$ n3 P
    38
    ! r4 _! i8 e* e5 M0 j# C0 T6 F39
    2 ^1 d0 E" s, E/ @40$ X+ @( j# f$ d! k8 I$ ?
    41. O( i7 G6 M: M' R
    42
    ) S7 C( R' x3 }4 N. @+ a: Z( G+ S439 f; K, T' b% @9 n
    44& \* g: q8 [/ y# S
    45; A. x3 L" F' j
    归并排序的特性总结:" M" e5 K6 D/ t

    / Q, w0 F8 g7 u  c) c归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。5 G* G# z  U* g
    时间复杂度:O(N*logN)5 d2 Q  K8 }2 O( W2 B8 r+ Z8 x: ?
    空间复杂度:O(N)
    6 i1 P7 i0 @6 E' j稳定性:稳定, b5 t1 [- w0 T9 M1 l( [

    " J* R  L- C  g8 F+ s————————————————! B' R* K9 [/ u' ?
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& B! u/ \! @/ O9 ]) b+ i: G& s
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    0 a  L1 ?9 a& {1 ^2 N6 N. F8 @+ R4 }2 ~/ p

    / q: n2 J: y- p* `5 ?8 V2 l4 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-8-24 03:39 , Processed in 0.337507 second(s), 51 queries .

    回顶部