QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3393|回复: 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的排序算法】归并排序" h& v& |, }' Z3 {% `2 [% N- |( c

    " z6 s- f, k8 S! b3 M  F前言% j  G: }+ w3 x6 [+ ^
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    * i) s  D& k& n4 q, v* v" F' y/ p" [  n
    归并排序6 D9 L0 ]! m) [) w
    基本思想
    + G( R3 _4 ~+ @. Z* c​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。% _- I& {6 g$ @& @3 @" L8 B4 W

    ( r' |/ @; K" C! o' g0 J$ ^5 w/ I3 M* _& U2 R) g' {5 B

    # Q3 [7 W3 l# e' ^& ]​ 合并的思想其实和有道题目的思想如出一辙:
      v8 L  ]* L! o( Q
    " U1 l1 R9 V! A; d7 z
    9 h# I, C5 Y. \+ g
    1 r9 X" k2 ]- x" u​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    ! q, ?4 L. a( v7 h, U0 L2 {
    ( j7 s$ Y+ i8 b( {[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    $ w1 M1 k) d$ d( p$ c- P; ?. Q. G
    # |( @5 `. U3 |) @8 Kint* merge(int* nums1, int m, int* nums2, int n)( y* @; H( Q  R' H( N2 Q
    {' D* f" l* h4 P/ c) W  R, o
            int* arr = (int*)malloc((m + n));
    0 _) M1 A9 D( c8 r* }3 H    if(arr == NULL)+ f- G% i. o3 a, u: s3 j
        {
    + L/ `. r/ |5 `0 ~4 Y- B( O, z' S        perror("malloc fail");
    8 ~6 k, l& h- Y& O! k+ g/ e% M: p; A        return;
    # Z1 N: e/ d6 R4 y1 z    }) M2 Z) g& o. O1 D* d0 d
    % L% d9 P% r7 \+ R% L( K$ o
        int p1 = 0;
    + u7 ^! u. ~/ h3 L6 P8 l* s# m    int p2 = 0;
    + U, U( U8 r& q2 @9 b2 j4 _    int cnt = 0;) p0 h( a2 U  f
        while(p1 < m && p2 < n): ~5 l! @& M/ c' o
        {
    - o  \1 [; \6 a$ Q& L        if(nums1[p1] < nums2[p2])* M% Q8 h7 G/ M8 K3 R1 C5 C
            {
    / @; X8 b% _: y( ^            arr[cnt++] = nums1[p1++];) p3 N# }" `5 Z- `
            }) t8 @0 h/ T9 q2 ?% `
            else' Y- E' `$ g( A( j0 G7 K
            {
    ) e, d3 g. Q9 y+ N5 N            arr[cnt++] = nums2[p2++];
      w1 N8 |! k2 {8 I: `3 D        }
    1 M6 k$ F& f; P& c9 J$ K6 P    }2 }( |5 q- g5 V5 f
        while(p1 < m)& b) s- Y! [5 w/ t' f. `
            arr[cnt++] = nums1[p1++];+ F3 U, G( z/ z

    ! H6 o- W- @! ]- n    while(p2 < n)
    # X" r! X+ N) ~% N1 g        arr[cnt++] = nums2[p2++];4 @: `# ^2 @3 ^! O* p$ J
    : @  T3 I6 z; a# @7 `& v
        return arr;( [0 S5 a( A: F4 [( }' \5 _' B
    }: Q/ N  f5 j$ g4 u

    & ?9 F0 O" {* L) i; t1( M: V: _: j' }, q6 ~% t1 [3 v) w
    2
    & n: x& R2 [! T; l0 a" ]3) ?$ t0 Q. `! c9 B! Z/ r8 w
    4
    # F6 X7 D# q: a; \& P. E5
    8 O3 Z! f$ o6 Z; S64 e* y0 X# r. b
    7$ ^, b6 }! e) V  j( j1 Q) e8 |
    8
    - F5 T* s; C: G& k- d9
    . w; K, D5 G4 F, ~3 Z3 F10
    * |1 T# v4 Z" j: y4 k11
    . V0 V1 }* U8 ]% l. P& I1 L12
    8 K9 F0 Q6 f7 R8 {, S% R6 t13
    : B+ l8 |8 K9 ~% e* ]$ a4 d6 y+ _14* Q0 x% S' U! d, B0 |9 a
    15
    , _* k# e& p' ]! u+ j8 o2 B16, M' J1 E# h- l: L3 C  ~& S
    173 R) R1 ~! q4 ?# [* J9 v/ ~
    18
    0 F% _1 M- M9 n8 r& x' |19( [. z% ~1 U) e6 \! e
    200 [6 l7 q) O3 i9 ^% l* n
    21* {: A/ N8 p9 Y3 t& {/ J
    22
    7 C, }! ?& u3 B3 ]3 R' |23; ~, ?/ f% ~/ _% k$ t" ?2 V
    24
    ' ]6 a6 ]7 F! k8 h6 A* P8 Z25
    4 X, F8 K) f1 r: n26
    + j& ~, _. R9 p9 H' r- ?/ j. q270 ^% v) l* O! Y2 l1 i
    289 o  w1 s, D% M# k* u
    29' t3 s& |  y* c7 e
    30% W: t5 [* Q) W8 N2 O. O% E
    31
    0 G7 A& c( b8 s5 T, C​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    ; I  w* X+ Y6 ]
    ; K7 \6 N! X, X递归实现
    / [9 n/ }3 N0 l​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    . ~( r# ?$ P) X( N9 A5 x& u4 |! [& q+ S* t6 E
    ( t7 o% y- a2 A  Q! v, t

    ; E6 ?7 l: x" _) i/ @
    5 F6 N& i8 m% L0 Y. x" ~6 }8 H8 }0 l% ]
    void _MergeSort(int* arr, int* tmp, int left, int right)  ]$ D3 J( i( e) W
    {
      `3 s% N! s' H2 u. n& r    assert(arr);3 W# n+ m0 E# Q2 B

    ( E9 Z! n0 }/ g. L4 X9 k# L5 R    if (left >= right)//递归结束条件不要漏了) Q* W2 B3 o& Y' g0 c0 m
            return;
    ( Y1 K0 t! {5 a0 o, T3 I
    % ~( I8 x' L) m# e    int mid = (right - left) / 2 + left;$ k6 V" a! S* U% Y* u1 \$ L
    ; g. F9 e' u! C! v
        //划分左右子区间[left, mid]和[mid + 1, right]
    5 \* C  G% A- R2 V2 p    _MergeSort(arr, tmp, left, mid);
    / R  L- X& Y* W$ Q1 [4 F0 \( @5 ~    _MergeSort(arr, tmp, mid + 1, right);
    ( |$ b; Z$ b& Z/ y" a) c% r' N# D% P% r* ^$ L3 A! l. B
        //归并' G" L5 H) y0 ^/ C0 v$ Y
        int begin1 = left, end1 = mid;
    6 y" ~* X! v! ~- {$ R/ G: o    int begin2 = mid + 1, end2 = right;" d# _. q4 h) J3 W/ n$ r# @. m6 C
        int i = left;
    ' ]( P" _! m% F    while (begin1 <= end1 && begin2 <= end2)( I  t7 l% Y/ L$ K
        {& H) n$ e/ c) ~
            if (arr[begin1] < arr[begin2])4 h; `: ~0 y: @
                tmp[i++] = arr[begin1++];7 K1 t2 l; Q, U% [: _9 C
            else9 C9 ?. Y) U; L5 y8 d2 o" d# B# v
                tmp[i++] = arr[begin2++];" C+ {* _! k% L  I2 H
        }
    / T# T( K$ l2 T5 v
    ) f' |4 d$ Z4 ~    while (begin1 <= end1)8 Z) a; i; q& v% f: F: l! N
            tmp[i++] = arr[begin1++];
    & e, g% V" m( c/ [    while (begin2 <= end2)& }: k( ~( G! E+ p4 {
            tmp[i++] = arr[begin2++];
    ' j& f( F4 U9 i  O+ n: I! D        % J3 ?4 _! u: \; |& q5 v' _- c
        //拷贝回原数组——归并哪部分就拷贝哪部分回去* Z; f3 C) o  f2 N/ B8 o
        //而不是拷贝整个数组回去
    ' y# W4 _) }4 m! p; R* L    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    # R4 m2 M. Z) }}' |0 R! W2 j6 w  c- V- @* g  C% R
    1 k3 j  e- i8 _: Q
    void MergeSort(int* arr, int left, int right)8 c+ t' S) {6 L1 C7 \3 m( S2 j- e
    {/ G" F9 b- q% o( X& x' |
        assert(arr);
    6 g, \# ]4 A$ O; v( }: A
    / E) H7 [$ m3 {: G: B2 p4 s5 v1 y- u( c    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    * j5 Z/ z- Q# l5 p1 y    if (tmp == NULL). a7 ^- b/ P8 v
        {7 H( L1 X: v3 y: K1 E9 }
            perror("malloc fail");/ p+ M  J- r8 B2 \5 f0 ~# G" v
            return;! N+ T. y8 O. z
        }
    , K1 t. J! Q7 B8 W: B3 t3 M: v9 |' G2 e  d0 B6 n- `
        _MergeSort(arr, tmp, left, right);! L9 [- T5 A- p7 @  [  ^; b, A2 a

    - P2 J4 ]7 H/ R3 j$ k- g    free(tmp);
    " i& `' W2 b3 W$ M4 _1 d2 ]0 ^2 q    tmp = NULL;' T* f$ G" ?! C, }( b0 h4 C
    }" s# U# ~! {/ A! [

    ' N- k! S4 W- R1 w1+ s( t  U. H' m6 G7 \) @
    2
    4 f  `7 w" c* T/ h0 v, |( D30 `6 \5 `1 D+ M, F$ u
    4
    % p5 v! r8 p4 j9 c' Q5, ?  z. V# I1 V) o! I. N; {  D
    6
    / v: Q7 |+ B! h1 c7
    - W4 z" D! U0 Y- @9 M  {8
    6 Y0 K" U4 s8 g* \9
    $ O( k, o! ]' P; T* F10
    9 r+ U& e- `# w11
    + s8 ]2 F; G5 y4 P7 q) `9 t12
    % {4 b8 Y/ A7 e13
    : F2 q: L- |# {; r' P14" M2 A0 _8 y0 z9 ]8 G9 D
    15
    # v+ N3 ~: }" R16  e. v; h8 A0 {/ F! ~2 w
    17, k3 d5 u3 C/ A8 G
    18
      B5 S  E1 _* ~' W3 Q; i8 V19+ [+ q6 N8 t: W8 i7 H4 i) R6 P
    20
    5 X: D( Z2 M' I3 b! X! i& r9 }, |21# D  Q- w/ W# K6 @! l$ K  A
    22
    $ ~3 b5 f$ N0 U' l! F23
    " G) g1 j8 S7 Q24! o* R. u" w; B
    25! A  f, b( D# q; p+ _
    26% U# f- N) ^$ S, ?9 @0 w- k& B$ u
    27
    5 J2 Y1 E* X" m8 ~3 p, R. P/ @0 I28& ^9 z; K& ^) P
    299 _( N2 p( W1 H; A# {
    30
    4 t  D+ J' K' o$ a# E31
    ' u. q/ i! Z' k) E+ j  U: w. T6 p32
    7 r! f- g1 Y8 T) T3 [6 R! ^33
    9 Q6 W/ _3 x9 O% ~  H6 ?34
    9 \: y& Z( a+ K  Z) p35
    % a1 J, m) N% w  }* \36  p; L1 i" `! |3 k3 _- m- v
    37
    0 ]8 a2 k1 R1 `38" I- F6 _4 J  f
    39
    . p; c/ U1 R) J7 b4 e* H402 \+ d: n) ?7 L/ B8 G: j. ]
    41
    % M0 x3 a1 h7 I" S7 p; T424 s7 \; X& _: J0 r/ `+ V# g( j5 ?, G
    43* V- n: g! s: t3 ~. r8 D
    44
    ! M  T; }. B( P& B45
    3 e4 J2 R3 l% E8 h1 ^462 a4 ~& m! Q8 }5 y1 i$ ]/ D; g5 t
    47
    3 e3 b1 r5 Y6 D* S" J48
    - w, D) q) Z1 C: }% ~# j: T49: `- ]( A9 p7 [, l
    50
    4 u! U) s& H2 w' z; ^. W6 Q/ L' Z512 J: T' U1 u7 P* z, ~
    非递归实现: P  ?8 `* T. x" b! G
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    $ M! D% P) U! Y! [( V* f  N. @( `& b
    + b; p7 j& y  N, |( a9 _
    ' k) z+ V+ H* w, K6 ~6 Y/ h+ M5 e3 o! t) D9 U  I& |4 B
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。* x1 O& X  ]5 b4 J9 M/ }" W2 ?
    6 [! x1 F) x) T& Z& I
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。+ o) S) n* ^4 [

    0 S( M- {) ~5 M' s# s- W6 Q; n% H​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。  E! u5 K) A5 t. g
    6 Q8 q, e. c9 v/ c$ j; |1 U* C
    代码实现, ^, B3 U1 j1 u2 l3 T* l

    8 h2 h& I+ f0 [: m; l0 V% v9 dvoid MergeSortNonR(int* arr, int sz)
    & M% v' ^7 Y. C3 c0 j/ J{% [2 }" u  y8 C. `. v7 U% \
        assert(arr);
    4 Y) u/ j+ D% |: p% N6 x  V$ Q( b% t$ w7 ]; t5 I+ f3 ^8 ~( g
        int* tmp = (int*)malloc(sz * sizeof(int));$ M3 f2 p! [8 q  k, a" B% }7 Q
        if (tmp == NULL)
    8 o* T  l. f0 p5 b5 H- \    {
    6 h. n1 x  l, a1 z; A$ V: Q        perror("malloc fail");
    0 x/ ]' j1 N1 [; P. T+ C+ G6 B        return;
    ! C" A8 t2 h7 ?    }
    . S$ \' h# T6 v( C
    . _. d* ~# V- q3 g, b3 r    int gap = 1;! j6 c' Z9 U+ h8 [$ r$ P
        while (gap < sz)
    / r* L& O' `$ F; q% v- l- @/ Q    {; ]+ U5 j* I" T" Z
            for (int i = 0; i < sz; i += 2 * gap)7 Q; Z9 k+ d# R) I+ O+ Z
            {
    $ O; V8 E! E! z/ v            int begin1 = i, end1 = begin1 + gap - 1;
    : y3 e0 d- T3 b5 [( @            int begin2 = end1 + 1, end2 = begin2 + gap - 1;# r% R2 A# w* b9 u
                int j = begin1;
    + t6 [; f, m6 N3 T/ v% _- M( b$ u' \6 h7 `0 k, V9 e
                //归并
    3 N+ C1 l3 o, r" K( D            while (begin1 <= end1 && begin2 <= end2)
    0 y9 }  K( {( I+ z            {4 O) p0 b+ ^4 d. }
                    if (arr[begin1] < arr[begin2])
    5 c& D* d) [- c$ v8 M6 _                    tmp[j++] = arr[begin1++];
    * r: X% t7 X5 U1 _. G                else     
    ; N3 H6 \) D: f& t  r% s6 H                    tmp[j++] = arr[begin2++];5 x' k- ]. x. E% E7 {: w! x8 z
                }
    & }: J  [2 K' ^! A' k$ x3 h
    9 R2 D; ]8 S7 i1 B# E+ \            while (begin1 <= end1)7 T, S, E. }! u/ M9 g% Z
                    tmp[j++] = arr[begin1++];7 ~. ^" B3 m: V
                while (begin2 <= end2)' e$ G& x; A- z& H& L
                    tmp[j++] = arr[begin2++];( K; d- L1 h0 Y
    * H: ]1 v( }; [* H- i0 w& S- R
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    4 f: M7 S7 `4 V' d6 q" Z# N            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));3 ]. }3 G- w, `: W5 s7 E
            }
    1 O/ h9 @+ H. m5 w$ o& e        gap *= 2;( B# \7 m. o2 ]% u" K
        }% Z' v& l7 z3 P1 K
    ; @8 L/ E; z4 \9 V4 @4 x: D8 M
    }1 d" P! Z1 b+ a
    - A4 G, |! a' t$ [
    1  k9 m6 O+ B! [6 ^9 n
    2* [+ b: s. M0 R
    3! C7 h  a$ r( n# B* E, U) b
    45 \0 @& k. J: n; ?8 D$ u/ J
    5
    : p& v( q% t5 U: q1 v% j6; v' w& L/ ]5 g; P
    7
    3 X6 e! P' z- r- P  v0 @8' ^1 z2 K: Z0 x6 i+ @0 U8 ^
    9
    6 c  K3 o+ I6 X. e' M+ x0 W105 Z) ?& i+ L8 [7 [4 k1 d8 L3 m
    11
    5 P( d7 v. r' s; u12
    $ Z$ K! D% }# F1 z7 A' ?. h13
    - k9 T5 l4 H2 r5 J5 X1 v9 P14
    . R/ n# v' z: @6 A15' d+ N5 H2 ~4 h6 i1 Y0 ~
    16, K9 X/ w8 N: m5 j
    17( R+ d, \1 z  R9 |+ }
    18+ H/ ~3 D/ X1 d  o" \7 y
    19
    ; V+ D- x  d' T( I204 F5 Y/ Y$ N. E  b
    215 d' O! q! v2 o5 f- u' l
    224 P/ p) H4 N) R' v( c% z/ A
    23& y% n' n0 p5 j& o6 |
    243 ^6 r4 L2 u) N& y; l9 G( V. ]
    259 G4 s' n* g2 R
    26- b) v( D4 A6 `" Q
    27
    ; ?4 h" P! q' k1 s) ?$ ?- U28+ R, H1 R* [7 ?, B( o* g' k# {0 J
    29) u% g, S+ o' ~2 Q6 Q8 u
    30
    ; M: q/ n; l- P$ V. w- c  I. e& w31, ~& s; h8 r- f/ J
    32
    5 e. O8 B" P  _/ `1 J/ G, `33
    8 F! u3 L8 K0 [: I1 K: Q34; v. j; N9 J/ ?: t7 _5 R
    35
    ) P: f1 ^  X# m+ N8 r7 j36
    9 J# @  P/ m# m9 c37
    $ B, a4 S; H1 h& C) q38
    ; f5 ~1 g+ f( o! m& c39* r) o3 k! G* y% j& \% }
    40
    5 Y# b% {. Z/ w& d+ q% M- p41
    * e; Z3 D& a4 r3 S! f6 A) J! [; A边界问题" ^- P1 c  f+ _" n9 s
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。! V6 M% Q1 O+ ~* d: v; F1 b
    # R* r' N* @* w0 J" t& w
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    % H/ C/ y( _5 Y: i! }
    - U$ O1 L: W: J1 i' |
    ) ^$ X: ]$ e7 I- y
    ( y/ h4 [) c4 q; a由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组). q" A& s9 u6 l0 f
    ' i; q, o/ |/ P4 t( K
    第一组越界(即end1越界): y2 C1 A5 T4 ]! m. ^1 R
    / H! C- Z/ _' b: D% X
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    # o' @% H% W! f3 E+ h( i+ R
    1 k" ?1 @: U( i5 c: ^0 g& E第二组全部越界(即begin2和end2越界)9 r2 a  U' o5 T2 ]- _
    0 {4 J; O7 }. d* m
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。( ^( s0 j; F! b* G6 L+ X& ^+ @
    * G2 @# e& W/ }1 i
    第二组部分越界(即end2越界)
    3 I& V& A# F3 Y. s/ f2 ?4 I
    5 u: `* e9 I6 l8 ^  w( Z. Q  k应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。  I# E" N! E( G- I3 {3 r+ U
    + i! n8 L* s5 I8 J% H
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:" o, D5 o0 E& \

    ) @4 l& t, s! v- W" ]) i- }​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。* e1 \% c1 i% g% a( D: ]; L
    . A! P: t0 C( i! u# b; K' L! Y
    ​ 拿两个数组试一下:
    ! b  h  F4 l1 X% j+ r; k
    7 W. {- P. R: s) r7 o% \* D5 J6 O, U5 E/ \. r$ ]) c. x2 I) `
    & |, V# o, d0 J" @
    9 S6 E) ?$ A! ]4 t! G0 q; n) y
    $ ^7 V" |% x9 B; H2 y  Y+ T- C
    代码实现
    6 ~: c- x9 E6 k+ q8 u& }# p' q' z0 b  o' v
    void MergeSortNonR(int* arr, int sz)
    ) z) J& U: S/ o* D$ [{
    . q2 [  _  Z+ O    assert(arr);
    " t' X( z! x( c$ K! w* ]; t1 m& g- n" z6 b1 o( k2 [+ P
        int* tmp = (int*)malloc(sz * sizeof(int));# C7 ]4 @% w; \. ?, t
        if (tmp == NULL)) Z  l" {7 C% A4 Z
        {( _5 ?4 ]2 ?9 Q8 K: Q* L# f
            perror("malloc fail");3 y) z, M% c, z7 e
            return;6 g+ Q6 ]; |9 ~7 a
        }
    : @! u4 F5 O: I# @; e4 {
    9 e; C9 E+ ^! Y; k    int gap = 1;
    7 ^" |; Y; @! D: @    while (gap < sz). g" G6 N) D% F  h
        {& H$ w  V& u! `
            for (int i = 0; i < sz; i += 2 * gap)5 r( O1 a" _4 k5 H
            {
    - ~4 M& A1 |5 i            int begin1 = i, end1 = begin1 + gap - 1;; B& j$ ]& X7 d) n5 q
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;9 ~- ^+ U  c5 U3 h! d1 d3 M
                int j = begin1;: B5 r$ R7 H# f  a/ y( [  t# _( \
                            //越界检测- j; k' e, R; P& d$ q% _
                if (begin2 >= sz && end2 >= sz)+ L& d4 \9 Z$ ^& N: [* P
                    break;
    1 O6 `8 e5 _  W" f            if (end2 >= sz)8 N5 f( T" o8 v2 k/ Q
                    end2 = sz - 1;
    " D- w; ?5 `/ Y5 D            //归并
    ( a7 t# j7 w; i" c8 o4 Z, V5 w/ X- ^            while (begin1 <= end1 && begin2 <= end2). O& {+ `: o  t5 e9 K
                {
    # ?' {. y( Q* y& `& W1 b; h                if (arr[begin1] < arr[begin2])$ f; b. i) T3 q* _& m+ y# T
                        tmp[j++] = arr[begin1++];
    1 y2 I# g1 @$ r% x: D! G# [                else     / _4 }: |3 p+ h
                        tmp[j++] = arr[begin2++];2 L+ W8 f1 R: R. Z% t/ c* K
                }
    7 u2 ~1 y: c7 K6 N5 m$ I
    7 Y- O' F7 [" l$ Z. q            while (begin1 <= end1)
    7 ^$ @. C' v2 m1 K                tmp[j++] = arr[begin1++];6 W% Q, q% g- k; O  D4 ~/ X: Q
                while (begin2 <= end2)
    ; w7 r% v! ^; j: J4 R0 v9 w                tmp[j++] = arr[begin2++];: h+ S* Z9 w) y7 r% o9 r

    , o7 _8 A' x' J9 P0 S* Y            //拷贝回原数组——归并哪部分就拷贝哪部分回去$ p& F4 O8 x4 @3 W# h, \: f# S0 K) p- c
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    4 Q' a1 [+ {- I        }" W) `" y& g; [. Z9 B9 D4 k
            gap *= 2;! M  a" w1 K5 R" l
        }
    # [7 L4 u" {' ~* h' ?$ V
    2 X0 k1 n- @# a$ o}
    8 k2 P) o; Q+ `' j9 c7 b
    % t3 F) }& w8 @: a8 d+ `17 A1 g1 @! w- ~! B9 t
    2
    2 @9 p' u" G2 `% r9 X3
    , D- ?( k% y* k4 g6 l49 V; [4 ]; `; e  n7 d, F; N
    5
    , X6 E) M9 L) k. }  r5 B, M67 w' d9 U) j$ ?8 W# Y6 I
    7
    2 y4 a7 i) Z# U# a- ?6 `8
    & g# s. h( z; b) O) B: x3 u9( x; {% N( U9 Q. H7 P
    10& \! I8 z8 ?( @6 ^1 v
    11
    . l1 [" Z, v# i- I$ E8 V12/ l0 a% E0 s3 \9 T3 D
    137 Y" `# p& I* q" F% O7 M- H# k
    147 N5 Y5 l4 ~1 w# t0 `0 K. z) L
    15
    # C( X! ?( q7 S# K3 o4 K7 N$ B16  U7 `- Z9 C0 g
    17- V& N4 K2 u% c. f: w
    182 J+ w3 C; T  c+ V8 }, O
    19
    ( n* `+ J& |  R- U, n" |20
    - ~$ A' J/ `" w' Z. a/ U# v21
    8 a2 _: o  b" d222 c( G9 u+ ?( J4 z; `" Y7 `! N
    23. \* q% R' x' }" b7 c
    24
    : T8 e* w2 J: i8 y' Y1 p25
    + s3 Y- Z. E: ]# j; l26( B% b6 H9 u* k3 h* w4 d! E, l# O
    27
    % `; l1 z6 A, a281 \. g, q* _# M& ~4 G
    29& w4 x* k: H1 q, B6 a+ V7 u( G' E
    30
    / Q9 u  o1 [0 x- ~* Z+ l31
    ' k; s' ^0 E) ]  e7 i0 }32* x5 K: ~* O0 w
    33
    * ~% ?8 Y' {6 x34
    " ~+ L- \8 N4 X/ }35
    ( U, N# M6 s: p) M2 f# {; x36% O4 a5 t; S% T* K+ X( R
    376 a7 i0 a4 @3 S
    389 D9 f% G$ F$ x4 H' \
    39. ~. U! x9 v  y/ d$ |* ]
    40  B% i1 a+ n6 y" l0 k
    41
    / l( z0 z# b) X42: C9 G- q6 ^; H/ m( T. E, I6 D5 |
    43
    9 o5 a/ k" K( n& f44, I' Z9 G2 d: [
    45
    0 l9 {- B0 [' q# @- j8 b归并排序的特性总结:
    2 S/ N/ S" C9 j* f! [% E0 E  I( j5 n
    8 s: `( I; K2 u* k& B4 L归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。/ m) v7 Q# a/ U5 u4 L
    时间复杂度:O(N*logN): A. v. G$ L3 ]! L7 p0 J
    空间复杂度:O(N)8 b* A: C' q0 C" }( M% o
    稳定性:稳定+ n+ r: t9 h) b2 K
    ) T  D+ Z6 Y4 }9 h
    ————————————————
    5 s( b4 L# s5 M! J版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 v5 R, k0 d1 `  }+ J; K原文链接:https://blog.csdn.net/weixin_61561736/article/details/1267966575 }* ]" ^' w# O/ Y

    1 h% J' V/ Q: B  K& A- ^6 H. \, F7 B2 ~2 D* G1 J  N6 i
    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-10 03:13 , Processed in 0.412737 second(s), 51 queries .

    回顶部