QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2215|回复: 0
打印 上一主题 下一主题

[其他资源] 【基于C的排序算法】归并排序

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

81

听众

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的排序算法】归并排序  f* E- }/ {/ c0 }7 q& h1 ?
    , D( G5 T8 }- U/ a
    前言
    $ M8 ^4 R/ T- Y4 A- Z) Y8 M) ]本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    / _) [" d& G! E5 B* i$ T: M7 X) u' f
    归并排序0 p; _5 X' Q" E, J) c+ j
    基本思想  C1 r8 v2 d, Y! v  _* p
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。( U1 I  N0 h; L2 F; L6 Z8 m* H

    0 a  |- g2 ?' B- _' C8 L% Q  T# T8 V+ d/ e8 j7 b+ }

    8 O3 c# j8 k3 N5 e5 ?1 D​ 合并的思想其实和有道题目的思想如出一辙:
    1 I1 ]  g8 {( g5 |
    ; Y% p* e, D* S0 K0 u$ W
    " K2 [! [0 R+ M5 N
    " [, W: u) s6 @& |# I  ?* g​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    + z. m' ~- ^7 C$ d) n+ h# c7 |0 |5 f! X; m8 w+ `
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]9 F8 J  l  A/ w; C& H, t; ^
    ; s( i( P9 |5 _6 I
    int* merge(int* nums1, int m, int* nums2, int n)
    8 s( h0 K+ i! O" s! q- k% M{
    4 r+ U/ ?1 H$ \7 v0 _* Z        int* arr = (int*)malloc((m + n));  R0 ^! r( k6 M
        if(arr == NULL)8 h6 @8 E, S& S7 s$ g
        {
    # J! L! m, a- |, h& N( }        perror("malloc fail");
    * w6 C3 s2 W& I2 N4 n8 @        return;
      r- ]# U! P2 E$ [, t  h# }# e% t    }- u/ i) j8 B' F/ D: t! b9 E/ V% d
    * y" ]. t& ~' Z' n& m6 \
        int p1 = 0;
    5 v+ w1 ^# e3 k/ `    int p2 = 0;: [$ M6 i8 Q5 V& D, {
        int cnt = 0;
      U1 a1 U$ q% \    while(p1 < m && p2 < n)
    * w9 ]) Q+ f6 [2 n8 T    {% V6 ?# V' n: C' h4 j
            if(nums1[p1] < nums2[p2])0 H+ I' n# k0 \- I7 I6 D% z
            {+ S7 v8 o5 F% v* u
                arr[cnt++] = nums1[p1++];
    ) F( A: d1 U9 ~) N$ ?# b6 Y        }
    + s, G. ~/ ^, C) c+ t3 U  J4 P" [        else' e5 M7 f  ^/ e# Y4 d. x* b
            {+ Q$ w- d, t2 o5 W
                arr[cnt++] = nums2[p2++];; `+ }7 ?' U: ?' @" d' u8 E
            }
    . V; h2 y8 I/ B/ O0 {+ v    }& E& R) R; E' K/ X" E% x
        while(p1 < m)
    2 ^" G0 `. k- S6 _/ t# D$ a        arr[cnt++] = nums1[p1++];! Z: ^4 d; ]5 ^- K& f. N

    2 j8 V" Z, X$ K7 n, w' I9 p. I! ?    while(p2 < n)
    9 x; d- {! |+ @3 b2 s& g        arr[cnt++] = nums2[p2++];6 k  h5 e6 j9 B3 P* [$ \- [/ a
    : k' x! U5 b5 F9 d2 U
        return arr;( W" b, t% e  n2 q5 ~- v
    }: ?$ a, V, G1 c& ?3 F+ H
    6 O- B- I7 I- J! |: Y
    13 _0 k/ [& x: G: R* z% x6 y2 a, m
    23 ], ^! H# R3 \' T% d/ j" x
    3# d! v6 z( Z; w6 y# Y! A! {; @0 G
    4( r) H. Z, g7 u
    5
    & F. b* o- W; \5 e6
    1 K# L4 j1 N7 K' |7
    6 W( D) k/ o1 T2 t% J8 X88 n' ~! M/ v: S0 e- {( h
    9; ]( t! J4 }/ U0 \4 _5 G) K
    10
    & M6 n2 ^' o) B( Y; ~117 S4 g5 n* w; f9 x
    12
    5 O$ P+ i: k+ v3 L! L! }% \& l13) z  t. Y( w- n9 i; d% W
    141 T" c$ l' |. V! b6 p% ^
    15* |% i1 Z. Y) w$ f! U
    16
    ' D9 O, M5 H& j0 i+ W4 e3 U3 W) W17! `$ S; _2 c' w+ b4 q+ D
    18
    6 u9 q6 j) f) w3 T# r# G& v19& d( L4 G+ _6 C+ b6 q# B! ]' ]
    20! y8 q5 x+ c; r3 l" F2 @( D
    21
      s" O/ }8 K, ]9 J+ n, G$ V. ^22
    , f0 k5 o( L9 Z1 Z" ~8 f23. A; D9 l  S6 A
    24
    $ j: v8 b0 R+ g/ F2 M9 E, n2 ~+ C4 \25- @3 g/ y; C2 |3 P
    26
    6 ~$ p7 E/ ]* i27
    % Q* [4 }) C, e: X& j285 c& k" L' J! N) Y( {! O9 b) @
    298 X8 F& c7 {1 M- g# ^+ R8 J& G
    30
    ! b3 m! J, v( ^5 m0 Q! e. _! `31, X  P/ \. l! V2 w& X
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    4 ?4 K2 C! N+ z& _, J( x4 R+ o5 c/ s' j$ J/ b0 i. W3 u2 N
    递归实现) o5 J7 |1 G3 T/ _4 z( V' i
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    ' H1 y# ~, u! J
    * F4 n( X8 L  `4 r
    / x( A% P. z" O; t% t
    # t) g+ ^, j9 H. F
    ) v9 d7 i1 z+ @/ b5 N' |* v$ ?( g! u! U0 [0 Z
    void _MergeSort(int* arr, int* tmp, int left, int right)
    ! ^5 p  {! a' \2 e{4 `. e- c+ \3 s  |* F6 t2 D. n
        assert(arr);
    + }* Z! L2 z, U" U8 y  O) }, h2 E3 d+ w# P" ?( |0 y! U
        if (left >= right)//递归结束条件不要漏了
    6 s  w( O$ ]) F! ~: g1 d        return;" i- Q0 u7 M& q& `5 T. N

    ) p2 @8 i& L* `5 N9 l9 @    int mid = (right - left) / 2 + left;
    9 x1 {$ U1 h# B: A8 r) o( s* L+ N, v4 G: u
        //划分左右子区间[left, mid]和[mid + 1, right]
    ' s# C6 X; H( w( }: z    _MergeSort(arr, tmp, left, mid);' G6 S; |9 j) U+ N
        _MergeSort(arr, tmp, mid + 1, right);
    / f  I3 ?* V4 H. U7 F4 g
    * l2 {- T2 _5 X0 d    //归并
    ' \( B3 R6 ]* M- S    int begin1 = left, end1 = mid;
    2 Q1 Z. C7 g( f5 \) n$ v( S    int begin2 = mid + 1, end2 = right;
    ) P7 V7 q- p, A4 s. @    int i = left;. j! `& S8 a0 s7 ]+ T+ ^
        while (begin1 <= end1 && begin2 <= end2)
    " i/ t$ W5 T1 O) J' A, Z5 \    {% z, `* a& [' ~/ s. g
            if (arr[begin1] < arr[begin2])
    ( G$ [; r2 r8 U  k+ M4 N            tmp[i++] = arr[begin1++];
    % M5 b" r( j! U  a" s        else
    , n  A- v7 x, ?! i. D8 t. W+ s            tmp[i++] = arr[begin2++];
    % [7 `$ y) S, J- P1 y2 h. w    }# b5 d7 d" Z; I/ I

    ( ?( K+ i6 {) b/ H$ K( ^    while (begin1 <= end1)
    - p1 ~5 l' ^$ ]7 k$ ]        tmp[i++] = arr[begin1++];3 G4 H8 _1 \/ O4 `* p
        while (begin2 <= end2)) h! F" w  i) f& a. J  Q: v$ W4 j
            tmp[i++] = arr[begin2++];0 P( B8 [. @7 p5 X# ~
            : N. h* d; i' n+ J$ k
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    2 a5 |1 T4 {& h    //而不是拷贝整个数组回去
    ; L1 j. _* S/ \# G+ m* [0 @    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));$ E7 w9 I% J" ^
    }" i6 t+ y* M) I/ [$ Z& Y
    $ n* V, A9 P; S4 w! O& T9 r( U
    void MergeSort(int* arr, int left, int right)
    . W+ a# P6 G9 p, M1 x3 y% J% V# O{( K* @2 q6 {$ }1 T! _
        assert(arr);
    7 @4 T& N9 L3 ~- E5 e0 h: S- }% ?3 U; X2 l( w
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    ) X& i( d" s2 [  Y: Z" b% @    if (tmp == NULL)! w% J8 q8 m0 V+ A3 ?
        {4 m3 t- s( l" }# O$ m& z3 g
            perror("malloc fail");3 S8 |# k5 l# k" R& j/ D
            return;
    ) g1 E$ S- f2 t    }
    , J% ^8 w0 U  ^3 ]% J1 Z! C5 \
    - R# F  ~- d+ l( _/ ?    _MergeSort(arr, tmp, left, right);: }, N  N) a7 L+ A5 a' I

    9 m/ ~) }  K0 ?    free(tmp);/ g/ }+ {- {: x0 Y7 b& v' J  g+ n8 L
        tmp = NULL;
    ; c8 ]( @% a: d( L2 `}* i3 e' W; a# H. a
    ; ?8 z; i; J6 H$ v# z$ L6 \; h
    1
    + o: p5 a% b$ o3 P2
    8 W! }& S7 c0 x  r5 I' ~& l6 b3
    6 ~2 e( a! F+ P( j) c% c4" u: W8 j) H1 {) N1 K  F0 O: h
    50 P+ X4 M0 h* M3 ]' D7 L5 p, J* b
    67 d- Q8 A/ _8 \5 E/ v+ r# @
    7/ J+ {6 r" Q  Q( ?0 k* ^
    8$ }" Y: T4 o8 t4 C  r$ ]1 a
    9- H% K' F5 [0 ]: Q; `! M
    10
    / J/ a+ R2 \+ g" U- Y11, w% r9 d+ o3 d! }# x
    12
    * T1 s0 Q2 p9 Y% e/ r2 p13
    * W2 ]" I1 n1 B( S( p6 u, H$ w: B( S14
    . a4 {$ s% K# u3 p15
    ( ^9 a2 E$ o" d" Z2 I; B, s; K8 t16( b" @  f2 I: z2 }
    17
    2 `" Z3 q# {, x" u% J9 V2 n187 Y) J( c! i, R3 e. G8 @3 E5 \# @: |
    190 Q; B* r1 i. \
    20
    2 m% Z3 X. B& c# F( Y9 T+ m/ Y21' ?0 U* x9 ?) w' q0 V/ w2 U6 ~
    22
    % q5 J# W/ E2 W! T$ X23; ^, }8 N  m8 `3 Z9 @" S" ^
    24
    7 _  l' @, c3 z# G  V2 E( }7 x7 K25
    ( C. w" B( a5 ?4 X26' z9 y4 X7 f. ^, ^. u
    27+ `: s0 D" |1 Q6 H$ s
    28% ~2 t; N) l* t) _1 J
    29' d1 G1 h+ B9 [; A/ x% s- {
    30- n* x) H8 e- t- k* m. ~- R) B+ p
    31
    ' z/ A+ C9 A6 c( c2 z328 v& J) w- ]# ?# B7 E  @5 N
    33
    9 l/ U( @1 [( O& S34
    9 _7 r+ ~! e* E7 {35
    / n: I/ s6 Q! {/ m7 B8 ]36
    % D& a/ z/ M' K. r) {37
    3 O) @/ ]( X& V- \4 Y38
    ! ]- v( F6 j3 Z# B' |395 Q( e( G: ]$ x/ ^2 Y; ^
    40
    ! A! h7 n) }% L3 {" r& q41
      K! {( V1 N/ }- M" m422 N. `) a' C+ @) r' P# k' S
    438 n3 a9 w+ m$ z9 \  O3 `7 {
    44
    2 b( J/ [5 g) n7 X4 u457 l' K6 R3 N& Y2 g( ^
    46; ~$ W' s# L3 o2 k, D
    47% o: }4 v2 }5 I, v, ~8 ]. `
    48
    " y5 `6 s2 k6 t: X+ b49, ~3 o! B- X* o
    50
    2 V0 d$ l! }9 W8 Q6 E0 O( w, ^511 n4 h3 F( ?- M4 {- r. S5 N: n3 `
    非递归实现
    : b" e! I7 k$ i* `5 q! y8 o​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    / X8 |" T5 P  L& v! T5 B2 `+ W* t6 q* ]8 O9 k; Y( e

    0 J8 g* p; ?+ F( I, O* p+ F1 j& F7 z0 [9 }
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。' i3 E" S* {& L# H3 d) C

    4 V- n2 O+ s$ e+ A​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。# [% S- E2 t* z' I. _9 d# B% P! Q, f
    2 _6 N2 B& v# ^6 f. |* E3 ~
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。" T* Q& e% K7 K6 R  g( Z' Y

    1 G2 ]# t4 o- |代码实现- |3 Z+ M9 j' l8 Y* e6 q' e: ]; r
    7 u3 v6 q) y1 ]. W
    void MergeSortNonR(int* arr, int sz)" ~1 U) Y" _4 G8 n
    {
    6 \8 p% S, w4 N2 {) X    assert(arr);9 m) M3 y: n5 |& H
    , I6 x$ a/ A; P# K3 g# q
        int* tmp = (int*)malloc(sz * sizeof(int));8 c2 [2 k2 M& `2 y5 b
        if (tmp == NULL)  W" v* o' ^3 ?& w5 n
        {
    7 J- H1 P/ {. Y. S, j+ f/ ]        perror("malloc fail");
    , J! r. D% c" f9 ^9 _        return;  u9 k) j0 K+ A+ J2 }. ]& U1 E
        }
    - `/ q1 w" g6 ^9 f/ b  H) x/ J1 D* l9 q4 Y$ f; p; |% R0 m
        int gap = 1;
    : k. s- Y/ @! `( r+ i1 @. n    while (gap < sz)) K- X: }* o; c9 B, h9 f  j
        {
    # B; E, L8 T8 g) b9 T        for (int i = 0; i < sz; i += 2 * gap)- w$ i7 P1 S$ u  Z
            {# O; W# Y8 ~: a3 A# i  J
                int begin1 = i, end1 = begin1 + gap - 1;
    , b1 g. S/ E) `, P            int begin2 = end1 + 1, end2 = begin2 + gap - 1;1 ?/ B7 d2 l- j$ f5 }8 \
                int j = begin1;# H: O0 z8 `: D% T9 u1 Q

    # K. l( f1 W8 |' U/ ^" d0 `6 \! c            //归并( ]' n' {' {  k; _' A! t
                while (begin1 <= end1 && begin2 <= end2)' N$ X. v' R! I1 ]( P* |1 S$ t4 D
                {
    5 \8 [4 Z, B% S$ e; q1 ]0 t                if (arr[begin1] < arr[begin2])
    1 ~% D" w3 f; N3 S$ {# h3 k2 `- b                    tmp[j++] = arr[begin1++];2 p% B& T0 \9 f; ^% _; q4 V
                    else     $ J5 D* E0 T. A/ o
                        tmp[j++] = arr[begin2++];
      }/ A! @! c1 P6 c            }
    7 Z% l! m' x* s% G+ ^
    " K- t, p% g$ ~            while (begin1 <= end1)! q, A/ _5 r: W4 T$ w
                    tmp[j++] = arr[begin1++];
    * J, T3 G% ]6 m7 C7 \  K            while (begin2 <= end2)
    , [5 @+ p" S+ \9 X' S                tmp[j++] = arr[begin2++];  j+ H# x1 l5 S1 O, D

    8 n  T( K; r# J            //拷贝回原数组——归并哪部分就拷贝哪部分回去. W! }, u6 Y& G0 Q
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));6 }# g0 c" b) d- M, l
            }; H8 B& y- G/ P5 G2 u) X
            gap *= 2;4 \0 R, ~7 m- a
        }
    3 W. a$ a& r9 Y2 y1 }2 V, J  _6 H3 d% }9 O1 L* I  b5 w
    }
    ' {6 i! d8 T2 r
    8 E- P, x1 O3 C' K. T7 y18 E# n# b/ V9 C, T% G! X$ i) j, J
    2
    # s( Y# A* R; j- Z. t31 [: K9 l) Q4 L$ I' H5 w; {3 W: R
    4% u% Q7 H7 S+ ]# `& p6 H( S& R
    5
    . J* T# Z& U; P) R4 M. e" L6* k5 k* a- i- Y; m
    7
    2 @+ V/ x, R+ B- [- K; Y9 h6 L- Z8* E6 j0 @! ^5 ~+ v1 O0 Z
    9: Y4 ]1 C) U0 B% Q$ M6 t
    10
    " r2 F* @3 w( z11
    % r8 U7 ^& M/ ~' U2 S12
    + I- G/ ^% K! Y13
    / _& E6 B6 ?% \# r1 t! M  z14
    2 y! c& d" ?  u153 R6 ^0 Z. u: R) }0 \9 [( G
    162 H& ?6 ]' J6 @( q  q$ y  k! q
    17
    7 x0 y8 i( b$ `: W18
    7 B& @( t: Z% [! Z& ^& P) g  M197 T7 O3 X1 c6 ~* B) E
    20) Z* [( J  u% a: T8 x
    21
    1 q/ S4 E: u( }& ]22# W7 s6 R$ m. Q1 G. y  H% N( j, @" k
    23
    * h) j+ |8 _2 \2 V; H) w24
    6 A( ]8 \  y; W+ [0 d' U- i25" M/ s  T6 D; _
    263 \3 S% R9 U% D8 _4 q
    276 O2 p2 N/ ?0 B- b- O7 M' z
    28
    & g) \' S6 N, N$ |2 W- {8 M299 L4 i! I# d0 P+ x9 z0 X2 ]: j5 W
    30& V- m2 H9 `" a& v5 }4 C( ~8 k
    31
    7 q: V' V8 c( r  Y: Z32  \% t8 C! _+ C1 i: V  w" j+ f
    33. E+ }3 j5 |7 p3 r) X* A
    345 Q' H! i' s8 x0 y' _; o- `
    35
    * ]$ s! n! s! @4 r, y- c% ^36
    4 z' `" g' j1 ?( x4 C: Z37
    3 K1 ^& |( P7 S2 Z' H38! w+ N9 Y  }$ o- d6 E
    398 V( ~& c/ j& s9 m# l. A
    40
    / t% d$ @# R$ q: D41: Q/ I+ I: k9 |6 ~
    边界问题
    6 `- H+ E# B' o0 l: l* Q​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。, D+ D: v/ v+ O: K$ U6 p+ h  z
    * Q0 P, s5 j7 x3 F
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    9 A* J8 E' D6 A- {
    ; k! b0 i* ]. w' g2 }" }( Y* B
    % v' {! N/ d* S% c8 V  ^; ]; y# [( L( j; p- c: q* l, b
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    : b6 w% n1 G& C/ S* \4 I/ I* \  n+ t  n6 a
    第一组越界(即end1越界)
    + l, {$ b3 z3 {; S& I8 N) s* ]* p# I
    ; b: q  \- a. P; U$ T应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。: g, ^7 |( W! h# n. [. V
    6 B4 T# p) d# q4 E5 N
    第二组全部越界(即begin2和end2越界)
    / z) o- _( s# e% j) R  _/ e0 k0 n& e
    % V  q0 e0 {& R& w0 L$ v/ C# g应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。( ]8 s7 n( x1 Y6 r

    " y4 s$ i' C# l3 G3 [2 H第二组部分越界(即end2越界)
    9 g  T9 j7 P/ X3 X9 ~. H; [9 B7 d5 ~6 f0 C: @4 f) h2 ]
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。7 c3 y5 U. J5 g$ `5 z% n7 k
      O: U4 U0 b& z; m, i& F9 ^
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    8 ]  m3 L0 x. O5 I' h  R0 z( C5 i  q1 d6 k
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。7 k* g% o/ h# M( E2 ]; h
    9 }: W7 U; O% C
    ​ 拿两个数组试一下:
    # k/ I* x0 P( J: G$ h3 r! i8 c; M$ T- k1 v5 k& W: Y

    8 L& c8 O6 s8 W4 E4 Z3 p! i
    ( R, c" t1 y8 ^% g+ [' T$ _* I+ c  e2 q4 O6 h, b

    7 B6 y7 N4 p& `  h. s" o# I代码实现
      r' R$ t+ q- B) p& G
    . b) }$ o8 R) L. ~$ {& z0 vvoid MergeSortNonR(int* arr, int sz)
    ! g; O* E8 f: f; ^{" Y/ @1 j, X+ a% ?8 T% A% L
        assert(arr);
    + _9 H& I# S- x# I  t
    ; I2 t* ]6 K; ^    int* tmp = (int*)malloc(sz * sizeof(int));. d) z! e* |! O' R# n
        if (tmp == NULL)
    4 G3 @" L$ E! S9 Z# s0 A    {& h8 l% U$ ?! t3 s* f5 w
            perror("malloc fail");! j% M/ G! E6 v. k: o- b7 R
            return;
    6 s. S& C$ d5 V8 \" ]; w    }
    ; C* n. p; `4 |! O/ |* b
    4 ?; H6 }3 H" p9 U! E/ f    int gap = 1;" G2 E" S9 i* F+ U" q1 f! c
        while (gap < sz); t7 d# _. M, E$ J& a
        {3 s( E1 D! L; B
            for (int i = 0; i < sz; i += 2 * gap)
    ) d' L4 T1 X3 z$ F# M        {
    ( k$ W3 ^* ?+ v; X            int begin1 = i, end1 = begin1 + gap - 1;' L& c) Z6 C- s$ C& E1 a. n
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;' |, v3 d, s, ~+ ~
                int j = begin1;
    $ J5 k- ?# Q  |                        //越界检测
    & ]  [: [" a5 P0 {# F% A            if (begin2 >= sz && end2 >= sz). j( D; q. T8 p: V5 ^
                    break;+ h& p0 X" I* U8 `2 l3 k
                if (end2 >= sz)
    % p1 T  y6 W* n0 l! [- z7 I                end2 = sz - 1;
    * u% \8 o3 E! j/ t. k            //归并/ d  y: C* u/ H& [7 s, w
                while (begin1 <= end1 && begin2 <= end2)
    ' Y6 q: c0 [/ E' A            {$ _/ }6 f3 R9 m; ]4 c5 @
                    if (arr[begin1] < arr[begin2])
    $ K$ r' V. D' q8 D& a                    tmp[j++] = arr[begin1++];- M, L" y2 t) N0 b
                    else     
    7 g8 M5 ^, \) ~! }7 \2 m                    tmp[j++] = arr[begin2++];" }' }# \6 e# y
                }
    # h! s+ @6 H7 v0 ]" ^2 L* N4 }+ m
    4 G9 [; t+ b% D8 Z" y, `8 y            while (begin1 <= end1)
    ; B4 V8 g4 P5 p: ?                tmp[j++] = arr[begin1++];) G+ I3 S. M: y+ P/ n) l9 W
                while (begin2 <= end2)# G' `) F7 ~4 q7 \
                    tmp[j++] = arr[begin2++];# Q2 t, x, Q' b
      R8 A. z6 G! t1 @8 m' c5 G7 G
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    2 m4 L; O# s3 @  z, K            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));6 z, q* ?; M5 A# U
            }! z+ }( M) {- W/ Y/ E  D
            gap *= 2;
    , a& D+ h. j( F4 F. O% }. q    }
    1 M; m0 D' l# u( A7 [* e
    * o5 w3 z3 Y9 @- k1 _. B8 P}# Q$ ~0 l. w; B( {/ Y/ p

    " R; M  W- P9 I! o" `1. E; ^! R9 Q) G% V5 O' u) @8 ?
    2
    . S. w0 W% Q3 {0 B! w  s3
    # }/ ]  T* Z( K  @5 z$ C) A4: F, h, y8 I4 Z- ^/ R. K+ [0 E
    5
    3 y* U2 {7 o* F( a# g, J6
    ! c: g8 R$ f1 ]1 K- j) {# T9 J7. @+ `, p: v0 t1 c# X$ Y' g" n
    88 n- e: J" ^8 V: b* O. {
    9
    * \+ s4 M2 G' a( M! T0 h7 z10
    : U5 y* W* J/ f8 A" @110 r; u; S7 e! M0 Z/ e. e
    12
    : H1 G# O( ]8 \) `& I8 L13- c' L' D6 q% d- j
    14
    2 z5 O- v+ n, o15
    1 a8 ?$ F' N5 z: d16
    % O) @6 @# F5 S% F17
    ( v: b" O" w! r1 h% y18
    / _; a& O  K, @. c  H! U9 n193 w% B: L% h& B; c5 e4 K3 G; \- G6 m
    20
    ( {  q4 j" i" S! D7 S21
    ) W. Y5 F, V  W6 m22
    5 L% F* w% H# w23- Z  G# }" \$ C$ F
    24; J! J+ g$ `) W0 L; F
    25
    - e1 S7 o- l+ Y: p3 a% O6 G26
    7 b- M3 }4 }  r; N/ h27
    1 x& ~+ I  o. [) P287 m3 g( ^8 L2 I; s
    29
    6 B, p3 _; e5 U0 x1 c; @300 _# s8 w. f0 y, Q. o  {$ L1 j
    31; V. n) b" q% C" K/ n4 ~  x, y" A& l
    321 ~" w' o% ~% \0 c4 A" i: R
    33
    ! ?! x$ Q5 i0 Q: e34
    - E5 @" g( @. L6 _! [* h/ {5 W7 d35
    2 C& W+ v/ d+ S0 r2 |36
    3 Q: V- \' h' C) s9 L: [. s37
    " @4 @; j- O: n6 @381 R/ q1 l% e2 M" n
    39: y3 {" ^5 T8 M( A+ m
    40
    + E. C' H# Q3 G- d" T41) @$ e; C8 E6 _! C: ]/ R5 {
    42
    6 s! p; ~; I" i$ w0 o% K43
      ]: P. z/ d; W( |. R7 p44
    ( r! B/ P1 e+ U! X0 y) C45, v) A* R0 ^4 c" r
    归并排序的特性总结:
    7 H9 u; n1 r/ }  {. B4 g/ d
      T1 j- d2 R/ p% y! c归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    : [! K1 j, M* T8 b& n; ^时间复杂度:O(N*logN)
    3 ^; a  J! ?* o空间复杂度:O(N)! x3 A2 |+ i0 M! P; C
    稳定性:稳定
    $ n/ {  N) q3 ?7 k2 E. I9 f8 m! O' c1 o) i( b) ^  {
    ————————————————7 _+ E7 N- f' W- R3 w
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" K* u7 |: `9 |, H1 c
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    ! X6 h! r1 g: l( s& o- L0 p+ b9 Q3 v; C9 n. p+ _4 a5 R

    5 o8 }% I' K- B& S$ T$ N5 U
    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-5-10 10:55 , Processed in 0.330078 second(s), 50 queries .

    回顶部