QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3431|回复: 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的排序算法】归并排序/ R7 }2 Z2 K4 j/ r3 P! B
    : C. p. J/ V! b# i. u
    前言
    ! L8 j8 J4 R4 c1 ^* w' L本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
      d; H0 e% h) k- n) H+ L$ E7 B9 u/ Y2 W( W+ S
    归并排序
    9 Q- t* O; m! s3 P基本思想
    7 }3 |5 r' h2 L8 V5 V; e; g- ^( S​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ; \: {8 H2 V$ I. M* ?9 f( x
    1 a- u. u( i1 H/ l2 b1 G$ e' ~/ \9 S: `# M) ]& \+ }

      O8 F& e+ w/ `+ T​ 合并的思想其实和有道题目的思想如出一辙:
    & F3 U) Y+ D  b5 l" P; @
    % k1 ~- w5 h- T8 i9 A
    5 M) V0 s+ [0 X; o5 Y# T5 l; V+ b
    6 _4 O: s1 Y, i% [​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。2 g+ b) {" |& K5 o

    8 Q% H7 M( r) b[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    2 h0 ]# @0 U2 q8 e4 M/ h! M# \
      M7 u& A* _6 r, yint* merge(int* nums1, int m, int* nums2, int n)9 f2 [' ^: {3 G0 o
    {+ ~4 ^& ~' }7 b' Y" l3 C4 W
            int* arr = (int*)malloc((m + n));
    . T+ E4 r2 l1 B$ g2 T& i    if(arr == NULL)
    : u, M. H. H1 c! }0 v6 m    {
    + g% s4 x0 p' u: V. M* }        perror("malloc fail");' s( m5 S( @( T& \8 n
            return;$ ^# Y0 o4 ~! }
        }/ }! F; I6 |8 @5 P
    % q7 S  a- O8 [3 M# x1 C: ~
        int p1 = 0;( R& V0 ]) Y1 W: P* X3 p
        int p2 = 0;- \% C& p. Y% w( o! h4 ^& P
        int cnt = 0;
    8 ?  P8 }* \( I% y+ m5 H4 E% c7 h    while(p1 < m && p2 < n)
    1 @0 @  a7 ~8 t/ X7 O7 ^    {: u8 ?& B$ M# u( @
            if(nums1[p1] < nums2[p2])7 H6 ]8 _+ _8 l1 K; f8 f
            {. A7 ?( N5 X' }4 b: H1 s/ C
                arr[cnt++] = nums1[p1++];' j8 X. M1 ?- D! N! |/ f% ~
            }, ^  h: ]0 R  s7 D: S& h7 V
            else
    5 N* o) Y8 u! o2 {" ~# Z3 q        {
    , J$ B- L% |9 I- l/ c- S: H            arr[cnt++] = nums2[p2++];7 b/ ]: y& l4 M7 l+ A/ ]7 R
            }2 C2 B& }3 F* O/ C3 e
        }
    $ s% d: c! W9 m: I    while(p1 < m)
    0 T( |) D8 Q# o% Z* z" u        arr[cnt++] = nums1[p1++];
    3 j1 \) c; a2 M. B$ T9 o
    : {" O+ a5 {0 R9 B1 }    while(p2 < n)
    6 m, m) O, N- Z$ Q; d3 Q        arr[cnt++] = nums2[p2++];
    0 G' P! C3 \& H8 ], ^4 N+ J; D( B4 X  d' U+ X( U8 W
        return arr;5 K0 v+ t; e, T- r" L
    }
    0 R; T" ?  V* a1 W- }
    ; I, E4 {2 a8 M' s) l, Q- V1; X+ g$ N* f- o' C- @& ~" h
    22 ^6 I; q, s% _7 i* G
    3
    / k5 b" Z% F* r: f) `) m2 r4
    & u8 H4 ?! o  l. V% A/ E% b. C5
    % M' l" O/ M- k+ q% p. Q5 _$ E6* W  i% J$ V" u" \3 r: _
    7
    % ]3 e# f$ a1 n9 b& J+ i- W8  O7 l  L. q7 u; K0 Z
    9
    / v% f1 u: G$ ^4 _10
    ! M7 Y+ m4 G4 }/ ~11
    - K- C  a% t- u7 ^12
    7 h2 @0 L+ Y& O+ P" O4 v13
    - S5 {% y: d2 T% p. A14- N; ?' [5 U5 u, j  M
    15
    * B, z. I$ s, `: O; L16$ O6 L' ?* ]; V: }' `4 }; a
    17
    7 E( \  H& p( U2 ~18
    5 W" @0 d1 m. [* i19
    " X2 h/ |/ y# m' \20
    : g1 s: w+ H* F4 t21
    1 [0 w8 @/ S; H( g2 n22/ f: V" g5 u8 q6 |
    23' u9 H& k" l: ?: E& Z; ^: o# R( {
    249 L! N0 I! ]: v, R- J) }
    25
    ; n+ T" m: i3 l9 ~: L5 j7 k26
    $ p# y2 j. J: D3 M274 @3 d4 ]) V8 Z! K1 y6 e
    287 x, R. l4 _# D, g8 u" Y
    29
    3 D9 `7 v9 j* x- x2 c" S7 R3 V30) n% R2 U- l% `4 ^
    31
    ! I- x( T9 _9 j0 z​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。& C* ^2 u4 ?% P; G

    $ @, R( g$ m& Q3 f0 G9 H$ I0 N3 ?9 F递归实现2 n: i/ [( v+ o' N' _
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    . @! D- W  ^4 ^1 p5 i& o/ |. d4 z9 O$ T
    ; I" f: j9 t" O* `2 [) k6 d
    " @3 y  o, L. S) b/ r
    7 ~, z% l! k/ P
    9 W1 f7 N/ c4 a& {, c
    void _MergeSort(int* arr, int* tmp, int left, int right)# n5 f) H& @3 I3 U2 }
    {( w* s1 D& u8 U+ |+ @* B3 e: j
        assert(arr);/ K" f- L- e  I# \% M

    4 K/ E& D% I# b9 a* `% E    if (left >= right)//递归结束条件不要漏了  _0 b9 {/ Q9 n' O2 R0 M# f5 P
            return;
    1 r* Q  F; _9 g; [6 X# I+ E( m$ G
    , Y; W" J) _5 o7 D3 y    int mid = (right - left) / 2 + left;4 |3 L( C1 Z! I' c- K( h
    2 @" |( n0 e1 H
        //划分左右子区间[left, mid]和[mid + 1, right]+ Q/ _" ~5 n6 y  H% L! a7 l
        _MergeSort(arr, tmp, left, mid);/ D- O% i1 r) G  {# x, {
        _MergeSort(arr, tmp, mid + 1, right);
    ; f) e0 `7 |3 I- N% |2 ?8 j+ u1 z7 L8 a$ w$ S) Q9 {
        //归并
    - O: M5 j: G8 X$ @0 C1 @; K    int begin1 = left, end1 = mid;
    : v& H+ Q/ Q; c8 P+ V    int begin2 = mid + 1, end2 = right;
    ) o. |( f+ S+ S# ~, ?; B9 p    int i = left;
    8 W2 p9 c1 a9 J, K7 S/ k    while (begin1 <= end1 && begin2 <= end2); X5 Z0 \8 p. N% K* }
        {) ^9 r/ u( A# c* q- V
            if (arr[begin1] < arr[begin2]): u' c& z0 F: I) P) s
                tmp[i++] = arr[begin1++];
    * A' Y9 H; y% ?0 @+ Y& \        else% l, m' w' ~# ~2 g1 v7 x" p
                tmp[i++] = arr[begin2++];5 b0 X# ?2 z1 T: }
        }' S- C9 i5 E% z- V

    1 g2 A7 q& @( y5 l4 ~  G' ^# E    while (begin1 <= end1)
    4 V! K, u, q7 M7 Q5 b3 K: @$ I( c& b        tmp[i++] = arr[begin1++];& M2 B: O6 W! I
        while (begin2 <= end2)6 P: |- S4 E! T7 |* _& i
            tmp[i++] = arr[begin2++];6 L" s: r0 w! s& }. Q: `8 v+ |
           
    8 l2 b) Q7 n* [% u5 ~! T    //拷贝回原数组——归并哪部分就拷贝哪部分回去# S8 ]9 X( S. @
        //而不是拷贝整个数组回去
      J( }4 n" G0 o/ h    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));" c; e: S8 v' K. z" j
    }
    1 d0 x- C4 @6 `" [2 _7 m2 R0 _& z
    void MergeSort(int* arr, int left, int right)
    - E; X% t) ~$ R. [3 E- C/ i{
    ' @2 E/ Q4 V- m* s0 ?  a8 E    assert(arr);
    ' C; h9 D- K- k7 z
    / O% G4 J* p# W3 z  t: g  q    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
      f  z9 g* W% U4 x: z    if (tmp == NULL)
    - I+ j& @( A3 h1 v% H# l    {
    % x" Q! _; w: C) q0 O' E        perror("malloc fail");
    : M6 V" u( o  T5 p% \7 K9 q        return;+ i, ?9 s; H3 C+ `5 v8 X
        }$ {! F' _) i/ F& m, v
    0 l! \3 b) i* V; [
        _MergeSort(arr, tmp, left, right);
    9 s+ P+ ]% d* y$ U
    $ V/ R1 A: l% T7 O7 o- k/ b: N    free(tmp);& D2 G6 ~6 e- n8 w/ C! r0 N2 J8 ^
        tmp = NULL;8 z0 r: K. t0 f
    }
    . ]8 M  j+ |7 K4 N. J% t" G, a! h8 v  L  r
    1* l* O# L$ D! ^% U$ W, R
    2
    ; ^* _# y; v. T, [3* g" W3 N) K3 X  d
    49 h! J3 [$ W1 X% M, v- n! @- \
    5
    7 b$ a- w( n9 H* H; B+ S- p6# N( _5 H, _' l4 L3 X9 B
    7: \  }  D9 s8 D2 u2 x
    8% k! U+ F- w! ]+ g
    9
    9 W) z7 _' j; ~& J9 X10" @+ \3 `2 P4 Z9 R# z5 s* _
    11
    5 ~  o1 a' q* d3 `% M9 }5 o12" J1 k" T( Y1 }5 A" _5 ^: `
    13! m: m9 |7 E- }3 \2 U0 y
    14
    * L- ?3 |! \6 I$ {8 k* J% Q15; N" `- ?4 y$ n  |# I$ X9 c
    16. }, m/ W3 H1 ^) f: R7 u* h7 Z; _9 P
    17  u0 ], ?, P; j. U. e* t  b
    18
    3 J* B% V* y# n" J5 J9 n6 `19
    . @3 G3 n* h* l2 n, J# i/ b- J20( N$ X) `) G, ]! O+ R0 G1 `
    21
      k- o: t0 D2 P) \. p3 O22
    3 O) d& H( y2 G, P% P/ p% Z23
    + \, f- o8 ]& x3 N! D24
    " u! C2 K5 J& o9 Q+ Y* L25
    % z, x$ m3 T2 N/ ]# G2 ?26
    ! I+ A( L1 B, [9 M. \27
    7 ?& Z6 j7 X" \  @* v28* z+ {6 |. I, t& I" x4 w
    296 |( _: k1 y2 L' |: e& C
    30
    ; g# }& f& e5 y/ s1 x: R31) i% E) `. p; E+ ~
    32
    , J0 t3 Z* Q# j" {33) B0 n1 S) W' ]5 b  I
    34
    0 {. \3 l0 S9 g' f* e353 j, {$ T% o3 K0 Y, u% O0 z
    36) |  Y+ k# Z$ s$ e9 B* U
    37
    3 _3 G7 t+ ]- L4 k; Y0 z8 o388 b1 U( p* R7 T0 r0 g+ T! @
    39
    0 ^3 R; w3 y9 F4 Z, z. A40
    : c& e4 w0 k2 O. `, T& `$ z41
    1 O+ F1 c( o3 C" c" G! h421 a2 ?0 k6 T9 K& a$ E
    43
    : B, n% m0 q  t+ K6 u/ ?44
    # ~3 W, g4 Z: H# U, G8 m45
    8 \; B0 {1 @" b9 Q2 B  X7 `- V462 @* P- \) G* T4 O& O3 C4 S
    476 I/ s" ~; @& J: G
    48
    : B3 u4 i% j5 r3 @3 M49& t5 Z6 \; G/ ^2 i3 w$ \
    50
    , R: S9 t8 X+ |7 N" {4 _* [, O3 A51
    2 T: O1 z' J% H0 X非递归实现
    3 i! ]  K' P( j! E  |3 q$ `- G​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    2 f  p' Q/ \8 m4 i) H( v# V% i4 h1 w6 w% J

    ( Q; d! ~. R$ d+ V$ Q
    - G: e% ]- S# O6 i5 _7 m$ X​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    1 y" Q9 W4 ?7 n7 E1 p
    2 @; ?3 u! k" n6 K5 m' w​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。9 g' Y: }. C0 ?( a* n! f; @9 m; a
    + @9 D7 L8 r1 ~) E4 `: ~
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    , f! ]7 K. c6 y* z, t" D' ~* C0 l# P% C+ W* b/ g
    代码实现( y5 i. e5 P$ Y
    1 h7 d8 Y5 o* k$ t
    void MergeSortNonR(int* arr, int sz)7 o. a+ S8 G- W" ]) m/ M) H
    {. `8 R& X9 u% Q
        assert(arr);* }9 \; x1 V1 C1 S" y1 c
    ( G8 e3 x0 X( h) G
        int* tmp = (int*)malloc(sz * sizeof(int));3 x9 P6 S' b4 {  R1 T/ k* r' e
        if (tmp == NULL)
    4 q9 y* A6 v+ O. l& G# _    {, U$ H7 `$ K( t8 G! q  t. x: Y
            perror("malloc fail");
    , ^" d/ `7 x4 B3 b. ~. x& w        return;
    ! i9 U5 D0 i5 |    }
    & H9 s6 z1 X6 X( p/ I; z0 l8 k- O' r7 j1 U4 _5 P' |9 s% b
        int gap = 1;1 U+ e+ |% H# M. ^0 q0 t, v
        while (gap < sz)
    ; _# S7 G4 _! N$ e3 C" h6 B4 U1 t+ m/ V7 Z    {
    ( h2 h6 r: B" B6 [* B% d        for (int i = 0; i < sz; i += 2 * gap). s5 o1 ?8 n8 ~* u; c4 E: n
            {
    6 e+ r, `* X' }) Z5 }6 s, y9 l            int begin1 = i, end1 = begin1 + gap - 1;4 W% b0 n# O. {
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ' y+ |* Y7 _4 N; n2 O5 d3 O4 A: k            int j = begin1;
    2 V  z2 w3 L  A, A# s9 R
    / Y4 ~( n5 O8 D, y            //归并
    9 N' Z" `9 o6 S, j            while (begin1 <= end1 && begin2 <= end2)- ?! p+ s% n: M# M4 ^3 D
                {* H+ N2 D- w! `8 P" }
                    if (arr[begin1] < arr[begin2])
    8 O& _$ `8 g) k& B. i                    tmp[j++] = arr[begin1++];- d' K2 f2 a7 H& ]; B: ^
                    else     2 I+ \, H* a! I8 A
                        tmp[j++] = arr[begin2++];
    7 S) ]& X! ^/ u- `/ ^2 l% P. W+ V$ z            }) Z8 i, p5 V8 Y: b" z6 h2 @

    " J5 X. |4 q9 g2 Q            while (begin1 <= end1)4 K; u% @5 E7 n; K# ?. p5 I4 }
                    tmp[j++] = arr[begin1++];
    - p; T" {# c6 z7 |' {            while (begin2 <= end2)4 ^, T( J0 O+ n7 q5 a. p
                    tmp[j++] = arr[begin2++];7 s/ j8 A" `( ~- U
    + a  I3 I8 f3 m2 d! D- z
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    6 I3 V7 i5 R) D+ e- C) J            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    ' }) S0 g0 Y/ H- _- Y) q        }
    & Y8 o  M8 w  M1 G3 q. u# R        gap *= 2;
    6 t( t% x4 @2 q' u    }
    2 X, L+ _" @% T2 z% X5 R/ `7 \( b; T5 H3 X
    }
    . k$ R' U# ?3 M, Z8 X& O; X/ y8 C( K+ r0 r
    1
      X$ b$ ^' e, A( }3 `/ A! C) f' h( {2$ m( e3 y* Q" l5 w0 l0 T5 [; _1 z
    3
    ! T6 O. d& y$ q: j4" H1 i3 X, J( p# ?
    56 B2 f- ^, S' n. t4 t
    67 J( |. f! X+ e) @: W
    75 u% O8 F- o! ~2 n2 f7 m4 Q
    8; |  J$ x8 S: M5 N* q7 o' {' H! J
    9( R  i! ]' e( h/ z* |0 O- ]( G' S
    10
      L8 C( v! D- u# o! I) D* `* R; @; ]11( M- X4 \) ~# M2 J
    12% `* O" s# H8 `4 Z- s
    13
    ( {' ^# p# w0 h4 o141 t5 [1 j- q9 X7 n6 L) L
    154 x& Z! e5 h/ P8 {) t( q. F& }
    16
    6 S. B# n, o$ |9 R2 O$ u. ]8 W17, L/ m# j0 B& i1 ]4 D
    18: J6 p  \: I# i$ B1 x
    19
    ' k5 F1 y) m1 @- o2 ]' Y4 ^" e, k20
    " P% d/ u( N: Z9 ?. R21
    ' j7 p: A$ R, N! Q2 Q' E7 s' n5 f223 q0 S9 A9 ]$ I2 I2 @- ~
    233 A/ k4 C4 W- w5 a$ D9 K4 Z. D8 D% v
    24
    " p' O5 m  w* X* a- x+ n25
    * L( n! y$ }' k( K; [26
    1 z% j: z6 w% ?0 n3 J27
    3 a6 j1 `' Z5 s& }289 K& c2 j; E3 m1 `4 I  ?
    29
    ) U8 z' a4 r$ P2 S30
    + v+ j; w, s# x, l: y" o31) A; u) o( t. D2 }, O! u
    32) |) ?( k+ ]) f; j+ N% u+ l, j
    33
    # h9 Q; h4 G& e& [& e( l' Y, o349 j7 H& k+ T4 x: }2 \
    35- ?$ G( A! p  o; I, \: {
    369 C6 H. r0 @( s1 l- f0 J$ n; o# p0 f
    37
    $ Y0 D" }+ U& T6 w2 S" C7 H38
    ! |- A4 [4 L0 Z  T6 R( t39- v5 \5 K2 O) u' X1 ^7 Y
    40
    - i( v3 g# l) a6 P% o41$ ^9 Q+ C. j3 I
    边界问题( E- k9 v1 T! V4 z
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    . v) K0 ^4 q  g5 K! R$ f5 D" A% w' P% v. ]8 E
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:( P& W/ P  G! _) d

    ( C7 ~+ S' K8 @, R3 J0 K+ ]- d
    ! N0 g/ o2 N1 j  ?9 V0 D1 h' d. |0 S" j2 d2 A7 Z
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)* j- p6 K! f3 r+ q. O0 K: g" r; j

    , t4 D/ p" j" H" F1 g" o4 m: G第一组越界(即end1越界)  `/ y, a# }' [1 ]3 w9 A$ a) [

    * r# \+ W' O3 w1 k应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。2 D9 h/ x7 \8 G0 A6 Q, k

    : s0 c7 S' I( w; ]第二组全部越界(即begin2和end2越界)6 H* b5 x! r* B2 k' X6 R9 i
    8 x% \0 s5 S$ N5 `9 q8 X5 Y
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    ' M# t0 N8 S6 _9 c5 e' g2 G
    6 _4 I6 w4 H; H# Q& b第二组部分越界(即end2越界)
    " c  |$ n: Q  {7 O' L4 Q( [. A! ]6 x% a% Q8 ]( \
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。, s6 E9 L' i+ ^. L) b
    1 n, Y2 S: I7 f/ J( y/ T, ?4 ~
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:; W( u% p8 T- h6 G. J/ R5 ?
    / b' i3 v. C0 s: t3 M" @/ l: P1 c, Y) H
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。  j, U& C5 l+ [5 D* y7 Q3 T
    3 e1 v$ a8 O7 Y+ N2 R
    ​ 拿两个数组试一下:6 ^$ V. ]! A" `
    0 b( r, d4 }4 Q- G- v6 u: S) I: Y
    0 L0 W. b7 @# v1 \/ t/ c- K( s) m. O

      p' Z$ u* ?( [0 x8 ?2 I6 e! C' U, }8 [
    7 ]* J. p. J* v6 G" f: j1 I
    代码实现
    4 n, H* N1 ]7 M/ l  o
    $ K) ~* L9 f+ E4 V' f$ Ivoid MergeSortNonR(int* arr, int sz)
    8 H- b0 P* U  ~. w{
    / K2 k0 v# u- k. ?3 S    assert(arr);# B4 U1 E7 k" Z. n. Y

    ' ~+ q  J7 w# P& M! e    int* tmp = (int*)malloc(sz * sizeof(int));# v1 r6 N5 u+ |9 S. P" ?
        if (tmp == NULL)$ x. h6 D  T# }9 g
        {
    6 o% k" \3 k4 [8 J/ G        perror("malloc fail");% y. l! w0 w5 r7 r% l
            return;; s  q5 ~" ^2 R5 ^/ ^' z
        }
    " e; N( ^! t1 h/ i9 Z$ Y# _* V4 M3 T1 b, Y
        int gap = 1;3 g/ [9 k% [8 @
        while (gap < sz)
    3 j, H' L% j' L2 }    {
    8 }9 z( ~' S; c" t& G        for (int i = 0; i < sz; i += 2 * gap)
    4 a8 p2 l" \9 P# h% y) I. H) w) p        {
    6 n6 j4 s0 \8 e' i$ j# O6 ~            int begin1 = i, end1 = begin1 + gap - 1;
    # C# t4 n- b2 @, D, U3 s3 h: o            int begin2 = end1 + 1, end2 = begin2 + gap - 1;9 X# f  y" r2 F: ?* N! n- f. A
                int j = begin1;
    $ G# n  F& l, I% Z: M* G; q2 x7 P                        //越界检测
    " F. e7 Y2 C& }7 P/ ~$ G) Z" I            if (begin2 >= sz && end2 >= sz)3 A: ]1 \: k- ]2 S0 C" Z2 c+ k
                    break;
    3 X& \4 l5 F" s, B* R            if (end2 >= sz)8 f4 i4 w9 P% |9 ^( d$ f  J& V" I
                    end2 = sz - 1;& Z- h* O& S8 H5 W% O
                //归并
    : C8 M# q$ z! c( ^2 }            while (begin1 <= end1 && begin2 <= end2)
    ' Z$ |* j4 m$ |( e! L# P+ q% d  a2 q            {. u) [2 b/ W+ K$ U# g' v
                    if (arr[begin1] < arr[begin2])1 }. o9 A; t) t/ f5 s
                        tmp[j++] = arr[begin1++];# a( `/ @0 t" c1 k
                    else     
    ) v7 |& b7 W  w5 [! j$ ~                    tmp[j++] = arr[begin2++];
    8 K2 k6 X% v  G- s% n            }
    ( m; |4 Q& D0 |* F( @5 ?2 `0 \; F
    $ L; _: R' h/ x9 O& Q; p0 W4 d            while (begin1 <= end1)
    % o# W* o( b! u, D" t                tmp[j++] = arr[begin1++];
    ! i/ H% Q; V6 g% c+ Y2 W  f. P            while (begin2 <= end2)
    ! N" b0 x* a0 Q  y" C. c                tmp[j++] = arr[begin2++];6 u( M# o2 t, K3 y: X, [& m
    6 v) E) V! |+ R$ a  Y# _0 [* d
                //拷贝回原数组——归并哪部分就拷贝哪部分回去* D7 y6 {$ m7 |/ O& _6 U
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));$ ?9 Q% D( J' C, L# w
            }
    # {4 O1 M& y' i, \9 R2 B& Z        gap *= 2;
    % n& G6 e! n2 }' e1 Z    }
    3 G7 e& G. |3 |; i8 v
    & c: v. `9 Z9 m1 M- R& z' e}# c' ?5 X. u; p6 |. u
    $ `5 f: C" e. a4 o5 \' g
    1
    8 _  Q+ K: ?9 S1 R: z: N2
    9 B5 g, j7 T: F$ Q  R- p3
    / u) x3 f# m6 d43 H8 X" N+ ~/ q' o. D# I9 D' V$ P
    55 I5 a& G9 q# {
    6
    $ T) b2 d& M: k4 B2 T6 Q7
    5 L% X/ s) j# }1 K3 R4 F; T4 [83 c7 x* r& E9 a$ l9 q( r" B
    9& I# p+ U# e; o* t
    10$ B+ y1 G# \5 Q# O* R
    11* w) x2 N3 i3 M! n6 ?; J9 i
    122 E2 h- q6 Y" V# ^/ I7 o
    13
    6 k0 H/ k# g1 n5 g+ V2 s, X+ M3 ^14) M& _' p' q8 b$ Q- B5 R; |% `
    15
    + c0 S7 E! v% B2 k  t16' i2 d6 o( G; ]$ P0 |
    178 R! I# R* e  X( S7 H( U
    18
    . K0 S7 \/ Z7 e7 _$ _6 T7 Z19
    ) i0 j/ L+ J' h20
    : d; E! ]+ K  j/ l: y. T7 n) N21: U! a/ r* E+ v$ {
    227 [: G1 y8 m7 j9 Y: ]9 O0 ^7 D
    232 b/ k! h4 `7 X0 |6 X
    24, g% f5 r# [8 Y* {
    25
    + C# g3 X, @( p26
    8 R. {* g  Y- p( }27& z/ `' x& j  I2 P4 t/ x
    287 m2 r) m* y* R$ ^3 g4 |  Y
    29
    $ m8 X1 I( E  n30
    4 V! A3 p# O8 |- n) M5 s: ]# G* a31
    , Q) ~) s# m- ^: ?& ?; S: h9 E: Q32$ u4 R+ A& D! E6 S/ I% ~% T
    33/ k; V8 J# L: d- e$ T0 ?+ S
    34
    ) L% b/ y$ _0 ?; n6 ?2 l5 y, g: R35
    ' z# p' g1 P  A( c5 e36
    ! Q$ G- q9 k/ X$ ]# r; n37
    0 D) e3 V: d2 P' a. j) |5 T38
    " |8 w1 e' u8 ?2 Q6 _" R% S39* F2 F' [! I( v, k" c3 v" O
    40
    & Y7 w& |" D% [- W( \2 m" A41
    : o9 E2 y1 Y) q9 F. u6 j42
    $ m2 `: j2 l  \+ G1 y  L3 D% H; `43# F9 Q1 L% q4 \9 V
    44* @% P% P# h. d* ^  m
    45
    1 V! ]% E; l; X1 G归并排序的特性总结:5 o; R8 C6 i5 ^% \3 I

    1 _) f0 j8 K, I归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    ( ]! r. y1 k7 L7 o8 L时间复杂度:O(N*logN)
    0 t. P5 Z7 P# d# ~空间复杂度:O(N)$ ?0 L5 I. P3 d, \
    稳定性:稳定, B- L. S, k/ O) B

    $ B3 M0 s, K; S————————————————
    & i: H7 F" U) Y" o( E. f8 A: @版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 G$ Y6 g& K8 H) L% `( Z9 y原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657+ V: u3 y! n; A% ^6 h, c+ c

    5 }+ ]( V9 J8 ~! Z9 G7 V
    9 W  f# f/ _, `+ l/ h* e
    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-14 03:19 , Processed in 0.450357 second(s), 51 queries .

    回顶部