QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3312|回复: 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的排序算法】归并排序
    0 X0 |) i3 h  x7 b) O& Z
    ) [; I; e/ Y# D* V3 T$ G2 [前言
    ) ~1 y! n" r* r8 {4 J, j# }5 [本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。! @; D/ O' c/ M( B& `7 Y$ i" S  o
      x, B) \7 N0 f6 [: Z  I
    归并排序
    ) W2 w8 b7 F, l& V$ ]/ |基本思想# ]$ Y4 w, J9 {+ U
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    3 F8 I8 E! {: ?! W. _% H  x# }
    + ?8 A8 I# X: q% n7 K4 R- [  `$ x" P1 n- J
    , W3 t! P3 q3 t/ Y! s
    ​ 合并的思想其实和有道题目的思想如出一辙:
    + l5 L" j) c( p% {# n
    5 `; M3 F; O+ }, g& i! O( a: e% {, b9 j5 q
    9 x0 G' _5 X9 U  ?( p, h: b
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    0 n' @) R1 U9 u7 z9 Z: M* w' G3 @3 Q. T$ p. @9 m
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    & ?; m) a- ~5 S6 l3 J, j% L- i" @2 x" o
    ( W" U3 V! W5 y0 dint* merge(int* nums1, int m, int* nums2, int n)
    ! C2 g* M: {' Y, N{
    - f7 |/ D0 I- G2 r5 X0 p        int* arr = (int*)malloc((m + n));
    ) E7 n/ q5 `8 [    if(arr == NULL). v* `) U6 m8 ~+ K1 X! ?5 q
        {. V1 p0 H1 A/ o* {
            perror("malloc fail");! U$ k% c- ?0 {) ?4 E
            return;2 J! Y$ x+ I5 X' G4 a0 n
        }
    * t( C' T% B6 d; E) e- c! N: `" E1 l& W0 o8 U; S: p! V" H" I
        int p1 = 0;9 T& b; E# z  d/ V4 U* I7 D- h! a
        int p2 = 0;# z* x7 m! e# \! l4 y4 `: y; N
        int cnt = 0;) [/ ^. i- K; @, I: C0 W0 t
        while(p1 < m && p2 < n)
    4 P) ~6 \; h2 t5 E' K+ O& |+ m    {+ @% y' L! ?+ M3 S" H
            if(nums1[p1] < nums2[p2])) w" D4 W$ g" e2 a
            {2 X: x7 p+ r8 _5 W. ~' ~: e
                arr[cnt++] = nums1[p1++];* D) x  |3 n8 |( g9 [! X2 V: ~6 d7 E! G
            }
    4 G9 R; |7 \/ I! ^  D1 a" b        else
    ' F7 U0 e6 p5 P$ Z* l$ h: U        {
    4 x" ~1 ^, B8 E5 J/ \2 I7 B3 w            arr[cnt++] = nums2[p2++];( e% `+ q+ {- |' F. Y' X5 Q
            }
    5 e- W( s  b4 W8 U3 s+ e    }
    / e) N9 H9 i% I8 F/ ^% P+ m1 e3 }    while(p1 < m)
    , g" Y8 g" D# G/ I$ I" @  Y        arr[cnt++] = nums1[p1++];
    ' t) O* s1 l/ ~9 N, N
    9 E5 Z, x; i& o" U$ h* G$ h    while(p2 < n)
    6 x+ F# K( [9 F6 M1 V        arr[cnt++] = nums2[p2++];
    & g5 B2 I* o) G% K% E: Q5 H+ g: [$ A' |  ^* C. z6 t: M
        return arr;8 M9 N! t$ _( ^! g* K6 G; o
    }6 ?  r& }0 w) j" ?8 i& e& T

    1 j8 C% m2 Z- R2 x+ S$ M19 J5 Z7 ~* z+ A
    23 E, F; W: y. b( m
    31 j$ z4 O( c* @  `  w8 N+ m
    4
    2 s( ]5 A' p2 v) K0 B53 ^% G, u: n" H' [8 Y
    6
    5 X* u) B' I1 |% X8 M- |7$ C& i" P0 Z$ L9 N4 I+ J- Z" e
    8
    6 O; P  H4 J+ ?  A  l4 y9
    % @3 p$ ^, e3 ^0 k5 ]10
    * m+ k& N; G; d1 h: a" a11/ D, J+ t2 o$ b1 l+ a
    12
    & _; A# ~5 w: J0 W13& H1 U2 d0 e4 o( j# u: H: E8 k
    14
    + M: Q; Z9 t/ z# N15- i" n" A8 Q2 m; C. W( x# V" A7 i
    16
    3 V5 z8 a  W8 N* t4 N17
    5 C+ x. ^- O7 ~4 z8 V$ H18
    6 j" Z8 i' }2 h19& M* Z, z" t8 E' i
    20
    - W: E  H/ H& U  E, p9 @2 ]$ D; C$ f21' M' A8 G6 Q/ n+ T; x
    22
    % }& X1 w$ g7 u, X, V1 }23
    3 N+ `% F& U4 f$ q5 }241 V7 G- ?4 L9 x2 B, {$ i: ^5 m
    25; T5 a3 I. }) F0 |
    266 W% z9 k! w8 K' b
    27
    7 h5 W, B4 ]& k284 \; d. ^4 [- A8 _8 M
    29! n& D) g2 i2 r3 n4 _
    30
    ' O7 q* |3 S: c! U4 E; _31
    * y* ~1 q* D, k# G+ {+ j" h% b; a8 Q​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。: ]/ O6 c) B- _, j# q

    . y% w. k' I' v- C递归实现5 [7 B. Z3 |3 s- O; {2 W3 z: A
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    6 [( i1 F5 M+ ]& l# E
    " h) @3 U4 M# V: h8 E- }* Y6 C* g9 t" I3 F8 L# u
    + d6 y5 [1 R4 L! D6 A
    2 E' Y  ^8 S) ]* S8 w5 ]

    ; A$ n; B& k* vvoid _MergeSort(int* arr, int* tmp, int left, int right)6 |  m# m% `$ l# ^
    {
    % p0 q6 z( V4 i/ O8 S  h% C& W  k    assert(arr);
    0 _! C  x# z" I& F- b% R+ x4 ]0 x% q
        if (left >= right)//递归结束条件不要漏了: D5 k+ q! P1 a" V% n1 V' x
            return;2 q/ q* M( K8 R* t- t/ E& E

    6 i9 k7 |7 u# J- A    int mid = (right - left) / 2 + left;
    - J3 r7 c* t+ n( R2 @( {; T, c" H4 b) T/ m; F
        //划分左右子区间[left, mid]和[mid + 1, right]7 \* M; h3 G7 A* e1 N
        _MergeSort(arr, tmp, left, mid);& [+ w3 N7 z9 `  }2 ?) O' b
        _MergeSort(arr, tmp, mid + 1, right);
    + W1 R' N1 \* j$ |3 Z" _  m
    2 u- [5 S1 i  N    //归并
    9 s% a  `+ i: X% W    int begin1 = left, end1 = mid;2 y! X8 i8 `7 z9 ?
        int begin2 = mid + 1, end2 = right;6 e6 \/ I5 O% X& J4 Z. s% p
        int i = left;
    % z3 ~/ }. m- }% s! ?3 c    while (begin1 <= end1 && begin2 <= end2)- u6 G) S4 Z" Y& I& i* h0 D
        {  D6 u* l1 z# k2 B/ T( F* _
            if (arr[begin1] < arr[begin2])
    % [. N/ m8 T/ n: G8 F; Z: V            tmp[i++] = arr[begin1++];! m- r8 e& i5 E" ?5 r3 k0 @8 ~
            else* m9 c" U: b, d2 s+ w: R- \
                tmp[i++] = arr[begin2++];: _6 `* w" o$ Q
        }' z# z/ }' `* w' d

    & `1 I9 M( i, k2 m2 d    while (begin1 <= end1)) W7 S* @6 t" i" I
            tmp[i++] = arr[begin1++];) e5 O- \. M6 p3 V8 |3 t- B
        while (begin2 <= end2)
    / X% Q5 ^* P% \% @, g        tmp[i++] = arr[begin2++];
    ) W3 x1 [! a5 K! ~: X! G        & j( r1 h8 }2 P) d; q
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    / V6 n+ C2 [- v$ z. T    //而不是拷贝整个数组回去/ H9 K. n4 e& z6 o  o
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    ) d  k! E! L9 E! l2 _( x/ Y}- C% K) o& b' s2 X- a8 _' I

    ) H9 N# [3 B: u, W  jvoid MergeSort(int* arr, int left, int right)
    ! f8 ~/ a% b/ _) b  R4 C{# e9 b2 ]% a+ }& f1 \
        assert(arr);5 Y  U4 `8 A* h; N* B) E
    2 J) O" b5 V$ Q4 ^$ W! P/ Y( `
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));, f; X6 R0 Y, i6 n$ h% X+ y5 Q
        if (tmp == NULL)
    3 z0 t( e5 W$ ^9 H    {. n+ W3 h" z9 n' Y+ V, j
            perror("malloc fail");
    5 Q) `' w! P# m; z5 @6 I% Q        return;
    0 R  w4 Q1 G" o0 c3 L    }
    ! B2 n5 j1 @6 t/ m" s! v4 W3 N0 I% w) X; Z! _7 I
        _MergeSort(arr, tmp, left, right);
    5 T7 n+ A- C9 L% E9 _# }: h0 A/ T5 b* p; n
        free(tmp);
    ! ]; t& [5 D1 n6 E. F; b9 I    tmp = NULL;2 T6 |* f7 g6 {, z- d
    }+ {3 x9 `0 e7 I1 ~) g, d5 \
    ! y3 k' p7 Y4 \
    1
    - m7 F( q& n* d7 n8 t2# P) a+ X: K5 S1 s: c) G
    3  _9 O4 W# B0 m2 T" s8 E0 |+ O
    4" _$ d3 i% F1 u# H" ^; e
    5
    ( O& _, r, I6 I% T6  ^& W! `; _- p* R5 ~% h
    7
    8 M3 g3 \& ?" p% Q: h6 l8
    & k; E! r0 M8 p" Y0 M2 N+ M0 P2 h9( A4 Q9 F9 f/ y" u. |+ R( g% d$ O
    10
    3 w' f$ T4 k' ~7 T) q; ?5 R11
    9 v+ y$ k, C* B4 X  I12
    0 V9 O: @2 P8 u& l8 I13* Y/ g  d$ l6 @5 z! e/ t( x
    14, R1 [( O; P# @% z. x- L9 B  y8 |
    15$ Z/ n& N+ x4 ~$ Z( t2 V4 ?/ m
    165 K1 ^' ^6 ^: R+ y+ o
    17% O2 _6 U) M3 O; q3 q% \, B4 h
    18# A" z' K; u* E/ ]5 e/ u
    19
    " i% B" C' K; N* G  T- W) _- ^20
    7 _" X/ ~# W3 j  h21
    7 C* j' N7 Y1 z# q3 R22
    " q7 y5 y, n  v! v5 ?23
    1 K+ J  l7 h' ~; e3 r. D: f24
    1 D9 a& B( X$ t& G0 {4 E+ x+ u( b25; c; Z8 Y, Z+ @0 K& B6 l# S( e
    26( |5 W2 D4 a* L6 v* {4 B
    27
    ! }+ b+ Y/ v( _7 a3 Y2 E28
    4 b/ b( T; u) o3 ~4 K9 W" t29( R; z8 z# n- m; o( J
    30. `' B# r: {# j% n
    31& u9 D7 Z, v5 e5 H5 G( x0 E$ @, g
    32
    + b  r/ B# z3 M' `  t6 [0 L33' Y3 X  @* H. V
    34
    7 L# o7 L, f3 W, U, e35
    0 J; z' y8 R8 G- y" ]# m: F2 X36
    : f4 |1 \6 Z) b37
    9 u4 d& \7 @$ k* n0 [% D38
    + u7 d, H" ]8 t: l! E( \& `39
    * H, ], g" t2 ~8 q7 e1 K40
    4 P& P( ]7 r, e- g! K41. p2 o% l3 V8 _0 ~. M
    42/ T& F% z5 f+ H/ t1 N
    43
    9 |# l, S8 f0 n* w& Z44
    % m; ~: Z0 c' U* K4 P  L2 H* G& b45
    ; E& H% h7 y4 f2 [3 e  K46
    2 T! n+ G1 y- F* O9 d( R5 e5 @, }  s% J47
    / }" F. |: a. L, n3 B48; V6 X2 l4 c4 c: d: o- \8 u+ r9 [' l
    49
    ( V& ~+ A% Z9 f0 S0 ^$ Y, f50* o6 I3 H' }% Z
    51) X1 Y9 X; R% h  {% h
    非递归实现3 D# _7 g- y4 E0 C6 Y6 \! J- z
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。  O! u% t8 ?4 U- n( m2 B
    7 F9 O6 A4 f' R
    0 {: Y' i" t1 J$ x8 ^: A

    8 k3 v) R& s0 o7 g; H7 t$ U​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。# `2 b1 g, ^% C& e
    $ D8 d: I! d. {9 P
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。% B$ R4 s5 l  M! j
    1 `1 |# X; [, i+ b( O6 p
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。4 |: T0 _9 B! o% C7 x- }
    3 d; U. G# H( b  [7 y" ^1 P
    代码实现
    ! O6 |, ]4 {' f& g% u5 C% }- i! G& q/ e6 D' }
    void MergeSortNonR(int* arr, int sz)
    , g$ f8 d+ X$ Y& _4 N{# O: d- n: ]: ]( ^. [" G
        assert(arr);# P4 w7 X1 `! y- l: I3 s: g1 P' d

    ( ^5 ~  J, g/ J    int* tmp = (int*)malloc(sz * sizeof(int));' F6 }) U9 z4 }; r
        if (tmp == NULL)
    / P* E( n' g- ]- O; V! G# Q9 a6 r    {8 d& K7 r. _: T: {/ V" a
            perror("malloc fail");1 y* e$ z) j) |
            return;
    + g9 q- ]6 R6 k. k# [; J3 V( o9 u& ]    }
    . r2 A: [/ a4 T. v$ y% d. {2 J. t1 a9 h  F- `4 ?. V" @# d
        int gap = 1;7 A$ |( Q6 d% Z: Q- g3 Z
        while (gap < sz)5 L5 I& L# f+ W# l
        {
    & Z  p" ~4 i" A% p2 R# y        for (int i = 0; i < sz; i += 2 * gap)
    6 S! U% i5 w: b        {( W; I5 f* B0 W" v3 `
                int begin1 = i, end1 = begin1 + gap - 1;8 X! z- }  c$ i( e- ]" l
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    # Y  O" J4 d- k7 ^- e% p; V7 L            int j = begin1;) y% R2 y5 o; G/ u
    2 P' w7 o  R) Q2 l1 }
                //归并" q; Q8 U, J1 x- e" A8 \0 v
                while (begin1 <= end1 && begin2 <= end2)
    8 T6 h7 b$ n9 y' W            {
    7 g# w# h, ~0 P5 D                if (arr[begin1] < arr[begin2])
    ( D( h( D$ u7 M5 k) S% T                    tmp[j++] = arr[begin1++];* r& l9 X! i! a& h; @
                    else     ! f3 R# U1 h7 p+ c9 P
                        tmp[j++] = arr[begin2++];
    : Q2 g% j) w( }) k            }6 P7 w. }7 Q" M, _
    ) X6 w$ a) c  F' K1 |
                while (begin1 <= end1)7 o7 W* x+ v# p* Q& R
                    tmp[j++] = arr[begin1++];6 I' N* h0 h$ c1 f. \: C+ m
                while (begin2 <= end2)
    & u6 v% h' J5 H  v: h                tmp[j++] = arr[begin2++];
    ) A+ h4 W4 a- c4 D
    * O7 i1 r' D3 f3 L( j7 ~1 |            //拷贝回原数组——归并哪部分就拷贝哪部分回去) w+ s/ V% e  s( V; V) d
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));" \9 l' o" y2 b' @1 K
            }4 }3 y$ e' ^: @1 @2 Y0 X
            gap *= 2;$ ^. L- Z* y' q
        }
    * R9 I1 ?1 o1 [: j! q; O1 A1 m8 |4 B' T; m" h+ B" r4 ~! f
    }# H( e- P9 e/ Z6 j9 F( f
    7 [/ q  }( @: n
    17 k8 H) Q; q2 V5 [. t% r
    2( m$ z; x' `) K5 a' x
    3
    : C7 k- ?$ n: Q- @46 O+ m4 I+ n8 T1 |1 _
    5
    ' `) x2 h: {: P4 J0 _" J6
    6 _3 X" u! ]" v6 T9 q( C7
    2 w) q* s# P3 n: W! z0 V8# a6 Z- G! v3 {2 S& z  O
    9
    : ]8 n2 _; P% w, ~6 d; p" [10
    , \0 s! [6 a/ f. v% t0 `11
    9 T# e3 J8 X  D2 v12& D  r7 R2 q. N; I2 Z( X2 b
    13
    + ?. q8 x- {" U: o14
    ! L& _' _& }- O$ q15# m4 D/ a2 d( }- ^2 R
    16( r. \! o6 q; y6 B/ e$ @
    17
      _% Q( F( i" o4 w* t: t1 \; J) \. B18
    + \% H# O% ^' D* S$ O9 r19
    2 V1 z# X0 p8 N* T5 x20
    7 o  i+ J% E+ d21" y# w- i7 V' ?' `% B& o, O
    222 Q" W# r/ a& s7 o* q; k8 i
    23( O0 h* s+ f4 i1 a5 ^2 @1 r: F
    24, D# ^6 I& n* a8 C
    25
    % @3 ^0 c$ M! t& l  h4 f26
    . h/ o# d) N  @) R/ t2 q" C276 V9 _! F7 {$ K, }$ P
    28
    / x3 O; |6 [/ R* I. p/ R2 |8 w5 ^29
    ! f: H+ P: N4 N3 k4 i30
    ! f4 o7 B5 V3 G9 B31
    9 {; D8 \; o; m' p/ Z, L, K7 B323 y8 G& p- f5 F8 H* d7 |% U/ @
    332 D9 M2 D0 T. _& |$ f/ [) d
    34# y$ C8 R; E8 r4 F; R2 g( n* C
    35' q7 b+ \( s  {
    36
    4 m- Z9 ~7 U! p* r3 i6 |/ F7 V37. [7 }3 S; @7 y; l% J
    38
    ; u  l7 ?; `9 U& Y39
    - h+ j8 I2 H( \3 @40
    8 }- v4 t$ v$ v41( \! R: |1 K/ B; r
    边界问题' B+ {4 e6 J% R/ v8 _8 E; m
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。# e# L8 |' k' K( i4 i# e6 A" }& X

    2 R% M8 n9 \- Q* C/ H举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    " q2 F, L( L& u& O2 e$ U, v+ B* _& T! n- z& c2 G
    $ b' c5 e1 Q& m$ C
    : t% \% k% c7 f# q" E3 a
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    - I+ b2 k& \( [
    # W4 A4 p2 n2 G6 t第一组越界(即end1越界)
    : V$ A+ r8 d: t( s+ D% O, B0 p5 K
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。. O# Z. d& r  l; s0 ]  P8 ^

    , t# u( {8 v- ]2 S# F第二组全部越界(即begin2和end2越界)
    ) P& _4 E7 S' d, O5 v5 M, ~5 M) _( I5 J) W& B% K; C; X0 X0 }( T
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。1 w8 ?, Z7 a( Q

    8 Z6 ~: J# ~$ _$ X8 M: z2 e第二组部分越界(即end2越界)1 A1 c" f& N6 d4 k
    9 [5 ?: |" D: \6 _# |! i1 I& U9 W
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。* E+ t' M- k/ v% \9 c+ |
    8 M% ^' ^! v4 @
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:  `' V2 v, z, G/ U
    ) t+ @1 j  Z7 q
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    9 k9 ^3 h# P0 R6 |( ]' W, o3 a: w$ V5 |! D; {  n6 u6 _
    ​ 拿两个数组试一下:- U1 d1 x  F# w, V
    0 {" Z, H- {7 K; ~
    # A7 g; P. n, O; t; A
    : p% ~% U5 o5 T$ X+ T1 F  r

    5 e- ~) b7 Y9 @# K# `' Z( j' J+ x% ?& t/ Z: F
    代码实现
    1 c2 Q9 u) `# E. i5 x9 Q5 J+ m6 G7 B
    void MergeSortNonR(int* arr, int sz)9 y0 p7 g, o0 A  Y+ Z
    {- ^- M  L  k7 [/ f. z/ F
        assert(arr);
    2 H: }* H0 Q- n& c# R  t
    : o7 c$ b; O0 [, N! E3 _; D    int* tmp = (int*)malloc(sz * sizeof(int));
    # t. w: {. n% D* F  l  Q+ m    if (tmp == NULL)! d  ?3 S  m; A0 D: z1 Q6 w" N. S
        {/ Q' w6 O5 i* L+ ]
            perror("malloc fail");
      S) Q( E5 J) i* d" ^# a9 j        return;
    ! K$ j6 l* \+ o    }' E- t0 c8 h( ~/ t

    ! W' P  ^- `+ G5 w    int gap = 1;
    " @6 O- m% {4 n( ?* i: t1 W* E    while (gap < sz). X  ]" M# Q6 {& Y/ E. u
        {5 P) l' h% @- M( u9 _  E$ @
            for (int i = 0; i < sz; i += 2 * gap)
    8 i# l8 ^! R8 Q; {4 @& O" }! H        {  {8 P, Y( n# b
                int begin1 = i, end1 = begin1 + gap - 1;
    5 _/ a3 @* o  p' V& c, c            int begin2 = end1 + 1, end2 = begin2 + gap - 1;, g: x" @( M# p: z! o
                int j = begin1;
    4 P0 ~1 a9 i0 r- }7 n+ w/ E) O                        //越界检测
    ' y6 M9 C' v$ w9 Z! _5 }- U            if (begin2 >= sz && end2 >= sz); o3 y: H2 o" Y
                    break;
    7 l" K0 D2 E) H: X0 \$ V            if (end2 >= sz)$ h8 r) H% ]7 Y
                    end2 = sz - 1;1 W! O* e6 Q7 ~2 E/ K" r
                //归并6 F* V, k. J! ^& S6 A2 a9 X4 p+ v
                while (begin1 <= end1 && begin2 <= end2)
    - h9 A. `3 [3 v9 g4 P7 N6 ~            {
    : c. L2 f! c* ^' `                if (arr[begin1] < arr[begin2])
    ) ^  y& J/ _' V) D( \$ l/ K                    tmp[j++] = arr[begin1++];
    , J5 H- C7 Q5 n& F+ @% w                else     
    ; ]( {8 I, n4 H1 Q; S* i" i                    tmp[j++] = arr[begin2++];
    & I& N9 k) [7 h9 }  A3 A            }+ i2 J6 d+ y9 L+ X

    0 D8 O8 z5 @$ i! a8 X3 P* }+ n  ?! z            while (begin1 <= end1)* ~6 L# ?+ k4 ?# c( }( p) }; h# X
                    tmp[j++] = arr[begin1++];
    3 g' k7 s) z/ X: j/ K            while (begin2 <= end2)
    * z. p6 q8 x  p5 k% d& o                tmp[j++] = arr[begin2++];
    1 I4 [* ]0 r; E- W6 P9 [0 S+ s
    . d( i5 x$ x7 N* p+ [            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    3 i6 k. z6 Z% i! l, R            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));: v4 X6 U  `; c0 q+ n
            }
    * h& X# y2 |) B3 r9 ], S1 M  R        gap *= 2;
    ) O3 R: [: P% O# Z+ h    }1 J7 t: w, P/ a, A1 U$ u- ^
    + z1 F& z1 p/ `, `1 h
    }
    ( J, u3 L! V7 z% f1 N# `0 r; l; O9 T: u& f* R  V: Y
    1" d( i1 m, M8 T- C* w) j
    2+ O9 M- P8 x' m( [5 M
    31 _& I9 x- q9 [6 y- b$ [" b+ E+ ^
    4+ p& ~, W# @2 `8 J
    5
    $ U2 y+ P( `$ \3 e6
    2 \, v4 a0 N* z2 v8 s7
    % ]8 \3 O% X( T7 c% |% n& I3 j# w8
    + [( S2 X& Q# _% B" n; V" ~9
    8 P, |: r; h$ O. x0 |10/ ~$ R* V9 Z% a2 d# s
    11
    ; ~' ~4 E- x$ `' O) ?6 Y12, y9 s! }+ L2 f0 p# Q
    13/ b# V5 K% c2 X) `% \. M
    14. t9 A* |+ E- G& n0 G$ a# M$ c
    15
    ) ]. k7 x- r5 T$ T16
    5 j9 r, y: h! B  k# G4 ^171 h; \7 U9 r7 d3 [( r* ^1 i8 C
    18& Z& e4 f& ?0 _! n% @
    192 g3 D2 C1 a/ |( q- ^* b
    20
    6 H& m/ H0 u. v8 h7 R) e212 A. R9 k1 q: L! @# t
    22+ Y' W( z  p2 ^, z0 @2 q
    23$ p* Q# {7 D* j, H1 b- @. o9 m
    247 o7 }- _4 J9 i" Y3 Q' M
    25( [8 E: a# j0 n
    26
    ' D6 F# g- J7 }3 ]27
    6 K" k; ~( ?1 z  ?28/ }1 p7 W: C" F- a7 w: C
    29
    " e" V6 I! c! Q0 C, E, [6 \30
    5 {1 I4 j7 r! e318 _  k& C: f* [( I% y) `
    325 T# b3 w7 {8 _% @7 w7 o+ Z* `
    338 O1 m0 U/ q% r/ s6 P
    34
    2 l1 G% f6 U5 L9 R( K359 S, b1 E3 s+ Y& x
    36( V! W# m( `8 z/ f
    375 Y5 y$ K5 n5 Y0 r; x5 q
    38
    $ `8 ^2 ?7 s' Q1 T5 f7 ~' t: d39
    ( n5 L. p8 s7 y; R4 w40' A$ v. [9 l: r6 X6 B) p0 x) y' R
    41  {' K1 H4 j/ P) M3 X
    42; U- F. z4 R, s: [
    43. c- ]# z- }; q' _8 p$ ^# @
    44" O% E3 f$ `9 O: L& y
    45
    + n" r3 D/ O. W7 a归并排序的特性总结:2 T! D2 s6 A. o% H# s% m4 @
    0 U! i: e( g: }" H
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    5 J& j- _9 u( ?时间复杂度:O(N*logN)
    : R6 \/ [7 Z" W空间复杂度:O(N)9 b% _3 n$ [  _( W+ S
    稳定性:稳定0 A2 }2 d  u2 u# I

    & R! V8 \; g5 ~7 Q) U————————————————1 e' D  l  {4 {
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。# f% s3 h  I4 d& d1 C
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    9 I; ?- }" W' W, n- I4 L; q5 E
    ; L6 l$ Y- h! @: z) v0 }3 Q
    7 ^7 Y: ?1 P3 y: U. |; S6 B' d; d* W
    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-6-15 18:26 , Processed in 0.416682 second(s), 50 queries .

    回顶部