QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3310|回复: 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 A6 t# O) T& J+ t4 e; }

    # d8 k& G& e- g/ i4 ^: p1 ?前言7 \- q& u+ p) c- _$ t+ \+ y: [# e" p$ Z
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    # N# k& ~; r8 i7 t+ s
    , ~$ t1 m# f% F8 C3 ?. d9 s归并排序9 _6 B4 L* }+ V9 ?, X
    基本思想7 f- B  B6 u7 w" ~' v' B
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ' x$ J) D  W1 {1 r& p' m' g# U/ Z( Z! O' E2 V: N$ w) N
    $ `& ~' a* [6 C* m: c! N8 R! Z2 U+ R

    ( e9 \2 ~0 v2 Z  r% V; L/ B# _​ 合并的思想其实和有道题目的思想如出一辙:
    ) z4 x9 i, v6 w% r
    . f, F1 y& ^: X. }: C4 b9 n% ~; _$ j' o; h3 f5 s" ~4 N4 e

    + x6 d* T) i/ x1 A6 A+ m! Y​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    # H% z$ Y2 t4 F6 |% @9 _& e2 s8 n8 i0 j. Q$ {! n$ a4 }
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    6 f. H" C- Z- F  K: m% ~7 d3 C: p( C; L2 n; V1 O0 C
    int* merge(int* nums1, int m, int* nums2, int n)! K, X6 f4 S8 H' t
    {! E% O( Q9 C. C) v6 P4 d
            int* arr = (int*)malloc((m + n));
    . Q; b' ?! P% y) ?" y# _- [    if(arr == NULL)
    , F8 j6 `+ m% o; F    {
    " h5 `' z2 l6 m$ x. c/ I        perror("malloc fail");, O( M8 w1 }& ?. J
            return;
    6 D+ U) T% n/ G' `2 u/ r$ _8 h  i) o    }& ^& s6 I7 R" h8 Y0 r

    % L. c5 I. z$ `3 e7 |    int p1 = 0;8 f# d) d- q. f& m: Q
        int p2 = 0;
    ; A  J5 _& x5 F4 y    int cnt = 0;( F* C: z8 u8 c7 ?$ v
        while(p1 < m && p2 < n)0 h, P; q# S. G) F, j1 B$ [
        {
    5 f1 c+ Z( q; ~7 W4 F, S/ f. M        if(nums1[p1] < nums2[p2])* D7 J( h# H3 i* q  H
            {; ]4 Y+ p. R: u2 U
                arr[cnt++] = nums1[p1++];7 g* p) c0 a) G. K& d7 |, q
            }
    ) }8 ~! @2 T, l7 ?4 U- q" {        else* u- }# S( O, P: ]) p9 q
            {: ~+ S- @$ f5 H5 s" v/ ^
                arr[cnt++] = nums2[p2++];
    ! d5 s8 B3 f+ Q! o0 N        }
    6 U+ J& i. ]3 V( ]    }- d0 q. o  X7 G- \2 B
        while(p1 < m)
    # A5 r) I1 A3 P# v2 X2 Z' [        arr[cnt++] = nums1[p1++];1 O/ d7 k" C" x/ ^" v, o5 D& o  Q
    9 V! U" _/ K* o, N; B
        while(p2 < n)7 O, v% v' p" C# b2 d6 ?. @4 Q" f
            arr[cnt++] = nums2[p2++];
    3 f1 A. H% v% g7 C! `+ D' n- }& v! K0 u3 a& ?5 s
        return arr;
    ! I+ r; h7 ]8 w' S}( i" ?9 a# W# m/ t

    # a9 Q( L) P! L2 C$ |8 b3 w1* x: A* S3 z  D
    2
    & f) S! I' F3 B. R/ y# G3+ W0 b4 W# n$ W+ \
    4
    ; R* m, ?0 u! y0 N2 c* G1 E5) ^4 E) R. @1 _) X
    60 ~2 X. {- `0 d
    7( r% D7 H9 n" _0 q8 x0 E  n
    8
    " a. b/ ?( C# h4 w8 [95 h) p: d* r6 W: C  G+ d  \0 L
    10
    4 e9 G$ c! f; Y) B2 M8 Y) X1 h4 b& c11/ i$ D- k- F: Q! k
    12! r! n$ }. u" G6 @
    13) A6 _- e% O3 T
    143 y3 D$ G6 Z1 A; O: O4 b3 t
    15
    ) s; O' d3 ^" U# f+ Q% ~0 }- y16- X+ T8 T' m) ~, W* W
    17
    " w4 D5 ~, S5 M2 y7 R; d: b18
    * }8 j1 I3 }0 E/ V19- w, G) \$ V: Z) b( L9 Q7 E6 V
    20( X, U: y; |$ @3 _, V4 T
    21
    + Q/ G3 t3 e! ~6 r$ Q) V% Z22$ h5 A% Q+ d+ a4 V) U, n
    23
    - Y0 b$ O. v1 y5 |  v* U24
    ( x# ^$ y4 Y7 Q5 W25" M2 a3 Y$ Z3 I6 J8 _
    26. a) x+ Z% y% X/ {: j3 v
    27
    1 _& B1 z( s6 e' [! c4 H* I28
    ! h1 F" I+ x+ B) t6 T; Q29; L: g1 R$ o+ f& [# e* h2 X
    30' p, K5 g' D. `' l" s4 H
    310 h) i, J. v& A! S+ W, o) t' X
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。8 ?' |% h2 L3 f# m5 {- s+ S
    2 d* s3 ~/ `5 g' m0 q
    递归实现
    6 K, a$ R* Q" Q, E$ i* E, w​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    7 T" u3 S, w( w; ~
    ; v( R% S* D# m" L' @/ s' t5 c# M- J! I: w1 z6 Z, a" A# s% u3 a2 [

    . I: ~: n) P0 S
    ) U+ L+ \& K# Z0 q3 F$ K- s! d6 w3 }& {* A1 y3 \
    void _MergeSort(int* arr, int* tmp, int left, int right)- E' |& J$ u6 o/ E# L
    {
    % I' m- c9 S% \    assert(arr);9 y: w. o: e& f8 B/ J" A, M

    & W, I  L- S) ~. k3 a/ H' V    if (left >= right)//递归结束条件不要漏了
    ) ~; R% i5 }9 ]- U! C& s2 B6 M        return;- A% L5 ~; P' C, q0 R$ L
    6 ?4 E: A# S( n( r5 {5 Y/ R
        int mid = (right - left) / 2 + left;
    3 ^9 s& v( n' H0 q% l% [7 [& T8 f/ O1 M: g4 P3 [& {) m
        //划分左右子区间[left, mid]和[mid + 1, right]! m# ~5 ~! x( R+ b! @* ?9 D9 x8 g
        _MergeSort(arr, tmp, left, mid);) w2 [6 Q# w$ }1 U3 r9 i. [; ~5 `5 ]
        _MergeSort(arr, tmp, mid + 1, right);% d, a0 c* e! X) M
    ) q& Q% m6 h, Z
        //归并% ]) w; C6 h3 F" ~' D( W: p
        int begin1 = left, end1 = mid;7 V& S% h6 x5 ]' y
        int begin2 = mid + 1, end2 = right;) l6 ?1 Y, ^- U- }# w( n+ E
        int i = left;
    8 G; u# S7 M) Z# v    while (begin1 <= end1 && begin2 <= end2); G( e2 M5 k) O
        {
    ' f& Q) J% _  i) s& ^3 x" u) I        if (arr[begin1] < arr[begin2])
    ! q* s, A4 M7 p8 {0 k- w            tmp[i++] = arr[begin1++];
    0 m9 H7 i2 B( B: I, W4 g: H. Z        else
    - u# h0 }$ b& y8 R            tmp[i++] = arr[begin2++];
    5 h, N+ c+ N" [6 K. k% S    }
    0 P% {' _2 {( e
    . {2 w# q9 F' t- z" N' s) @4 Q" o    while (begin1 <= end1)
    1 L9 g; `9 A' X& u3 B        tmp[i++] = arr[begin1++];1 D0 v( l. X2 b' c' L$ |
        while (begin2 <= end2)3 c1 r$ l% I" o7 C
            tmp[i++] = arr[begin2++];* H7 ]) h. }( H$ r) S/ p# [
            7 i# Y  r: H2 f& N! a7 r
        //拷贝回原数组——归并哪部分就拷贝哪部分回去) s1 ]. B7 O. ~7 y9 |
        //而不是拷贝整个数组回去8 N2 D2 h8 d9 Y8 r0 ~7 ]
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    & B+ l2 S8 l7 K; W" i3 B}, t# r! J8 o9 Y

    # k5 g# H$ i- I4 A8 f5 Jvoid MergeSort(int* arr, int left, int right)9 Q1 ?& z6 F- r" y" I$ M
    {
    : j9 m6 b* k' C    assert(arr);9 M1 U1 Q- F/ C# R, u4 U
    9 d8 o6 |9 v1 J
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    ( z! Y5 e4 d8 O4 i/ B    if (tmp == NULL)
    8 ^  _* d9 m. A# T0 f9 O" L: s    {" L: K+ }- K- s( w
            perror("malloc fail");
    # u  |8 \  M7 n3 m4 C( n        return;
    " D0 q+ U9 Z% [+ O" S1 z    }
    3 `2 `" M4 }( n, y7 k) Y1 E6 t3 _( G! i2 p1 Y* Z, o- O3 S* T
        _MergeSort(arr, tmp, left, right);8 m8 P* R% Q0 d0 V, l
    1 y/ r8 B! j9 l. [
        free(tmp);
    2 ^, V9 J6 b: H5 x5 ?    tmp = NULL;  Z% u; X: a5 d6 O5 P% q1 p1 X  L
    }
    ( u; A8 y, ]: s3 w1 T- ]' \
    + y0 M8 l  l$ R9 i1
    % E# K! n2 u4 @- b. ~6 G4 Y- B, f6 k2
    1 k" z# g" Q4 ^! E; C6 n3
    0 F- @) B0 h* ^2 H4
    6 U1 Z  K/ D. n" O  R8 A5( ]7 F7 ]: }9 n7 D# G% g5 t1 }; E
    6; o: D$ H4 h! E) u! K
    7
    & g3 f- R% X# r- t0 Z$ G( k8! D. m6 u; B( e% c! m, q
    9- M- g2 {) Q6 e; {& X/ I$ V
    102 u9 v# ~, i4 n' `( c9 D3 ^' P
    112 W) H5 f/ `+ h- W% @7 Q
    12
    ) g0 J; k. ]* d; \9 m- P9 |13) x4 C1 A; B7 N6 K% J
    14  r- J: n7 @9 s2 I9 F
    15. Z% K- C5 U+ E; s
    16. L$ b) i* q2 z$ `2 P7 v
    17; y) o  P+ ]  w0 P$ d) l
    18
    : f( ^' S3 X! R, e& K) V198 `4 d: H! P3 S, j2 O) m
    20' @+ T6 D* o+ j6 j" e
    21- N6 _) R, ]( F! G" m
    22; ~+ K( v' C4 H& U+ y0 S7 [
    23' t, @9 U9 ~; E# }
    24
    5 B6 s- Y! C) L25
    6 _4 C9 N$ z) U( k7 x0 ~26! ?0 o. Y; ~, g. Z
    276 \0 y) G+ H6 x) K+ ?) z/ b5 H
    283 `7 J2 ^/ T/ n1 `0 Z# y/ I
    29. c6 E: Q& L4 c. v0 Q
    30
    3 i3 Z) L2 a* ?31& b& W! F: ^, ]' F% v
    32
    " G; I; p" K* d" d33- c: ?8 `) @! X8 {3 q( U
    34
    & s+ `0 g$ n, ^9 q0 b35
    4 S3 q' C, a9 }- i/ I, ^- \36  m6 F+ X/ Z/ T, s: j4 o/ w2 m2 Z
    37* V3 r8 g$ Q, ~* r' T7 M# U/ H
    38
    - E4 f' ~/ |, t7 v' \& x39) }6 n7 H- O5 O& Q: ~& `
    40
    $ N7 g  o" U; Y41# l# m8 y1 M3 i( o0 n% y. K# w& w
    42) i6 l4 `/ \  N6 L
    43* Y5 n4 X2 H" E
    44& s) |  Q1 B; f* M0 S" Z0 ^
    45
    5 F! |5 Y" u5 U* ]) [$ C46' c& X  w9 o% C5 G
    47
    ' k1 H) w% ?/ j  J' d48
    # Z# X, _( q" i! H( n) P49
    + X( W( Y+ M$ X$ f% k  f, l50; w  s6 }6 h' t; l1 @* X
    51
    : L# y; m+ g8 s+ }2 h" I非递归实现
    . |! v. |3 d  Q- v2 i1 f$ l​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    " h  x) G6 m/ x3 R' F+ |5 I- e% ?: Q5 t1 G1 L
    8 y; Y% N: b% A+ t/ V- e

    1 P/ ~4 C3 l9 W) d; O) \5 T​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    4 M8 N& X: d. G. u1 [3 w. y; I; y+ i! y- n% K5 x0 @- u
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    8 h* [6 I: @8 }6 `! Y
    ( C0 h' Q$ G. x​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。; R/ c: a) W/ }2 `" Z4 M
    ) E+ c) x# ?0 v9 [
    代码实现
    9 r. ]* U# z- h! {) H, w5 a7 J; n* N) J5 }  v( o" C- Z" y& Z
    void MergeSortNonR(int* arr, int sz)& @  I. r) D$ D& B' ]6 {
    {
    2 z1 Q, b( c4 h1 ~  S$ @    assert(arr);
    4 }' t" \; H+ D) ^/ V
    . y, D8 N* l4 q2 j  W0 d$ Q5 V    int* tmp = (int*)malloc(sz * sizeof(int));
    + x! P. f) z  l    if (tmp == NULL)
    # g. v5 Z/ o2 i% G3 F% Q4 o! S    {+ d% i  j4 |4 s4 T$ @
            perror("malloc fail");
    $ [- z1 b  i6 a* p( u        return;, t6 \2 J( L& ~* a
        }/ |6 H# V! _# b: A, ~1 n5 Q
    ; Y5 ~$ B' _7 U* p! P" |; F9 o, `
        int gap = 1;
    / p/ K8 f- |' A! S: V: d    while (gap < sz)
    : o3 r% N- g3 X7 G3 B/ ~8 G    {. k7 @/ ~" k5 r: \
            for (int i = 0; i < sz; i += 2 * gap)4 H$ _$ P- D. d& [4 c" j6 F: n$ `3 m
            {3 E% s& z. y/ u0 i
                int begin1 = i, end1 = begin1 + gap - 1;5 s8 s; \3 R2 M, r# g
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    5 G% r( _4 w" ~3 ?% b# A. _            int j = begin1;
    " i- B8 L# Z- `7 W4 `0 u# e7 B) z4 e) H0 Q
                //归并3 X. r) }7 h* o: j/ R# _
                while (begin1 <= end1 && begin2 <= end2)
    ; B0 \, k  h, p/ T) B, B            {
    5 T( W8 e, p: m$ \/ e- F4 Z                if (arr[begin1] < arr[begin2]); n9 ~  r/ c# ^, z
                        tmp[j++] = arr[begin1++];' Z- @$ {( U# P; p
                    else     
    7 }. _& [/ W  j# G6 f& i                    tmp[j++] = arr[begin2++];
    * U0 D' f- n8 T* \& `            }- {2 |: U3 r1 n8 u! Y, r

    : ~  k3 ]" k5 F6 P# S7 G0 ]            while (begin1 <= end1); @$ t$ h# f4 k- d% o. m' v
                    tmp[j++] = arr[begin1++];7 ~+ _- C5 J& Z3 g, }! k1 x8 Q7 s
                while (begin2 <= end2)
    ; R2 H' W9 m1 F  |' `                tmp[j++] = arr[begin2++];
      ]0 m* v' W. ]" e
    / k4 @6 ]+ v/ D  U            //拷贝回原数组——归并哪部分就拷贝哪部分回去, A$ c$ s' i7 `0 z, T/ ]
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));5 S# r* i0 l" G1 J
            }- C& Z( P3 v; Q% j$ S/ P, |' z& w
            gap *= 2;2 x; r4 {7 g( l3 Q; R3 q
        }+ G/ M1 b/ b' m3 _7 Z
    ( E4 z+ y. o. L- N, v
    }- R  h, Q) }& U  \

    ( _' b7 s! Q8 }1( X' h3 E. W' E
    2
    6 u6 ]& I& h) [8 n3% B) D4 [  p* O- _
    4& Y3 v7 X! m4 _' T: K
    5
    9 l+ Y8 h! ~# _$ n; ]65 W# D* P2 p! h) R9 a% ?: o8 k
    7
    ! _9 s+ x: Y. l1 n8
    ) ?' v$ M% Q- x& l, h9
    ) b5 y2 v; u4 k% y10
    ! A2 w9 c3 @! R" w3 \111 v# j6 v0 f9 ]. W  |9 r) u! y/ X. O
    129 B! D, s! c& u$ d& T  ]
    138 I+ \* F4 X3 |9 G
    14
    $ q. [% [2 M' B" a$ J9 A15/ e+ ~6 B% p- q4 f5 p% t
    16
    * D. G. Y$ ]$ i' b4 r" n* z7 `0 ?# d174 o1 W/ r7 D8 d2 z
    187 ~, E5 q3 t; \' S7 j# V- {* h
    19
    ' ]  n( J8 r1 G& x& [% H20
    % L6 P$ C* z- |+ F, k8 C21* W( \7 P0 Q7 [: u# d9 Z
    22: Y+ @; K- P; M% o7 p: N( ?
    23
    % O/ A! w; p. q! ^24
    8 p9 i& [- g6 h9 y$ ^8 r25
    0 ]% U6 _/ t9 I3 @! g26
    2 c' C' J4 g. _( J( p27
    & z) f7 f7 \2 Q28
    # v# x: r0 h8 r/ L290 f5 A' b# T" b* m2 G: g* c
    30- F* U- d, P* m- P5 I' K" q
    31
    ( k  O4 }4 x9 z$ t" o32
    0 H: c7 j/ F1 z0 W" K+ ?0 r33: @" h/ \( w+ e' ~
    34
    ) X8 _; F. a2 q2 d. y" |35
    7 T$ y- ]! ?2 R' S8 ^1 M- P36
    & s0 {: T% [7 {/ }5 W! v! H" K37
    - h, ]5 e9 {8 F6 W9 M" X38
    7 W3 u) Q" U6 n& z+ U4 R39( ~9 x+ a+ n( Z' Q- W9 _" q
    402 x, J+ f5 o) u: s# G- E
    41. C) F/ \0 n8 Z8 f9 ~7 Y
    边界问题$ l! I; y9 U% }' ^
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    " V3 G9 r5 _* k; m1 j
    , [) O6 {2 T8 K7 Z( u# [( S( o8 h1 M4 a) Z8 z举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:; e8 S, |9 ~5 u% L

    % j' v- B+ H# d! q2 f6 B7 ]
    9 l) p9 L7 N$ X' Z9 m% s4 ~0 y: e8 d" |+ R
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    1 G/ I% _  F3 h4 ?) E/ d6 I+ T7 I: n( n
    : ^% S: E  k7 Y; \第一组越界(即end1越界)
    # X! I" W: p6 t  h" ^1 q* d: h6 T8 Z" T5 U  Z% r1 O# Z  n% M7 f
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。$ n& N* |% d( X/ t, H8 ]; ^

      H* l+ b0 m- |1 |$ g第二组全部越界(即begin2和end2越界)
    " L( Y  @) E. {/ z! ~9 x5 V. G6 a# t; L+ A5 @" |9 j2 K9 B9 f
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    ( v, j: ~; t5 A( P
    4 x( l+ B- B" U7 ~- [第二组部分越界(即end2越界)7 W. m! T+ k- z% X

    ) h) w. ~2 P0 W3 E应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    + ]# Y9 V! \- V8 F
    ; ^0 R. E8 Y( d​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    : l! J! f" L5 ?" m' z$ f) D7 I# W: k3 d- v# z
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。0 U: ]" @" ^& [, ~8 ~! J

    / w/ h* z, |* E9 A% ?9 l​ 拿两个数组试一下:
    1 S* s0 z& |9 c1 Y6 z# E+ L. a5 Y  Z! y5 z3 {  R, A
    0 t1 Y; r, \2 }5 C
      h$ w' [; Q& B: S

    ! C+ x# {3 }6 @
    - K' s2 Y% C, F; u' Y8 {代码实现
    4 U  m+ K, r2 g# O+ ?: e/ J% h. C4 a; ?
    void MergeSortNonR(int* arr, int sz)# @: u, X, A. [
    {. x0 \8 X6 k1 V' k& R0 [: L
        assert(arr);
    1 a" R& ?1 M3 e: T: y6 w# i: |. U, L
    6 P. @% J* Y$ M( k- l8 d    int* tmp = (int*)malloc(sz * sizeof(int));
    " t$ k0 \. C0 ^6 V# M    if (tmp == NULL)) U8 `% c7 T0 v5 U
        {
    / E' W3 F( n9 S; B        perror("malloc fail");
    5 G2 [, P- o2 K$ l3 b8 j. `& X        return;$ Q# v: e" u0 ^/ y0 j
        }
    / ?8 w4 j2 b5 V2 }; w5 o7 }  x. K& l- V. g' v/ p7 F" Y0 ?
        int gap = 1;
    $ i) M6 U3 y2 t8 @    while (gap < sz)
    ) T- I" ?/ J% A: _; j    {# t6 \+ k8 ^1 ~6 L8 k- }% j, Z
            for (int i = 0; i < sz; i += 2 * gap)
    ! `7 i8 G& l- `8 t% ~2 V        {6 D. n* S1 y, s: M, q
                int begin1 = i, end1 = begin1 + gap - 1;* l" c2 i. B3 h' U0 L) V! g3 [
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ! p+ s% \0 W/ A! m8 e4 f3 U            int j = begin1;. A, G- Q7 g( r$ x4 X
                            //越界检测
    , w- H6 ], f* I" L            if (begin2 >= sz && end2 >= sz)  w3 h+ ]! m# ~6 ?
                    break;! T7 P+ u0 l8 z( T. H1 ?; p  L% l
                if (end2 >= sz)
    + ~/ X5 d' s+ w: n0 _# o: r                end2 = sz - 1;
      `0 e! s4 z% j/ V& o            //归并
    4 n* i! Y) p) O1 [            while (begin1 <= end1 && begin2 <= end2)
    - i8 e7 A% v7 ^9 O1 q            {
      ?1 z% |. ?* d# R# y& N7 n3 F                if (arr[begin1] < arr[begin2]); _3 r9 u  B% w8 I. ?
                        tmp[j++] = arr[begin1++];6 ?) x+ W! G; f7 [. C5 I; l& p
                    else     4 t* `. \. T! s  F4 o9 F2 Q8 m
                        tmp[j++] = arr[begin2++];3 I* I* R6 w" c/ C
                }
    & Y' R2 m, @5 }$ @4 R- T# e5 `$ U5 [1 y5 f8 V9 |- }- o! L- M
                while (begin1 <= end1)  e% V" L8 `6 V- f. L# B
                    tmp[j++] = arr[begin1++];. t( z; x: t+ D' K6 t8 v7 y
                while (begin2 <= end2)3 ~7 y4 y# J8 S* L8 q3 k
                    tmp[j++] = arr[begin2++];7 c# S, s0 d3 T

    0 u& e7 ~: s; r& ?2 x            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    . S9 O+ J' l; J2 I' t            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    3 C2 }: ~; u3 `3 U8 |* C% h        }
    0 p- `) u, W% e$ V$ i4 a        gap *= 2;2 c7 f. q! D2 P& H& q6 X* V1 h8 L+ B! S. `
        }
    3 j( C# i2 t' {+ p/ Q( M" _; S) k8 K
    }
    9 A( e* Q" ^- q- s, z
    9 E- f2 h* U+ f* O" }- g+ O( G1
    8 P( @1 I" E; q6 K5 {* E# d+ c2! L- _) I, m9 k9 H% ]
    3
    $ ~$ I' e3 X1 c3 Q* l3 E7 z4; M% M7 x3 W! H2 q8 j' Q  M
    5
    2 R2 i+ m5 Y2 W8 r* z6; M# f6 `9 j  _& t
    7
    % l0 G5 ?2 _5 T$ F" q81 s' _8 V' A) ]6 b
    9
    + L. L5 ]! p& U! Z( Z$ ~10
    : |% Z) a) H* J% l114 Q" W1 Y4 Z7 I. [  R
    12
    ) t" Y4 d) n% N- J135 A" h6 j# X5 R
    14: B$ M8 r# P8 m4 D4 }& Q' b) e1 K
    157 t, F3 ?# I. e, S3 Y- y
    168 Q, M4 E3 }' I) y) B% _1 g+ k
    17
    # ^$ Z- i/ z: \& O$ ~/ w18* b) |/ l* K  l. U
    19
    6 J1 t% I5 E) h. z20
    # p. V* z0 Q4 e21
    7 \. f) S$ u! Q5 j; u) s22
    ; N8 X( x8 z$ `8 i' o) j: K$ t. X7 K230 \# Z4 @4 W' P) l! i8 R
    24
    1 @4 _( a2 f2 Z25
    5 o5 v6 ?5 M" r4 n* |, D26- X3 n( Y! }/ O7 \( U) R; x3 y
    27
    " P( _" [) L3 p- J7 l* J28/ O* r* Z7 R4 P( N0 I
    29
    / U+ a6 d: R. q# z$ Y30
    . ]( S/ V3 I' c  h$ e! |, ~4 Z: G31
    1 w6 Y: n+ L5 D' W9 p6 I; X32/ [( S- M1 _/ y6 U2 G+ f
    33. j' `, K6 f* z; N. s7 v* r
    349 K; m+ E) v& z0 I8 c+ ]
    35
    * v2 D/ ~6 [" G1 D6 A361 [. h2 r( }  ^; G4 |) N# }# V
    37) @7 I$ J& z4 N+ G& U( T
    38
    * H- U6 j, p- U# i: L, S: o39/ I% L' K% @% x+ b
    40
    9 H; Z/ F) R8 f; y" J41- y1 u7 t( o% j) E+ d% ^3 q7 G3 h
    42) d$ @- d5 c' b/ [+ Y1 @+ t" I9 X
    43
    - E& A2 K" T$ w* X3 d- D4 Y- A446 G- a1 R1 M- u" {1 z, {
    45& Q+ z* k# o4 Z" A1 m
    归并排序的特性总结:
    ; S5 o; b! ~& o& n
      |+ [) j: c- p" E. i归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。- ~3 \6 r  E" P+ H9 O: ]6 l9 v
    时间复杂度:O(N*logN)% I/ h7 ^) S0 \1 E6 N5 I
    空间复杂度:O(N)
    , j: R+ `+ M% j1 C/ `$ M稳定性:稳定% L7 w0 C6 h! M/ ]. H' \4 _4 L
    ' J- {/ c; S! F* D5 S) v5 b
    ————————————————
    ( j( k: {+ ^9 N7 J, d/ x版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。7 ], ^  F+ c0 C6 ~
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    7 j' D* e& |% n9 L4 `7 x
    9 j- a: o) q$ H2 q' G4 P, ]2 M- T
    * f; O& Z6 ^( A3 ^3 _
    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 09:39 , Processed in 0.632829 second(s), 51 queries .

    回顶部