QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2894|回复: 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的排序算法】归并排序
    5 z9 r; P$ k. b9 L+ R4 }: |) k) x* S9 Z* e" u3 e0 J4 F
    前言# l4 n/ e- |( t+ y6 b' @  g5 d/ m
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。# X8 @, q6 `/ m: i) O

    ( C5 {! {8 e; `2 r5 M归并排序' H9 b2 @8 @4 v8 p% R1 P/ }
    基本思想4 q1 Q' W: }8 M0 `. K
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。% |# }  e1 ?, u  `+ G  g

    . T: Z! y  Z2 {: u' z" n
      ~' x) R: [0 R) h5 C6 P
    7 c9 y! M. I2 _$ y3 N+ ~( U​ 合并的思想其实和有道题目的思想如出一辙:  B! q& C9 P: R, i0 {
    6 u% s8 h% {3 ^
    3 n/ j& a7 Z% y0 M4 p* `+ s

    , g5 }) l8 u5 N, B9 e2 z​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。# f8 X% X% @9 _/ Z3 F- S

    7 i7 p' A8 `& D8 C$ h) x# m[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    0 K/ h! H! z2 {
    ' q, F# ?9 W: Q# \0 G$ Pint* merge(int* nums1, int m, int* nums2, int n): N& d  A* D. |
    {
    & b6 v0 d# C" E! Y$ A3 q        int* arr = (int*)malloc((m + n));. w$ z# J. M5 g7 ^
        if(arr == NULL)1 A% W5 O+ ]* Y( P
        {
    7 i* b" I% r2 t' ~# R        perror("malloc fail");
    & {) p: W$ P. ?' w        return;) H, P5 d7 H- O
        }
    ! w0 g$ W6 |& m" I' t
    ; o( b& n% {- Z, ^; ]+ q    int p1 = 0;
    9 @; X' n: E! u5 T" w    int p2 = 0;
      @  E* W1 y* N8 F1 z) M  e9 `) ]    int cnt = 0;( F) c/ _' j/ S
        while(p1 < m && p2 < n)
    # k( W4 {) i7 ~# Z3 \    {) f7 o" V0 \+ V
            if(nums1[p1] < nums2[p2])
    + j: J! F9 S3 ~% D# `) G- J        {
    : F0 y$ {% W# a4 x            arr[cnt++] = nums1[p1++];
    9 i) c) F: M1 j% }. }  B        }) I) ?! ]' r) ^' v
            else6 j4 v+ A: J) G; A/ i
            {
    4 j2 E' ^: O, i7 d& I. ]            arr[cnt++] = nums2[p2++];
    ! r  o- r3 f! {8 ]        }/ f7 G! d& v& K0 u0 r2 G0 c% E
        }
    4 }# }& w  k. O- ^1 [    while(p1 < m). ^7 L" L& P, R8 A' u
            arr[cnt++] = nums1[p1++];
    ) R0 ]9 T- l4 ?( I( |0 ?( w9 A
    / f" E/ y" v; M. }; z  T    while(p2 < n)! S; g6 N# V3 C. q
            arr[cnt++] = nums2[p2++];1 U6 K0 X. C0 i# j# S. Y% o$ z

    ! z2 H- Q2 n9 \5 r' F    return arr;
    3 p' {, b6 [8 n}! O1 R- I1 f' y+ c+ c8 W% ~
    $ A: N8 r! n2 z  h- |; T' [
    1. {3 J. r" E4 s7 T4 O8 |( t
    2
    " E( r& U$ x! K: r1 r' V' u3! @! t0 I, u6 {' a
    4
    & P) \% c; }! ~: q7 F. b5+ k& [" q" o+ F
    6
    . J! q7 \/ Y! t3 s9 y, v. q* d78 Y! U  e; Z6 ~- @" c* ?
    84 V# H$ ~9 D; m( d2 c% B# }
    9
    ' p1 p7 y: L! z10
    . A5 x, s* O, O11* X5 j9 E& k* L8 N+ i( K
    12$ u5 i6 `% D& ^1 ?, }9 {
    13) j  m; i$ q/ Q
    143 L3 q, s2 g# T7 `1 q2 @8 [9 R
    15" q% V; Z& O6 a9 S; v; b& P
    16" @# j& D; d1 }0 i# U. A. X
    175 m2 \8 f. Q; I" X! P/ U$ f* X* ]
    18
      N  q0 I" p& g9 G4 ?19
    0 X7 `- ]+ O2 X1 ?7 W) w0 Y20
    6 j) p* ?  J; Y, F+ a21
    & W# Y( w  r% q4 I22
    $ q: i% |, w1 m. M23: H, x! ^: Q: h7 E( L0 B7 z7 v% ~
    24$ z+ f* i; q2 o' O
    25
    ' O! |1 O1 {4 X* `8 R. ~' I9 M26
    ! N" e9 z0 m* U2 o8 x27" Y8 b; Q$ ]  ^! }) K
    28
    , x) z) E( P7 T; s29
    % ?6 O3 o: Q4 I0 Y- a6 v30+ c- a. @4 v1 ?9 K. w4 P. c& C
    31
    * \9 ]/ T" L, F) h​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    ; B# V9 F2 h. a4 S+ ?
    9 M: `, i0 R" {7 |3 {; l递归实现4 }9 `- Y7 Y0 N, |  q8 P9 [
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    ) `6 H  g! _! _
    ! y1 g* ~9 ^8 t7 e# R6 C
    ! d1 _( K1 _  l9 w
    # p5 [: Q3 i  |: p1 a0 f! X7 L+ V1 x; f

    ' L' O  s' X2 v7 [# N- `6 C: q- _void _MergeSort(int* arr, int* tmp, int left, int right)
    ! b+ k$ v* @( n  O! x! B{$ b  f- d9 w$ H
        assert(arr);
      \; H6 M5 G1 f9 N+ j# U, z7 p
    : I7 ^5 {: V2 Y' I$ z1 Q2 D  e    if (left >= right)//递归结束条件不要漏了, P4 p' t8 Q2 F$ W
            return;
    / _+ _! R& V0 Q4 D. W5 c8 z
    ( V# ]8 H+ y. W    int mid = (right - left) / 2 + left;
    # h7 _8 t6 [9 S1 j- J* A/ W  V6 K
        //划分左右子区间[left, mid]和[mid + 1, right]
    / e5 r3 `$ }% s/ m* c    _MergeSort(arr, tmp, left, mid);( b4 @4 |) S! d6 w3 t- |! e
        _MergeSort(arr, tmp, mid + 1, right);2 z% |4 l. l. T* _
    : l; k( T4 E! ]' v) S* q4 a- r
        //归并
    & r, u- t; o1 J5 g8 _- L    int begin1 = left, end1 = mid;
    " ~' K& s/ c- V' h0 ?    int begin2 = mid + 1, end2 = right;- C4 T+ p) C. R: O6 I8 y* Y1 I4 K
        int i = left;
    ) Z1 J+ M7 c+ N" f    while (begin1 <= end1 && begin2 <= end2)9 k! B. p; @+ O0 x
        {
    ) C+ N6 y, n8 S" ~% F9 C2 K! x8 L+ m        if (arr[begin1] < arr[begin2])! d: S' r$ D& o3 i( w- M# X
                tmp[i++] = arr[begin1++];8 ?* x" s/ ?/ |* K- C+ ^
            else
    $ F2 H1 Q3 A: Z/ t            tmp[i++] = arr[begin2++];
    ' R. v# g8 V9 a  {9 n    }
    / S2 U& _, c0 p. e& G, N& ]# R) x9 z
        while (begin1 <= end1)
    ( T. X2 }: @+ s% Z/ R( l! P4 R        tmp[i++] = arr[begin1++];
    0 `8 H; a( d4 a) }3 x: l) U    while (begin2 <= end2)8 X: o! a% ^8 C# ?/ Z8 l6 A* f1 x- z
            tmp[i++] = arr[begin2++];4 K! b  `5 T+ i9 l7 |5 M
           
    ' @9 T" e6 v7 r0 w' w( L    //拷贝回原数组——归并哪部分就拷贝哪部分回去' V# Z. V+ t# p$ q( q
        //而不是拷贝整个数组回去9 P- a9 B' U1 e& a2 m
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    $ {. c6 R  p& r& h; j; \}/ Z  n6 n( L" D# ?% [
    1 h* L/ ]( o5 T; O
    void MergeSort(int* arr, int left, int right)+ |5 S$ {0 u9 `/ C0 p+ P
    {: T, h0 a. h) `+ \+ Z
        assert(arr);
    8 Z6 \! q4 Z& m: e  K, p9 W1 W$ K- d# Z
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));9 W) L# Z5 l% {( z
        if (tmp == NULL)
    # Z4 x. t; M1 f! i7 P  j" {$ B    {
    8 H. q3 {# {: k$ \/ q        perror("malloc fail");
    , A' h; p- ^" U3 f$ P        return;
    - Y+ c' \' {' U0 \1 q' W# l% b    }) u+ `. n7 R8 @

    ) r# }( u( ?" F! |3 u1 z$ g; P    _MergeSort(arr, tmp, left, right);" D4 k3 d& j4 u; u

    . o5 ^9 e( [( ?! s* Q# v; G    free(tmp);3 C' W; B; ?$ C# p( c2 O9 [& T# ]
        tmp = NULL;+ G+ b' H) n- d, H  j; L
    }0 B% L: P+ V1 U. K
    5 E+ i: v# v# \2 x3 L
    13 k' T! V9 T( o
    2
    ; O  l" b, `0 E4 {4 ?/ x) X$ I7 ?3" W4 g& N! q: B- i
    4
    + z$ p7 H  y- Q, h: W5
    * P% z# s3 {- v4 M- S: H+ ?" y6
    9 ?% ^# B+ H" }$ @7 o; P  ^" p7
    + R" C4 f& u" Y8 T0 p3 l, j8
    & G8 d: s/ C2 Q$ K0 n% T& v9
    1 [) V0 X8 Q: Z, ^/ @10
    ) g: j+ ~- l9 f+ y! K11
    # ]1 r0 o" _& l% ?12( o& Z! h8 @) v/ H" C3 i
    13
    : R7 E3 n. {6 x14
    % }1 y+ E8 t0 j0 W; C; n% N# l) Y6 R157 b* p, ~" ]5 z5 @
    168 \9 V3 ^$ ?( z  ~  B. M1 M( ^$ d. ~
    175 J4 a( }% P& g* d
    18
    + q( R1 ^4 B- W" g5 L+ h4 k* M19
    8 b- {" ?; j" }6 w" m1 c' K20& C2 _& C' e' K, m* V! `
    21
    # x- H3 k/ C  ~; d222 n7 D: w" C6 ~2 i
    23
    / {* X+ K( O8 v& n6 ?( F% N245 z" N# [" H7 n2 i" C" G
    25# y/ [- l' t& T: U6 y9 S9 U" n& j+ p
    26: B' k  L# }- b, J$ _* j9 N
    27
    + i: u) E1 V) v: G2 w" X. r28
    : A6 F% d# r9 J( S4 z& `( _$ r29" z1 \. h8 T5 z  ~& w  k! ^8 V
    30
    4 U. E" W2 `2 l/ k31; E2 q. e0 ^0 \4 i6 p8 F9 M6 W* T  F
    32$ ?! y- o( Z* k
    33
    5 z, l5 F+ {, Z% O0 F" F34
    * C$ m: J4 U! Z" r& R' ~- y35
    8 @4 S6 y( Q9 |/ E36) h3 U% u& D0 d' e2 y
    37
    & s$ d8 {  K' q* H0 e2 E38- ^, t" j" [0 Q" ^4 M7 u( A1 H
    39
    $ b1 u- X  G2 [# O7 m* u. k7 c404 v: J, n: F4 h" v5 m3 G
    41
    ; u' @# o1 r7 |; V42
    ; y& p# V2 U5 o1 ?) i43
    $ E# A' B; c1 k5 x+ ]44
    / Q# T# ?) h+ c5 X455 N' S+ m% B+ N. `8 i
    46
    3 U$ E- u+ ~/ r47
    ! o  t1 Y* H# d48$ S$ W& e4 X  G9 z9 A
    49" s5 y& r7 A2 q3 X
    50
    8 O1 Q0 v3 h' W" r! V51& d& z' J2 L' e% S2 M* _
    非递归实现) W8 _3 ?! u# f8 R- H
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    9 E* k  }. ^9 X1 h* L7 c, n# l+ w; E3 D$ s" t* {% m5 v

      n( u/ Z0 @4 y4 O9 [6 Y* l3 V. E! H8 Z# `
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    & F7 f2 C4 o4 T5 J. y0 [
    ) i6 ^5 |! s% K3 i​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    % X+ \5 T  h9 \& C/ Z! M8 H. p1 U
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。8 S7 C0 |* w0 a' A
    ) @  d3 B6 P1 H4 Y
    代码实现7 p/ E( l. [0 e

    % M# ^7 U* _5 f% E5 J8 P' j3 gvoid MergeSortNonR(int* arr, int sz)( {7 N& P6 G6 B4 h! W) B5 F) V1 H  q
    {7 p, p; f: {7 J: y5 O/ b
        assert(arr);
    6 J1 I5 [9 x* g% n2 M# E
    : m& X% O1 S  g4 }9 O: D+ `    int* tmp = (int*)malloc(sz * sizeof(int));9 @! {5 L' C9 M2 T2 D
        if (tmp == NULL)
    / p" E1 c, g+ i    {# B2 D: a; o: {  _& `: u1 n  f
            perror("malloc fail");2 m/ j  A3 b$ A$ T# k
            return;
    1 C4 m. h1 Z' x/ N# i( p    }( l1 K, C2 v4 w0 s* r9 S' N* W. w7 T" e0 {

    ( K$ e1 o0 ]4 A% ?9 m. m    int gap = 1;
    1 d6 `$ t4 \( w9 T3 G( P    while (gap < sz)9 R7 Y  m3 S+ F3 a0 Q
        {3 a& `9 m  A' M% e" S
            for (int i = 0; i < sz; i += 2 * gap)1 F0 ?/ e+ W+ p- z
            {
    3 R. i' G- U4 |' P            int begin1 = i, end1 = begin1 + gap - 1;' g) ~* f6 E$ f% D; z
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;- I7 f7 Y" E1 X  o
                int j = begin1;" _' M& `1 u# G9 m% }0 @2 J! a

    % u; w) ^( q$ M1 R            //归并
    7 u/ Y2 p1 c/ s7 z            while (begin1 <= end1 && begin2 <= end2)
    2 `" z5 P- W0 z, e4 v; K            {
    ' c8 C& O% M8 D4 k2 m6 u; R4 L" o                if (arr[begin1] < arr[begin2])1 P7 c" `  K# h, l9 {/ ?- H$ x$ N) |
                        tmp[j++] = arr[begin1++];; i# ~, e, d& s% z7 U! |& R) G  n
                    else     3 B* C$ G) @4 U  b' s* J& G* Y
                        tmp[j++] = arr[begin2++];
    ! G( D2 w$ A+ P/ X            }
    4 f( g. D1 W8 V- O, L3 t# O: k, D
    $ u* i2 u  @' ~% t5 s            while (begin1 <= end1)
    / X2 |$ \  e  k                tmp[j++] = arr[begin1++];
    & y. Z1 E; j! ^) L" p            while (begin2 <= end2)
    " p9 F; p8 g: q                tmp[j++] = arr[begin2++];
    & @6 p( ~9 D: C5 }& S
    6 d: l: q8 L: K7 t* }$ a. |6 v            //拷贝回原数组——归并哪部分就拷贝哪部分回去& t# N5 m/ G. s; d$ T- K, d; Y
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));+ |. h$ w! l" P! h; z4 H/ C8 y
            }
    $ W8 }# d  a* x, D/ Y' P1 D4 d: S# J        gap *= 2;
    5 }- E+ _9 |8 n; Y( G    }  c# E1 E8 F8 o& n$ p

    - `7 |9 e" m4 \5 c1 J: ~" v}
    ' y" ], k7 z9 v3 x- M/ H+ \  |+ V7 B7 q& P+ Y! x
    1
    8 p7 E  `3 E0 R0 g- V2
    9 \' q+ L' X4 b7 a. j7 P3
    ! _( ]" `7 n; B8 Q4
    5 H! u& l! W+ R) X5 L- l* v2 J5) }3 F7 k* P; p- ^. A# h& b
    6
    & Z1 j# q  x0 s) l+ A# e- N7
    8 F3 P6 Y) i* s8/ n6 M1 J/ [' d2 v" t
    9
    # ]* E+ J1 m# a* Q& J8 _% N  d8 Y10
    9 Y+ A4 C4 o: k9 J' @# m# A. ]. Y11  T+ R, @: J+ ~' [  B/ z9 d
    125 F* a: o" l/ U; V" ]
    13
    # D; I" h2 \% n6 K. @# b14
    3 b$ o" [% M! s- }  A15
    5 g% E7 V  @, k0 X( c16- G/ o& y6 W  e9 l4 n) R; i
    17
    4 T: x/ `0 s# m  U! ?18
    ! r5 G* \: x9 S' G19
    2 [, E& n. y0 M3 b# V# w20
    . Z: [2 p1 i- `+ v: d* v, @21
    2 Y- \3 A- \, X22
    5 g- D7 {% H! l0 r  ]23
    6 Y$ J/ B& s4 `' h7 h% n247 P" t" d; o  B* \1 I; w2 m1 [& o8 @0 u
    25
    - T8 H+ o  J3 p( J( U, S: @7 u9 q& o7 o' t26
    ( x3 t, u( e; G276 Z' u, F# V5 i, m/ o
    28
    % C* T, x9 o0 Y9 _29' U, [6 X8 t! |1 U" `$ D$ w/ F" Q" c
    30& ~4 |1 A2 O8 F
    314 ?% [  N! _! x$ }9 v" v) g3 Q
    32
    ! j+ c7 |" v. M33  z/ C& M4 g1 N5 U! r$ L8 U
    34
    " Q/ {) M; f. F. O35
    : S7 {* P! k0 n; h1 [0 D36
    0 u+ i' t! |$ ~9 G, R37
    # {* X7 K; I9 W7 i38
    1 |% c: f/ k$ B7 P39
    5 x' Q, S" `8 D' P; I40* B2 k% b$ o* M# f( D
    41! H: A; v. b8 z& r4 b8 |% A9 d
    边界问题
    - N: P1 F/ j: Z0 ~% O* S( m​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。8 ~( ~: l0 q2 A' _

    + o4 H* d( q! E% o. `举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:) g9 g8 g; h+ F0 e6 o  ?& t
    6 v- S5 \- s1 N0 c" q2 W. O- S3 l
    $ h2 q: P' G6 @& F
    ) H) a, H5 p' M. b  g; c  b2 W- }
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组), C4 G4 Z* o) x9 A9 ]
    + B6 R$ r9 a( N: `
    第一组越界(即end1越界)
    $ A/ B, v( J7 P7 q4 S) }
    / A, _  _" m4 {0 V+ ~+ x( P0 u' T应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。) }. l! u- y, s  Y- I( r/ u

    5 ]7 l, ~5 H& |: L第二组全部越界(即begin2和end2越界)" z: V: T$ {( X& U9 K

      o* i$ l7 B7 i0 Z, q. i6 \应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    # W1 s8 q7 K/ l- b  v
    & e7 x9 H! B. u4 S第二组部分越界(即end2越界)6 `: R/ `# K3 \# J6 J5 n

    . N/ |4 r# A/ i# J, ^应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。  s( C+ R8 ^9 Q% k1 S
    / `# O( p5 k( L! S- C/ \- |& r" K
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:% C* g) e$ o* `: m, C

    * D% e' x9 S; y5 h0 m0 ?​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。+ K! m2 R% g: T+ m9 d

    . D3 w0 ?' \2 H​ 拿两个数组试一下:
    / a" ?) q2 d( c4 w  T: D, m2 _& Z
    0 R6 H: [; f1 u. X& i
    + f; H' b5 W- t0 r& I9 G$ F# [# p" b* f

    2 b0 A$ o5 d7 E( @3 D$ t
    ! f+ U5 @' [1 s代码实现% H, k4 r- F* f7 @
    6 G( I9 ^" a: R" \, O
    void MergeSortNonR(int* arr, int sz)8 {" O, O' G* b6 g; |
    {
      o2 _  x! t- J& Z$ W6 o    assert(arr);  b6 K( A2 `" O8 W" }
    ' p3 J& r6 a5 m0 y+ Q) K
        int* tmp = (int*)malloc(sz * sizeof(int));
    ' l$ s9 m: G: b! e" Z    if (tmp == NULL)
    7 @4 K4 v7 x' Z$ w+ s  N    {/ d0 Z1 r1 L1 k) V
            perror("malloc fail");$ h/ D7 O: m! C9 x3 Q3 A
            return;3 F3 l$ m) N) I2 n5 T( F1 F
        }  j' }6 s' r9 L
    + X( f  i( q5 _
        int gap = 1;$ @9 L" a6 `' w- c" k& A9 t
        while (gap < sz)
    0 V3 h3 M0 w' s8 v+ [) f" l+ G. m    {( m% c9 R1 ^# n1 V# X, N7 q
            for (int i = 0; i < sz; i += 2 * gap)
    % C2 `* U  @$ i" f8 R' k* W        {9 {; o, q8 s7 Y1 L. B! L) w7 V
                int begin1 = i, end1 = begin1 + gap - 1;
    5 I4 V% J$ O7 L# |- Y            int begin2 = end1 + 1, end2 = begin2 + gap - 1;$ s3 a& O1 v% g6 |; W  r9 M
                int j = begin1;( z. f2 l/ F0 F/ x* k" J; n
                            //越界检测! F; X" u% r# N7 ~) K( d7 p5 ^& ^
                if (begin2 >= sz && end2 >= sz)
    / u1 s; w7 s: S4 p                break;
    6 I! L( X! P9 V* @            if (end2 >= sz)
    / H. B# h' ?6 K+ i: [9 P                end2 = sz - 1;
    ( c) u# X9 V3 I+ n2 Q/ |) H6 K            //归并$ M  y5 \$ Y2 q9 M" H8 g
                while (begin1 <= end1 && begin2 <= end2)2 `) F" R% ^( `6 F& w
                {
    8 K0 Y9 y3 h0 v3 ^                if (arr[begin1] < arr[begin2])# ?( ]- A4 p) O5 `3 L8 Y
                        tmp[j++] = arr[begin1++];' P& a  _7 v3 L
                    else     1 E* x2 ~; x+ l; P. [8 E
                        tmp[j++] = arr[begin2++];  R6 i" T, U  t+ C3 l; X# W
                }
    : [4 T. y* c1 k2 ?
    - E' R8 r+ c+ L7 Y" P. n            while (begin1 <= end1). w  ?. k5 H: i0 ]' S2 s* _4 R/ C: @
                    tmp[j++] = arr[begin1++];
    # Z4 E$ [" G9 f+ D            while (begin2 <= end2)+ @3 N- A! C; P/ i+ i
                    tmp[j++] = arr[begin2++];
    4 z2 O2 Y4 h4 \) K% {: w
    - b# P# _, L/ G            //拷贝回原数组——归并哪部分就拷贝哪部分回去' q% i; e. |: @" a9 T  n
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    8 j7 R5 K; p# t        }
    7 R9 K8 t* f2 g" ~! R' m7 a+ @        gap *= 2;. C5 y! I4 S4 ?9 @) k. B
        }! u( U. N$ H& f3 c( N
    ! c! k: H, X: }2 k4 \7 |/ x
    }
    2 V/ T7 a7 x7 B; O2 Y5 H0 ]
    & [3 X* s! ?) _% S' V- w/ U13 k! V9 D; u6 o/ {7 @
    25 k  p: F) c  [$ J8 G
    3* d5 k# E9 s0 O
    4: P: k& z9 t& e# X! c
    5
    5 ^4 Q2 l/ N' ]. ]" u68 R6 K* u4 v' ]
    7
    2 u" T- Z* z5 J7 y5 n! E8
    : \& |1 A3 e" ^% ?9 m9$ l, }& X8 C" J1 [
    10
    ) c7 K0 y  _" o- a7 Z3 |! v11
    * m; S! R+ h5 F% o12
    8 |. H$ U$ M6 A: W( S2 A3 M137 P5 {' O: b  B2 G# _- f
    14: ^, Y3 @3 C' b/ S; D$ |& D3 m& u& B
    15
    $ q; u% `  F# C9 C6 ?0 i0 m3 ?163 `" G' i! C" d  Q6 ^6 M% u
    17- }6 v4 p) ?% P
    18
    3 g3 {5 E, H2 G  k4 j* x8 z& U19
    + k$ t/ N3 J# u. |9 O" F9 _+ E20
    , g5 n/ X7 o& W21
    $ k: a" J: y2 S$ s22
    $ w, @+ Q4 C" M. v/ }5 a" ?231 Q* x/ H7 X& B* X# ~" m3 P' Q
    246 v9 M, I7 U# z' i
    25# l9 j: J  k0 f
    267 E1 H: Q8 w9 G
    27
    7 N) a) l0 h$ i+ l0 Z6 g28
    0 V$ n" d1 [2 p8 {. l0 O+ B29. q/ X- [, Z+ j" q3 t! v3 I
    30
    # z' d! o& Z1 K8 w, y2 h7 d0 J31
    ) v# g4 K8 \# g+ v- L: Q32! S, e$ d$ f0 [( H8 i; m
    33
    - s: B1 X0 {( o' B34
    # Q; n# t" U5 a: k: M% f; U0 a35, \1 n( X5 }* o! J/ G
    36
    ' V- K$ D3 q% k9 t  M1 ^$ C. s$ N& L37
    * E" U" e$ W* r9 s380 N  d8 f4 y+ O
    39% ]2 @' ?6 Z4 D# V) {$ u
    40
      J; x- _+ k( Z6 e9 I1 Q41
    1 ]8 F* |% O( I2 R42$ S6 g& F0 A) F9 G
    43+ m9 p9 p* L+ O
    44
    0 u  M6 }- X2 G, r7 h. Q45
    $ w" p9 m8 [2 n* H3 k5 \归并排序的特性总结:5 W; Q6 z5 D% [& ~
    - n6 M3 A, O! @2 O, d: `$ X9 [: Y
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。; i7 C4 g6 T) k9 Y1 B. b
    时间复杂度:O(N*logN)+ v, p8 p  J7 d: k
    空间复杂度:O(N)* C; O: r1 R! W
    稳定性:稳定. Y$ S# _) x; L( I1 q

    ) Y, F, L4 @: @- e————————————————
    9 y/ K1 W: d+ t3 C) s' _版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, G+ x1 i: @1 G! s
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    / @4 R0 V: j. P+ [8 Z
    ! P( g! |# E4 g+ q) ~3 b
    9 g3 F8 g  E8 M. A  c! G
    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, 2025-11-8 18:04 , Processed in 1.338355 second(s), 51 queries .

    回顶部