QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3317|回复: 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 ^/ A3 Q  T( a4 Z
    & i. B! s8 X3 P/ n; `2 X前言
    3 Q9 d0 o6 {) r$ g本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    & X6 }! E$ T# R% t* t' ], f3 Y& B* B' u- @! q
    归并排序* j) U/ E) v7 Y1 j5 A
    基本思想9 M6 N" b- k: E1 e. P5 @& K8 d
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。/ u/ O; J8 s) t1 }+ e" V( Y! Q

    ' z  h1 z) x1 @  Q( H# f5 q/ r
    : ^0 C: K$ A. o& t1 H
    8 \) p/ ?4 X# j6 d8 ?​ 合并的思想其实和有道题目的思想如出一辙:
    7 c" D" D: O9 m: j- c& l  G; @  e8 ]4 P- ?9 V, Z4 n  `

    8 u2 t" H, j. \% e
    8 P# y* f8 }, e6 c; J& q8 V  l2 F​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。0 e9 z" t2 j6 F7 ?5 r# \: j
    $ x* _% |/ x; ?! }
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)], D1 H& G8 {& j! n+ f# r5 T- V/ `

    3 d' g' `8 c3 B5 m: aint* merge(int* nums1, int m, int* nums2, int n)* V; ]$ g: a/ }8 i7 j; z
    {: Y5 a4 Y/ a; j: s  r# l5 ^( ^0 S  V
            int* arr = (int*)malloc((m + n));5 e$ f& S3 i" J- {" Q4 g
        if(arr == NULL)0 |- z/ F1 K4 V: ~# C" a4 \7 s3 p; F
        {
    5 x2 [  ]  U5 N, [+ X" \        perror("malloc fail");# E5 B: K$ P% L+ N7 q) w: I' Y
            return;
    ( e) x# c; H/ M9 ^9 _' f    }) Z# [$ ~* @. v/ s

    5 ?. T# s% @4 [) h; `' h$ G: G- F    int p1 = 0;
    3 o& N* z9 U- ^  F" x1 P    int p2 = 0;
    / I: o7 n1 E- s  ^    int cnt = 0;
    , @& b6 d' _$ o8 x; |- p- q" T    while(p1 < m && p2 < n)/ ?  m* s3 K: r
        {
    6 e% G7 @4 N' G' H        if(nums1[p1] < nums2[p2])
    2 g2 _) C+ h& B' K# L  c) T        {2 l2 k+ J; ~+ J% b' w2 l3 D
                arr[cnt++] = nums1[p1++];- R9 f; B: d% y9 m) h3 K- v
            }
    8 x' R- K& d: U% N1 D* Z! O5 {1 V        else# M# a* ~( J( p: j% c/ r
            {: P5 z4 k+ T4 M) _: a5 e
                arr[cnt++] = nums2[p2++];
    5 r& i# \; J8 u' h* ^5 }8 ?. q' [& ~        }
    $ D' L7 G$ G! \; M# B" Q$ E, V: l) T    }
    3 ]0 H) z+ O( M0 E" V1 C+ C2 c0 }    while(p1 < m)
    : A9 i* I( W" p        arr[cnt++] = nums1[p1++];
    / u/ U6 f! A. G3 a- n5 r3 m5 D( T- a& c; \/ q: d2 [3 U/ c' C
        while(p2 < n)8 H1 Z" k& m" f- J) p9 [
            arr[cnt++] = nums2[p2++];- x* o: D9 A6 M9 h  p' p
      V% |# P$ [. y9 ^5 w
        return arr;7 P, g; D* e: r" |/ d( y
    }7 R+ d7 H% @6 x* q

    ' F, c$ J6 y. b  i, B& B! |1; N/ |: {; l; B- \9 Y+ W- L- m; `6 {
    2" R2 n9 m: t$ z. r' B
    3
    6 f/ f6 G' z- b! m% h0 m. R5 ?4  X% B7 k9 I8 D# e, }% S
    51 p. }3 k5 M2 }; F! _* r$ l" u, D! @
    60 }, o5 Z! [( q/ j4 j
    7# z7 l4 q/ [( N) p; S
    8
    ; O  w2 K( [1 W% \  M; a) e& e9
      C0 M& u0 N  w/ K; ~6 @10
    0 a; o$ O4 C9 L5 J- F( V11
    - ~& D9 H4 w! O3 ]. ^7 i; [% P9 ^12( y: S: J  z, S4 [
    13* l0 K' n( ]  I9 ?
    14
    ! l) y6 f# V$ y: {150 L, W6 z' m9 w2 @
    167 Z3 M' Q8 H2 l4 G
    17
    9 N8 B. K1 `7 }4 R. U: X. F18
    ) m3 y9 c! L& _19$ V$ n% ?5 Q. M+ @, n
    20
    ; c2 D3 [4 [' @21
    2 C& A# x9 S4 ~' h# h& x221 }1 J6 n' L) u! c4 l
    232 [; ]: z' H( j5 P
    24
    ( l/ ?5 D2 K. B" n: h0 y25
    ) H3 Y7 I- \2 e1 y5 I+ e; e+ J( U26
    - g+ g  n/ N- g4 Z1 N: Z4 l4 C27
    % i9 _  ~$ C2 @28
    % t0 \2 n7 O8 f- C" N7 Y29
    $ O' e; u9 E  d5 Q0 C( R, _$ a: m305 Y% h. j( y& ]: X4 k* _
    31
    0 J$ ~2 L8 U/ J5 @( P+ P​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    5 I0 x) q. x8 e, @1 s& ~$ y' ]& G, }( R, {6 n/ a: O+ d
    递归实现
    & ^/ w  m. l) U* P​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    + u6 U0 z5 {% k9 g! o
    . b! V: ?5 n8 \, V- f# X9 F1 O
      h, D$ o% B# W$ I8 v4 ^, G6 g$ f* p  Y; D  q* q

    / }& B& K7 X5 t0 e
    ' k5 r/ E7 x- j' a7 l+ A8 ?void _MergeSort(int* arr, int* tmp, int left, int right)
    : v& M6 P8 W  A# w6 P; b{6 b8 r' x* J/ o* }
        assert(arr);" i, U( n1 u5 T* Z

    9 \4 y  H1 f2 ?  ^( [    if (left >= right)//递归结束条件不要漏了
    ( M/ r7 x; W- k( _! _. x! F# C        return;
    8 F6 ?# D* K7 l+ `# V3 M; u% l  v  ^  e; v; i
        int mid = (right - left) / 2 + left;
    0 M& g7 W3 b+ T" m$ j* c
    5 Q  g. N, J# s( {& }( G    //划分左右子区间[left, mid]和[mid + 1, right]
    & N! K5 ~1 a' h( B. [( J+ ]    _MergeSort(arr, tmp, left, mid);6 q  R5 n- E& q
        _MergeSort(arr, tmp, mid + 1, right);8 y5 R- `/ A$ k$ u- C9 u
    + G* l9 t3 c2 j& ~: t: o
        //归并
    & C# c& H7 `! O2 C6 w* |    int begin1 = left, end1 = mid;
    & i3 b* R1 D3 M+ R- S. ~    int begin2 = mid + 1, end2 = right;& c7 ~* H3 ]; P, }' A2 E4 l
        int i = left;
    ; C9 `" l4 ]5 w$ u    while (begin1 <= end1 && begin2 <= end2)
    6 e. `2 g' g* D8 S  B. n    {( l7 z" f0 ^9 K/ e
            if (arr[begin1] < arr[begin2])
    0 ^8 Q& [; }: `, ]  L# l6 |  E/ I            tmp[i++] = arr[begin1++];$ U2 y! }+ ?( O( ?# _
            else
    # ]* J& `  h2 r% B7 R# x* _            tmp[i++] = arr[begin2++];
    / e6 S# J$ M- n& j9 l" v: m2 L5 J    }
    9 w/ P' d! x' A4 X! I+ r6 |; h' S, K8 O8 E/ v( d4 S) H; `
        while (begin1 <= end1)
      u( r- t, E. A! X5 z+ t3 ?* L6 r        tmp[i++] = arr[begin1++];$ W% a! L0 l5 H7 p1 V# F
        while (begin2 <= end2)
    / n8 k: o7 a8 p5 L6 z        tmp[i++] = arr[begin2++];, [: J1 U8 b6 }7 G$ A0 u
           
    ) Y6 M" J4 i3 k+ F, ]    //拷贝回原数组——归并哪部分就拷贝哪部分回去0 R9 \. u$ t& r( G
        //而不是拷贝整个数组回去
    , L- X5 C+ W2 G, ?    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));  ]& D- y! E( y3 k7 i) B
    }5 `0 r8 w" x6 ]0 F4 g1 u
    6 a2 x% {0 w1 G9 v" c
    void MergeSort(int* arr, int left, int right)5 @. s$ i: p, }3 J) R* q
    {
    # F/ Y' r4 a8 `3 @, T8 a5 X    assert(arr);
    $ n9 [/ l0 \$ v1 I
    ; R- d9 |6 y7 U    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));% l. M0 l$ i$ G% F  W
        if (tmp == NULL)
    - {9 j3 M$ s6 M' D: \, x% w5 U    {- E& C8 {. p, W" Y5 `
            perror("malloc fail");
    / i8 x3 h) y# S# q5 z8 [        return;# ~0 V2 o7 Q5 Q/ z; C
        }
    6 h1 a# @% e6 j/ X
    , ^5 w! r# W1 @. a    _MergeSort(arr, tmp, left, right);
    9 X6 K- ^: n) k' q# K" a" s# q
    / y: |' e( g2 f/ ?  ?    free(tmp);  _7 @! {* k. x+ ]. I
        tmp = NULL;; S" u0 ]& j+ Q  u, Y3 k4 e- ]( `
    }
    % l# i' j1 a6 }+ G
    2 @& t2 A! M( l1) Z8 S: ~: j( A' c6 u- u5 @0 _
    2
    % T% o. Z, {+ l. M6 C' y' x4 g3
    ! z3 q$ G/ Z" b) I& U4
    5 X8 i1 A3 U' A3 L8 D5$ o  V" }9 T" \$ V
    6
    % A7 |& {1 H. S' j7& H# I, z) L& }( B
    8* A4 E9 s2 E  {' A' a
    9
    : K  `" r" {, L  E10. J6 S- m7 T* `, X5 T4 k
    116 C! c3 m5 I" K9 w2 _
    12
    : n7 \4 [) R% N! H0 ~13* D, l) I  W4 G9 U. P/ d0 n
    14
    5 a) J5 Q! r/ a% R& Y7 ~! S+ |5 o- L# y15
    , @, I$ t  e6 O164 u, h6 W" b. p8 w# ]
    17/ c) l: \: B7 y+ N4 s' G
    18
      X0 O( ?/ `& v  C4 q* b8 i" [19
    9 W- H) ?8 T2 o1 ^; {20: Z$ U( ?3 Y* ?. ]
    21
    $ [$ C5 P7 d3 ]22
    8 p) X9 O9 o; y. q: Y  m  V" q23
    2 i9 \7 A8 n, ]* G1 ~# A24
    * C9 p) Z1 H) w0 J+ B+ Q25
    7 ]9 S2 U* F9 u26
    : F9 G8 Y3 |) X8 m4 h! u272 q6 G0 v) B. `, K! u
    28
    $ h, J/ u* y3 g6 h; n9 r29
    ! n- l" A  o1 k- f* f30# v0 @- l& V& `8 |7 c2 V# ^
    316 h1 D. c5 w7 ]# r5 f; u8 B
    32" }" J) t: Y* ^0 k3 \! H  C% X! ]
    336 h4 c: |0 ?4 ~' }% q# _& Y. X2 D
    34# }) e9 K; A; V; D: G: k8 b! p
    353 x9 L- L, [' X0 l1 r0 ~3 r8 |
    36
    3 k; f! |8 ^9 F1 w373 W% ?/ H, ~: r  E
    38) u* W( `* @2 b) I- N5 P7 `- t
    390 H- y9 q  S9 o0 W/ X( b
    40: @, [: U0 u% r% a# n
    41/ O, c2 o0 c& e! O/ G
    42
    1 Z1 C$ n# t3 i& Q' h$ f43
    5 w3 \: q1 L, r44
    2 x4 y7 W; [. z2 z459 K* E8 ]6 _1 e' l6 w% v5 g1 T& K
    462 u$ E! J: |/ U$ a$ b# ?
    47/ [" n! X" X, D1 b* g% x! A2 A
    48/ D! S2 [3 c+ P0 ?" z9 I* _
    494 D, l3 l  W, M5 D  C! b) e
    50  Y5 t$ ]9 ]! x8 L& A& G# C
    51# }2 Z; r8 {) [0 S& V
    非递归实现
    % m+ `& x) _' Q& R9 {" s​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    ) I+ m$ g0 h6 B5 K( B) a4 U* ~2 f% ^( H6 g1 K( K: H) _% K" `* k0 T

    ' L3 G) A# q4 v. O9 x; b/ h7 J
    $ |/ H6 D- I) e# a$ h​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。: V7 C7 M8 [" K8 m: g* b7 J
    ; N3 F2 C4 w0 y! [; S
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    - J" f2 h0 ], d/ m) p$ \! f; Y$ e# z; ]* N& K
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。) V6 r% X' n" `! d3 u; N- C
    % a1 |* y( m! D" B
    代码实现1 f3 E3 W* [3 W! b

    % k: ^+ T) k8 ], F  _/ s% qvoid MergeSortNonR(int* arr, int sz)4 Q% m+ H+ J" h
    {
    & c& C8 j, D) J' p    assert(arr);. t. a* s0 {/ t
    ; u, E' N8 q! P
        int* tmp = (int*)malloc(sz * sizeof(int));
    7 G# |: T. S( S    if (tmp == NULL)) c0 Z$ ^5 w/ i: R
        {
    9 _" ]* Q- Q/ t+ F  k        perror("malloc fail");
    " D* B- L1 v5 {        return;
    * \  m$ h9 i. r# o5 |    }
    * Z/ {2 H5 V/ H: a# {
    & ^% w. S# v- D# h' q" F    int gap = 1;+ O! b4 q  K  d' [; z" r
        while (gap < sz)
    6 z; w' E4 L' C    {
    - O  Z! m6 o2 @. e" y' s% ?        for (int i = 0; i < sz; i += 2 * gap)
    ; R8 [* m. L- c4 _" v        {
    , t0 J! X; B& ]8 d) ~            int begin1 = i, end1 = begin1 + gap - 1;  F' Q# R8 }, i$ @" i* j' u3 Z
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ( Y& }: w# f8 L5 F# e: Z7 `- Z3 O: u            int j = begin1;
    ! R7 f+ S/ X: ]+ v% m3 \" S2 J) q. ^* D
                //归并" }5 f$ l4 l. p
                while (begin1 <= end1 && begin2 <= end2)
    7 O- `& d# r: L/ v            {  g/ D7 H; O- y: E
                    if (arr[begin1] < arr[begin2])
    9 {  T) g* E) z9 w8 L                    tmp[j++] = arr[begin1++];' V$ s& z" N- U* \
                    else     ; m# {; @5 ^, K, e
                        tmp[j++] = arr[begin2++];
    * g2 G0 [9 _( c( T            }
    " G" H1 D4 W$ z: o/ G# [
    7 K% f( @! `3 `) e2 }            while (begin1 <= end1). Y' j) \: K. V
                    tmp[j++] = arr[begin1++];
    " g& U# i. h' z$ e8 E            while (begin2 <= end2)
      H! I8 w* i4 {7 o" a+ t  B                tmp[j++] = arr[begin2++];) Y7 q" o' C( j' O

    1 j$ m1 z5 D- S* [            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    6 [( i* H+ I  p  c            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    * Z) b2 _2 G% S- Z: c        }
    * z0 u( }; i1 a' Z, I. z        gap *= 2;
    5 G5 d& I2 j+ t* Z" d( g: w    }
    ' K$ j: J. e! l! X6 q$ D1 w& v- C' @- v# p* ]0 N6 Z  j
    }2 P; a: ^: s+ Z/ L6 w

    ! T5 d' \! F; C. z1* O. N6 C9 t2 P1 ]1 R4 t
    2
    4 N! l$ e' {. i/ o' A' F: C: a3
    2 m7 |' v9 _0 C9 C. o4
    & c0 R. q. K1 D5
    , J$ w. Z) Y# Q; m6 {9 d( u6
    4 \6 m  z8 k, U/ k+ q7
    - [2 K5 G) c, B+ r6 k# \) Z8
    0 V" G. j" w5 X$ c5 G. r  B90 O% f, Q, f0 B5 t; m
    10  L9 D$ S7 O0 Q# G
    11
    ; b0 k" g% ?3 g120 j6 {2 A# c5 g! G; [  L, g0 ?
    13
    2 V2 O+ c& v  V8 n, r5 _, k147 t2 o% ]# r- @- w# Z" r( ?
    15, r. M4 e, p7 O/ C1 D% z1 U
    162 K6 p5 Z2 W( x9 P/ D
    17+ i$ {6 s1 N! F' j8 V' v2 _
    18# n# j% D1 O  k- Y$ M
    19
    ) Z$ h' s/ D, v+ j4 ]20
    + ~* ^: k0 u5 ]$ B! _21* h+ N' m& T$ d2 E; x2 n
    22" y) K1 s. e9 A! X; f8 V1 U
    23: X7 R8 f# P+ q( \6 `
    24
    . w' m6 n6 j' [: e25, U' ?4 H& [) e& ?1 V, G
    26
    4 S& `& O0 \) `, e, [7 i$ }* a3 k27( U6 T8 A+ j8 `  W, ~/ v
    28$ T* x3 Y/ t- {0 C
    29: `) r- p- L# u0 i
    30
    5 T. J4 ^* V% d% \+ i1 D31
    3 M/ |& ?6 `$ ~, m/ a323 ?/ t4 T1 Z) N+ B
    33
      M# o7 p3 ^: f7 d. o347 z- `7 A& r5 ]7 L% m5 l( f
    35
    4 S9 u* ]* r% s9 m36
    7 i4 D9 v( w: T. I37
    ( E9 n; q' W7 j5 W9 ^. h38
    ' y, p. k" |3 x39
    # v3 `# {4 V8 `3 y2 j40
    / F$ F, M  y9 U( n  \41
    ) i! w6 g: c1 Q4 P边界问题' W- n  ]# T' _& Z% v
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    . B0 r0 u9 D0 [8 F; Y3 F3 D& R5 N: q* W5 r; {
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    . w5 P& s5 \: b) z! y; w, \- [3 l+ D  z7 v2 O. D8 h

    / a6 y, t7 G1 M! T' E0 v4 x: B0 b( a/ b) @' z# f8 ~
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    4 r' D) ~# Z8 Z& F0 l! ]1 S# S/ O! C& [; w
    第一组越界(即end1越界)
    2 k8 x; [8 S, u1 u& h" |' _# S3 O& z' y
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。) M: c  G$ }+ N" {* Q& D

    9 g, g- h/ h# [4 _: b: U第二组全部越界(即begin2和end2越界)
    - |$ A+ M/ _; {+ I8 V. q
    8 J4 t6 r$ l% V应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    ( Z7 t9 Y# }1 L3 e
    9 a% n+ e$ `2 y, x第二组部分越界(即end2越界)7 D/ F* {. k2 }- v1 P
    $ n9 ^5 L& C; T& G
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。( A+ M" X# G" f6 r3 t- r7 u
    & d' L& x* B5 ]8 \* k7 C
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    3 Q/ \: w+ F0 n. \: o
    / u+ X3 \( ?9 J​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。5 j8 c, h0 Q( ], \
    & A9 ?: i  R4 w3 ^" h- ^9 W
    ​ 拿两个数组试一下:; S/ x, Y+ C; K1 }  i) M. d0 f

    2 o. Y; H% ~0 U. X, k# E4 e, d: ?, r$ V! o/ M) G. x- h# R6 H  h

    - a) w! w% J% E. m. j& v& s# f7 _# D0 y

    % B  |: s+ g+ l0 G( K  {代码实现+ G7 _: f0 a: j6 d& f
    5 K+ N% }. W7 p
    void MergeSortNonR(int* arr, int sz)( }. u( K5 c. o
    {
    9 {5 q/ a/ K; `2 Y    assert(arr);
    # Z  V2 O* z" o8 Z0 y* d6 E) {4 V% u1 c  ^) f; ~
        int* tmp = (int*)malloc(sz * sizeof(int));
    6 p1 G0 r2 Y& b  `' @1 ?    if (tmp == NULL)* I- i1 e, ]4 E, U# H$ y
        {( M# N# ~5 [" R6 F5 l0 v, x  m6 e
            perror("malloc fail");, o  E0 \5 f* {' Y% |
            return;
    - l3 M8 L$ R: r# ]7 {8 E    }& N# h4 P- o% j% y; _3 x

    1 O1 x# b) x3 f3 x) c    int gap = 1;
    & a  M+ Z* l# ?    while (gap < sz)
    5 F1 _  ^/ P* \7 \0 c6 T    {
    / L8 F/ q; E% |' D) q  b        for (int i = 0; i < sz; i += 2 * gap)
    / O; M' i6 [& B% N* _, C        {* r% y( H3 V1 {" w0 L: a
                int begin1 = i, end1 = begin1 + gap - 1;
    # R& F8 G* U) O  J  A9 _            int begin2 = end1 + 1, end2 = begin2 + gap - 1;" t/ A5 g. V* m
                int j = begin1;9 H+ \# ]6 E2 z
                            //越界检测
    & i& Y6 Y' F) U3 |& R            if (begin2 >= sz && end2 >= sz); j4 _' i1 Q/ f- [7 w, w8 @
                    break;6 g4 P* o; [6 Q( N5 J3 I
                if (end2 >= sz)4 N- K$ `( j; [2 o  [7 G4 H' B
                    end2 = sz - 1;
    - z  w' \  L, m* D4 g            //归并
    ; [. v, B& u" t7 N" A( W( ?' \            while (begin1 <= end1 && begin2 <= end2)
    - e2 o& y% Q3 F            {
    % h, Y' A6 j6 S4 s/ o2 E& e' u                if (arr[begin1] < arr[begin2])
    3 n2 P5 Y3 V4 Q# l( Q9 y                    tmp[j++] = arr[begin1++];0 ?7 T& n7 s8 v4 B: ~1 C& a8 g
                    else     ( e7 e% k' _; H1 d
                        tmp[j++] = arr[begin2++];
    * b' B/ d1 s5 e: u) o+ W8 ~            }
      ^) }; T( m2 j; I& {: }1 Z
    $ b9 x/ m; F1 ~2 l            while (begin1 <= end1)
    7 e. i" n; N. v3 n( c) z! x7 B% \                tmp[j++] = arr[begin1++];
    ! _2 g( H. C. Y9 \& e/ K; L            while (begin2 <= end2)
    / F; O+ [# _; V! i6 G& @. x- h                tmp[j++] = arr[begin2++];
    + E0 b' ^4 q- M: j. t4 ~- j0 p& D* A$ v& _6 t+ a- O
                //拷贝回原数组——归并哪部分就拷贝哪部分回去7 N3 n# z7 x: t# \5 _. o* n# y8 P
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    6 E/ E* h8 _; Q0 L; q$ m. `        }* [9 {9 o4 }, B
            gap *= 2;. W; Q( W" _6 G; C# F
        }, E( m6 ~: E1 J# S; J
    # {: q" e/ v- {* u* g( n6 _: `: x
    }
    ) H4 V1 t; Q* ~7 i2 D& V/ s; k- u$ E# X4 f6 w* e5 v
    1% L' b8 P8 U0 H$ R" M7 W& L: F
    2! _3 z5 f5 n2 w+ W+ Z1 h3 w7 g
    3* p3 W) f8 `/ i
    4! k$ V" {7 H0 C+ a6 J2 q* y
    54 g4 G( y2 R7 A* p& L) D
    66 t6 W; B% \+ D2 t
    7
    * G$ i% v& _+ m" k! {# r4 Q( u0 u8# B7 g: p9 X  P! K, D" M' v
    9
    4 u+ D8 ?% e9 Q1 \# b, |- I10
    9 l; ]$ j0 J" s/ [- f- q11
    " w& `& d+ Z; j0 O% r7 f3 k# T12/ |; ]; G  d2 {4 R* r
    13
    7 b* A8 `3 _% V, g7 K: T6 ~1 O14
    2 i7 b) N' |& M15
    " F% D3 X7 U2 H5 u9 y! j: Q16- ~- T# w: w9 i7 @. x3 a
    17
    $ r( d. x" a7 P4 I18
    , z: A) w% N+ \5 {- Z19; m0 k4 @3 I) ]
    209 S  ?7 J# i6 z# T0 H5 e
    21& k. k9 J6 h" v! N: P/ Q5 H& X
    22
    ! Q5 x  V, L+ z3 D: A1 V8 V23
    0 i8 U' Q9 i/ t; p3 f24
    $ s. @4 a6 ^  l5 H; i2 S25
    $ D& M& X, Y0 X' K26: G9 O# n3 m7 `
    27
      O) u# |. C. s28  Z) j7 m7 K4 q7 R4 l6 I
    29
    - `$ R2 L$ I: M4 E30% f$ s4 a2 U- @
    318 ?+ B* Q9 A* a$ Q
    32/ Z9 w+ }  ^7 }3 {% H
    33
    9 U% M' t" K* f" D34& N1 h, O& C' t0 h( o
    35
    0 p' y; T( Z2 j1 P; O  [, K  x# d36% i$ w2 T3 Y$ P- a, Q
    37
    1 V* y: I/ f/ [1 T38
    4 d* S& q7 Z: R0 ~, H: J39
    ( ^3 Z  K( S, a# U40' W0 |/ P) V4 x* X3 G' i% u
    41
    0 r) V8 u4 @* I! B8 Q) c42
    ' h" ^1 A2 [4 y& |6 a2 W* h) m43" u& M* d- W4 C; k7 G
    44
    ! E. r5 S6 x8 i  h$ d) V& A45
    / l% h2 e/ M! e  t0 t归并排序的特性总结:# a& o8 s& A+ x" w0 ]
    ; w6 M. f5 N+ J3 t
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。8 l4 o% J3 Y" w! e) [
    时间复杂度:O(N*logN)
    * X& B; B  {1 C( u# r: H) q/ o空间复杂度:O(N)
    ) s" r' P" }$ r2 r稳定性:稳定
    % u& Z: J* A2 x* w- H- c% K+ O
    ' k: |% J+ F7 w————————————————
    " y: @* C- h, U版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, R" s# i5 K6 W7 q% ]
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657; K- t4 g7 b* Q1 o/ k" a9 y' f
    * @' b+ e5 S6 U+ ^- o) H

    6 r( J" u# s& k
    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-7-9 11:05 , Processed in 0.279370 second(s), 51 queries .

    回顶部