QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3273|回复: 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的排序算法】归并排序: B  ]$ A2 G, n3 j
      t& h  z5 ~" p7 y; v& a. l
    前言  p% d& U4 P; T- J& r
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。5 a( O3 q1 O& o4 `4 q

    ( j5 ~7 J6 M. F归并排序- o9 l2 S6 t! t1 r0 N7 E3 i$ E
    基本思想
    & m; c/ Q9 n8 K# z; C8 d​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    1 K: F- I6 Z4 c4 M) Y4 x& k2 J7 B2 p0 }- d, l- y1 A* Q

    * o* _+ {+ {# a, G4 N4 s% E$ ]6 K  s" G
    ​ 合并的思想其实和有道题目的思想如出一辙:3 B3 K/ U) r- f2 A, f0 f7 C
    / U: ]% f8 A, D

    / w5 h) |' H0 W2 |: s3 i8 t8 U# T% E  g$ ?; M
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    4 y" j1 N# \. \5 W+ n5 E7 [0 ~
    1 {+ ?- j; f% u2 T0 j, M[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]/ M$ L" R# P* V

    , u# }+ `, k$ \3 q9 ]int* merge(int* nums1, int m, int* nums2, int n)
    + Z1 h3 D0 D# @) s{7 S$ u* d" i1 w  i; O3 }
            int* arr = (int*)malloc((m + n));( L+ [6 a: a7 `
        if(arr == NULL)
    $ n) u' @: E8 B: `) W1 C. T    {! J5 I: \+ E& X) k! d
            perror("malloc fail");
    $ m- L% _. ?. l' D        return;# D* d/ V# b0 t& F3 H' w
        }& x$ n7 e. @, t# \( H, B
    9 h- O& ]' M  H1 A2 U( d
        int p1 = 0;" I5 G6 x) T& P
        int p2 = 0;
    - @: G  s2 x+ @    int cnt = 0;
    : s/ W$ Q! |9 e. l0 m- K    while(p1 < m && p2 < n)2 U9 e. [+ @0 W3 s9 g1 B
        {4 Y$ M: ?1 Z, Y
            if(nums1[p1] < nums2[p2])
    . t/ j5 w  x  t# X2 H$ [/ s& l        {
    ' R1 f- H0 |: e: y            arr[cnt++] = nums1[p1++];
    0 `- A+ }2 s! L, o8 W* x        }. g/ d& T$ _5 I! y+ M
            else
    + L- g4 h* D# j, n0 M3 n        {% c. J$ ~4 H1 f1 A* K4 n* P
                arr[cnt++] = nums2[p2++];9 c7 Q/ f. M/ |0 t: S) S& q
            }
    & x7 l- U; l1 n  v; [$ j6 [- |    }+ J$ a$ T1 A! I/ X0 \6 J) q9 l% k/ ]
        while(p1 < m)& U6 {. P+ E: n9 P9 v# {
            arr[cnt++] = nums1[p1++];
    ) G9 J  Y1 @" s- ]) F/ C6 l( ]* ^! Q3 x2 _$ S# Y8 f, m& |
        while(p2 < n)
      K1 F  r1 e2 B9 b- F        arr[cnt++] = nums2[p2++];4 q9 v2 P4 J, [) T5 j' r
    $ t7 p, J5 ~* L
        return arr;
    . c/ T" c1 n; x" v  ~' J}
      l' q- F2 U( v) A- ?# L* E' p5 m7 b+ V1 M: F7 y2 o) {" }5 \  m
    18 ]9 I$ Z! _1 d) B, {4 j
    2! Y% N' j/ F7 h0 L4 y9 b
    3
    4 s8 @. @+ j8 b' {44 V8 l+ U* W; b( W1 X7 q
    5* w' `9 V9 O0 I. e0 b% M8 _5 v( u
    6
    $ M5 u6 A3 H7 ?/ x: H0 H. h5 N5 u7
    ) a4 s4 d1 k7 C. {8% n' }9 I! U' T2 L- k
    9% u8 @: W* }; Z: |
    10' Z; m. C9 W- T) d6 @4 b
    11% E8 k5 z( u: E8 {
    12, J1 z: M5 Z. C5 a4 \  R% t
    13
    + x* G; z* E3 |  |* y' z14
    4 R% a6 R% @% K8 C2 w& \15$ k$ h, s- m" H( `/ t: z
    16
    . r% K9 d( I0 ?' L0 ]/ S5 y1 e17
    ' h5 k3 J. N) V1 }4 y- |. u/ o18
    . h7 K5 P/ m# e195 Y+ W4 {% Y9 i( i; y
    20
    # C" b+ r0 i4 }) `21) i8 A" p2 O/ E; H2 K7 Y' k
    22, z* D# Q9 O+ ?: E% r; G
    23
    8 Z% B# B& T) D24
    4 {: r9 \* c% I" g; o25. {7 S+ j% B* {. C3 X
    26& Z8 e  `* ^% y
    27( Y2 D' x& l3 Y
    28* |, h+ s+ f. o1 q
    29
    6 W8 S2 c8 ?1 d$ ~4 k. b$ |30  B6 q/ ?3 d8 R) u  w
    313 b' j( U5 K% [: T8 _/ t* f$ }1 X
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    , V  v  ^( ~3 S0 o( I  s4 d2 P7 V, }, h+ y8 |, N+ a0 `  c
    递归实现" t$ Y# }% [0 I% @& A, E7 l
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    6 ]( {+ O2 L6 @. }7 W
      W4 L9 T: Y% P4 B' }& f+ l3 `: n" H
    . N3 e) _+ r0 b) t+ s4 d
    ) ~+ L( o* z- p. b, v. |

    & A) i! G: ^8 q: @void _MergeSort(int* arr, int* tmp, int left, int right): P( H; i7 T8 y# j. l8 ~, U/ B
    {' ~) M0 p  f7 D, x8 a- ^1 j' f6 n& y
        assert(arr);8 z2 F( \, @6 u
    5 G  v- B% c. Z$ j
        if (left >= right)//递归结束条件不要漏了
    ; ^. l8 }. B' L9 o7 K. k1 G        return;4 i; j6 _, P& T$ j- t' P
    . X1 r' @9 H9 U% c$ W1 B! ^7 r, S
        int mid = (right - left) / 2 + left;
    ' p4 |" H8 \5 t* e9 N- {' a+ j  P7 D+ [3 w. p
        //划分左右子区间[left, mid]和[mid + 1, right]6 Y  T, o( q* k8 B/ D2 M
        _MergeSort(arr, tmp, left, mid);
    3 I6 [* t- ]4 W' A    _MergeSort(arr, tmp, mid + 1, right);
    ! r$ a, m; Z7 T8 ~6 B5 k* s1 p& c2 l; j& S
        //归并% y8 J6 s. \; O+ _( s& w) i( I) l
        int begin1 = left, end1 = mid;; f+ |+ n& j( `. x/ i. P: l
        int begin2 = mid + 1, end2 = right;9 x9 j- g: a+ @( g. m( W+ v, u
        int i = left;7 c" l" e% S  x1 l* S: B7 Q
        while (begin1 <= end1 && begin2 <= end2)
    4 ~/ v+ I2 J1 ?/ S    {
    ; f! B7 Y* d2 |" G4 b1 D        if (arr[begin1] < arr[begin2])
    ! K3 Y- s3 j  s            tmp[i++] = arr[begin1++];/ X* ]; g! [- f4 ]7 I$ n4 V4 k
            else- D* ]% T$ B! L# t; P8 }3 b
                tmp[i++] = arr[begin2++];
    & @# a, Z: `* ?: N9 O    }- _1 N1 Y9 \4 m. }! A

    3 w+ n' V$ x# W    while (begin1 <= end1)! l" e7 {" D) Y
            tmp[i++] = arr[begin1++];
    7 L$ M, k5 ~, d2 ]; f  @    while (begin2 <= end2)% }4 _6 ]4 Y+ L% K
            tmp[i++] = arr[begin2++];
    6 i; F% _! ^/ E* Y( ^* q  T/ S4 M; `       
    ! C# |' ?3 x/ k  O    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    / ~8 j: b7 g5 `! V' ]    //而不是拷贝整个数组回去* d' ^& g( \+ m& K2 j& v7 W
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));& u2 I, l+ v$ _. `6 a1 @' j1 S
    }" V& u* n8 h5 z

    ' A8 O1 M( o$ r! I9 Xvoid MergeSort(int* arr, int left, int right)5 N! j/ Y; x. |4 v- P; b
    {# }0 N1 b, ]* p  K& C
        assert(arr);
    # y/ o* J2 j* \  V& }+ m
    0 x/ E  S' a/ F1 k) C, ~    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    + H  }  I" ?" P6 L' U+ s+ o    if (tmp == NULL)2 x) O; l+ K3 D9 |/ ], q- x4 Z
        {) L) E& G1 N+ t7 Z* l
            perror("malloc fail");& b" z. A5 K7 _
            return;
    5 g2 V% d* e. Z6 R1 ~! e9 P% o    }7 D: k3 \, J' H5 S
    7 A# z' i/ Y$ g- J( i# ~
        _MergeSort(arr, tmp, left, right);
    4 n8 L* u; \+ \  D6 ?, O# ^3 o# M' q, {/ X! T8 `
        free(tmp);
    - c  p& ?* w' b    tmp = NULL;+ q* p7 L1 Y$ Q& }! Q: I9 S
    }
    . Y6 `0 n( C7 j- ]4 e- n7 w# p5 i, N, K3 |3 z
    1, Z; j3 Q$ x5 v! n
    2
    / x/ M% {1 z2 x" S- u: T3
    + `7 B- I6 O, H' ~: L. I7 O4
    + T1 j* P& x' V5
    . U! i5 X! t* D5 \- \$ M; }5 q. B' x6& H+ A" c' t! g) w+ G2 v4 ?
    7+ a. ?/ q, ^5 ?5 f0 A$ K
    8! B6 u- C! Z# X! b& H% S: t; I
    9; G6 p9 p7 U! z. J5 R; m4 M1 b0 Z
    10
    $ o$ F( a( f4 A2 a! y0 v1 _11% V4 D6 J0 K$ u% a1 I+ E
    121 _; |" ^  E& U. |) p3 a
    13+ i# B; S6 Z) ^' Y7 J$ L2 V4 i
    14
    / c1 b+ C$ e" j9 ^2 D$ l15. W  L& c% X9 x" L1 e) H0 z# y
    163 Q; A3 T2 F0 V4 B7 `
    17
    6 t4 Y) ~7 z: ~2 l& V8 A$ J18
    9 D+ G3 a; P! O* P& I; e2 w19
      O3 N9 O7 h, p! D1 N: T6 z  }/ Q0 |20) J' a* @- k( A
    21' \# c7 T% P1 Z; L* q. ~* A
    22
    4 _8 ?: u. }, T4 c  o23) L" A. h% o$ q
    24
    + [1 C% a( t+ _5 \& A. D25* ~! n1 [" W0 O3 |4 P5 M
    26
    1 s* U' t: Z7 q5 e/ P27% z4 R% j, ?: _4 u7 L$ o
    280 L6 m3 {2 b: F5 J6 U7 J
    29
    , ]5 F3 O+ z: c" f8 Z) _. i8 {30
    8 w& w! y4 m# s, @9 T, S# j313 Q% I# T3 S& X$ T
    32
    0 J6 p+ s% D' T9 k6 u4 T7 ^# B0 s: ~33! v8 r; [% _; f) `
    34
    # |) Z- \7 U2 l# G8 _7 [. J354 d, J1 p# u1 C) y& s5 b! z
    36
    6 p' R" R+ a  f& b9 D0 N4 {37. b) P' k2 L, T
    38
    8 K! m, ~' _: W39  s, `1 @: V. P# P; L- ?8 U# h
    403 c8 h( D( _+ D- C
    41
    " J' `- E3 O$ z/ C" L; j42' U; s6 |  k1 l9 Y/ a. N# p( [
    43) ?( [! c" F. R6 \; N9 N$ q
    44
    # v+ Q- c: ?9 R: v9 }- o% p3 S3 u45
    ! A  k: _0 g1 ?5 l& x469 O6 g* N% ]. b/ K
    47
    " V" y9 E, h3 B! G  y48$ B3 \2 {: O! I1 Q
    49* C2 b9 N2 ^% \6 _
    50; d- x( b6 S" C& w
    51
    ( w9 I3 P& }$ n" h8 v非递归实现. s2 l  p% Y' o
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    ; ^) L( j1 w: y" F, t
    2 Z8 Q/ H/ O8 N$ w( j7 N" h
    + Q6 j( o$ R% H5 k8 O
    2 U7 x+ @. }6 k​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    5 [' `+ n) i8 @. k( q5 l1 U  \9 p" g0 O" A  \
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    0 _$ i2 D8 \# j* g' k$ P4 e9 R' f9 ]2 ?. L3 Z
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。2 R' d. |7 {0 V( u1 t

    ( q0 k+ w4 _+ W- x  }9 Z; j代码实现2 j0 c3 S8 r" T

    6 X8 O% H0 N# x& e! pvoid MergeSortNonR(int* arr, int sz)
    6 x' D' Q. d5 j% E2 v{
    8 s, O5 n/ r3 ^    assert(arr);
    6 i; K3 d- }4 n9 V# f- G' V% s* S9 q2 q
        int* tmp = (int*)malloc(sz * sizeof(int));& z! f, U( f5 m0 M0 }( m
        if (tmp == NULL)
    4 C0 E, C! L* t$ t    {4 }' }. K# D+ z
            perror("malloc fail");( A8 O  I4 @) U
            return;4 [2 m3 U" Q# s' W9 T, A' y5 y
        }; {3 l3 L1 k4 v* {: ?
    & W3 q  \( ~  U* b$ H1 L' G
        int gap = 1;
    ! H# P" V  @/ ^" {& A  y  A6 a    while (gap < sz)
    - }# \3 U2 y, }0 Q3 V    {0 v: o9 M6 \! x0 K9 F7 R% @
            for (int i = 0; i < sz; i += 2 * gap); X5 ^' V9 b/ y/ w/ B0 l
            {3 z, |- L+ f5 P6 z) S9 `) n
                int begin1 = i, end1 = begin1 + gap - 1;9 F! b& z. e# T* l4 q
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;4 P. r5 W3 D2 n
                int j = begin1;
    + \- S' j) Y" L- M9 i3 r1 Z7 q' t, n  O; ^: Z
                //归并: A- l; m# c& e4 v% ?
                while (begin1 <= end1 && begin2 <= end2)
    8 A5 v# p8 K2 Y/ C( n. j            {
    ; B- [  k/ i& [: V8 R1 Q3 o" E2 a& m                if (arr[begin1] < arr[begin2])+ A8 t" c. F$ h/ u
                        tmp[j++] = arr[begin1++];
    % x" _: x! k7 Z) f' h% c, u                else     + M! Z" w& w/ r" p0 m9 ?- f
                        tmp[j++] = arr[begin2++];
    ! }. t2 }3 e3 d% [8 i: \! p% l* J            }8 n7 s- `0 M+ a, o/ F
    ( j- \4 `7 ?: ^
                while (begin1 <= end1)
    6 c9 X6 d+ y& I+ [. a4 a                tmp[j++] = arr[begin1++];
    ; g5 v3 g6 z- e8 A            while (begin2 <= end2)
    2 Z: n) e5 C& e1 P! A* ?( Q                tmp[j++] = arr[begin2++];
    $ s% p& L1 E  @
    / t7 A' P: e. W9 t( N4 D2 _  [/ L            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    , t7 a  n& x/ v8 {1 u, s5 y            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    & V. T) M+ U* m) k        }
    * {- C4 r7 j) g2 G        gap *= 2;+ u; L% @! y$ k
        }
    ! r9 ^  a1 w9 s  ~  s  W1 x% X4 m' f& @
    }
    ) K+ t8 C. `* j" z7 y
    # ~3 T1 R9 K. a1 y1
    ( r# @9 z# ?5 y4 ^  q2' `# y) w+ F5 K9 ~+ q
    30 O$ f2 ?0 o+ u; n( x/ x
    4
    , i) k8 X, I4 \& ^+ B+ v  k# t# T2 e" S50 L0 m/ }, F" _& ]+ s2 ~
    6
    : b5 E* Q% F( q2 r3 r3 M: h1 y7
    . J+ m" D/ U& v: L/ B4 `8
    8 }$ r6 Z6 X* k! C3 T. p! i, [9
    % J% ~5 B0 y6 ]2 \103 U  N$ c6 p" q! F1 Y
    11! n" p" W! F+ [# C( P, ?
    12! V! i/ ?+ Y8 @4 u6 Q$ d) E; f
    13
    . z5 D0 T' `, a9 g* M, M14) C9 O5 ?, u  u$ W3 T
    15
    6 @6 @5 d2 W0 I# Z$ o9 g16: c2 o; M) A( u( B' v* e
    174 P$ B/ w: B2 P0 [" k: Z0 a' i
    18
    + @# ]6 [% f. {, x2 ]8 E/ G19
    ) z/ _  p& p! n% C8 S! I' x' a20( _; f% I' m+ w
    216 G* A% Y. d& e9 D5 o4 o0 _# I
    223 X& K7 K% B1 K% f( {. A/ p
    23' C  O( c, [" I- Z: T% F! _1 v& V+ p
    243 w) O( Y: ?. @/ d# I* e# N
    25
    5 `9 R6 w: L& n26
    , k% A/ I9 ~  ?0 N5 A27
    ( o* V' w- J6 k7 I3 r1 a28/ f- U$ r; d$ t0 p
    29. l& T% B. @5 W# B3 \8 ^2 d
    30) p& m0 L! `0 e) j+ d6 _
    31
    2 v/ _( z1 t3 T0 x+ e. w1 w2 L) a328 V* V$ m& o! p2 E8 j+ o) U
    33- F. r) ]% @6 ?/ M
    34
    2 R$ k* Z% [0 f0 L' e, _35$ L0 e4 c! e8 v* O
    36
    1 E" T& G& ~' {1 ^6 _0 G37; ^( K1 O/ n) N9 q. H5 k- ^5 [; [: K
    38
    & e7 d. ?" Z5 @/ G9 w5 _& c" P  U& F392 `' P! z! N7 l6 O
    40
    1 Y7 t, i$ s) K0 N3 H" v3 o41, i- Y+ H0 n" e. ^9 z: f
    边界问题; [) N  L- Q, z) [0 m% j1 [
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。1 R* q, _' D- f0 ~; Y; i. {

    5 w" d- h5 ~: r# _/ a举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:$ t6 ~2 f$ u( q7 B6 @
    ' k! c. Z8 C$ |; H- ?! F
    1 ^7 x9 Y. r" o
    8 Z3 S$ n+ {) E: M8 w
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)7 U7 W6 n% Y3 l  a6 Q' a
    1 J. `" u( b1 _" m  R* s2 l9 T& p
    第一组越界(即end1越界)
    ; H0 i( X( r( m/ L. I+ _; A+ }& k( \) @
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    6 c9 o% V9 d+ D$ \% p: w' E7 e
    , t) S' u1 q9 I; ?7 S4 n( F& `第二组全部越界(即begin2和end2越界)1 U- e3 [7 l2 b, r

    # {3 K7 `/ y0 F: |3 p0 _应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。+ N7 U' U% c3 q( h0 ]

    . K2 Y. G9 }# u0 q+ \2 z% Z7 m% v第二组部分越界(即end2越界)1 |" y! [/ x2 p8 _

    0 t+ |& {6 t( D5 D: y+ d应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    ( z. w. O2 s$ v  V4 j: b1 f1 F6 ?; ~% ]: H0 X/ e; J
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    * O4 R; C' U9 z( D" l  D. ?# C- W4 D* U. @. M
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    9 }6 _' ^- m/ B: U! [  w( T
    ' o& d6 I) N6 P" `6 u- z7 Q​ 拿两个数组试一下:
    - o2 t* U6 _( C9 R5 B6 N+ g
    5 y& n9 J& m( t0 E5 K; i
    9 Z1 D1 P0 ^0 C: V! P5 U4 r" z- j2 K% w  T
    ! h! t, s0 v' m8 n8 E# y5 t4 d

    ! i% c) P+ V" T# `6 n" f' z* j4 _' g代码实现$ {9 a6 }5 v5 w% k# z

    % F, ~0 W% @! W/ z) R& Rvoid MergeSortNonR(int* arr, int sz)) L/ f. e# W2 N  u; ^2 B
    {# H& z4 {4 k! C: A
        assert(arr);0 e8 H+ |( E! X1 {+ Y
    1 _; |( V5 _  l/ S, a' [+ X
        int* tmp = (int*)malloc(sz * sizeof(int));$ W% Y- V9 T3 E$ r. m) L
        if (tmp == NULL)
    - A; K; o+ P$ p. n    {
    : T. o/ G% f$ ]: b( Y3 E        perror("malloc fail");
    3 Z2 a7 b# P  V! H        return;/ O' S+ y6 }! E* M- ~& \/ B7 T1 ~" f
        }
    9 z5 V! ^- g) R7 P% J" @8 ~- c0 x5 G( k2 o1 \" [
        int gap = 1;6 `1 c# p- h1 Q; S2 T+ i
        while (gap < sz)8 x4 k. S2 Q2 G
        {* m4 q7 G+ E' c  y' i# T
            for (int i = 0; i < sz; i += 2 * gap). b- B# v% l- \
            {
    & X  C, G( z9 e/ ]! f            int begin1 = i, end1 = begin1 + gap - 1;3 Q' @% J; e" s. @( d2 x
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    " {$ w2 p# B* A            int j = begin1;: r' ?/ P0 p5 X3 a) [( W
                            //越界检测
    8 g7 z$ b" \! g4 _3 `; f            if (begin2 >= sz && end2 >= sz)0 f2 @$ L2 t2 K) t3 c; k
                    break;( E" R- N$ n) @  m& A
                if (end2 >= sz)
    2 E$ H8 y5 M, A6 [# y: }5 u                end2 = sz - 1;
    ( q$ S7 J) R+ X1 F* i. V            //归并7 z3 B6 {8 |+ j7 W& g8 M- C
                while (begin1 <= end1 && begin2 <= end2)
    - m3 g4 I; `2 t  b5 p            {) x' b! B$ x" W$ V/ V
                    if (arr[begin1] < arr[begin2])
    ! T$ e- `) F+ U: I4 ?" r2 r                    tmp[j++] = arr[begin1++];
    : b5 `+ p8 @% p0 |0 M                else     
    0 j% k- ?: w# L3 Z8 z9 t) x% n  }                    tmp[j++] = arr[begin2++];
    ( J' z: H0 K. d! p            }
    7 _& D. P8 u+ Z) Q/ w/ Y. h4 M1 d3 w: T
                while (begin1 <= end1)
    1 D5 s* l+ z- |  {                tmp[j++] = arr[begin1++];/ A+ w' `0 d( y0 f  ~
                while (begin2 <= end2)! T; J3 O- e& M8 C3 x! |$ A
                    tmp[j++] = arr[begin2++];$ f) J+ V: V6 W) f' h
    $ m/ I. l* s# ~+ n' }# g# J- X
                //拷贝回原数组——归并哪部分就拷贝哪部分回去0 d  Y% J) z$ `3 |
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));% e* F1 j/ b7 G- E! y  w) M
            }) J" Z; I8 I* f8 @% ]
            gap *= 2;
    # W7 {" U( C8 `    }
    3 h; [% U) M  M$ R& `
    3 O% _9 E) M: f9 e, o}! G& M7 X3 u! |% ?
    3 N  m8 O8 v2 {- t4 Q5 C1 c
    1# i6 g$ i! v5 j* a; \
    27 `) }+ m# n; B* ~4 @  h
    3" H9 S0 Z. o) @( |7 l3 Q2 t: M
    4+ K6 N8 Y6 M" O, m, q
    5  _" n$ @/ g9 I) U% x8 K' ~2 R: P
    6- C% H+ @7 r* Q$ D5 s# U
    77 K0 E* m( t1 z8 M
    8& J/ v7 [4 V7 P2 D
    9
    ) A* c9 M9 h& |. o, V" b' ^0 U10
    " E( K; G+ E( g: g' E113 v8 K6 z+ d/ H# t. ]' Z
    12
    $ S  V# N5 T" T* o13: f$ v( E! t! B
    14
    9 |8 @! t' o. ~! k15
    ) J  C% T, c4 U0 [16" _4 i6 p7 L4 U" r  U0 k
    176 @8 X( _  F4 }3 W4 w/ U) g
    18- d3 i2 m/ c9 Y$ M- o
    195 C# o/ x. `: D* d$ y2 K) t6 N
    20
    3 J! ~8 Y! ^8 H! Y21& _( A; }5 ?! _: k* P2 [
    22
    7 T0 b# n+ ^4 m& u7 a/ C23
    7 `' f# C+ c% K1 j; ^. F240 j" w0 R( S% D
    253 l: L; p; ?! F5 M8 Z1 P' J2 T
    26
    ( C$ y4 u% K+ r% ^5 p8 {( H, J. ^27) F; f4 b; }/ M4 ^
    28
    # T% u6 G3 ^! |29
    # f: g( t1 u" K  }30. b3 F! J* I" Q3 O
    31
    9 E' C% v6 B8 l! [: Z0 _323 a* H* u) r, W
    33
    6 z- p5 ]. ^" [34
    - m1 d( v+ t9 k( C35
    7 Q6 d5 e! @- K362 N. C# i0 G6 {' c; f$ F
    37
    : z: R3 @  D$ R6 R38. ]1 Z1 r# v5 b! {# A& f$ _$ f( w
    39+ e+ n( z) I5 S* Z6 ?, l* q
    40$ M, ]% ]  H* d, S0 Z- \& F
    41
    7 m- B, B7 ?6 G1 j422 }% {5 h: s$ u
    43
    7 z5 ~2 A7 h/ E( X44: R, P4 ]; L* c. y. S
    45
    2 ]% i& Q$ ]3 ?0 k4 J) }归并排序的特性总结:
    . l' m2 |8 [, Y' U  L3 v, a3 Z, M0 y
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    & c1 _( c! v4 K2 M* _/ K/ Z时间复杂度:O(N*logN)0 O# T/ M0 ?' P  [, `
    空间复杂度:O(N)
    - L( V( w# m0 m$ a! _+ @' V' t1 m稳定性:稳定
    ! U* |( e; k  N- K, M
    % s8 ^- U; }# P% c0 Y————————————————
    1 F  l) c6 ], U+ ?& N4 z版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。! L, [0 K3 Y5 H+ ?$ Q# w
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    . X4 e* c, Z* @  f
      s; G* c, h7 N, c" M4 p
    / U/ k! ~# E$ L4 Y* @
    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-4-13 18:26 , Processed in 0.621844 second(s), 52 queries .

    回顶部