QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3294|回复: 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的排序算法】归并排序
    1 e* P8 F7 u" \) {7 `% Z5 J* o5 \+ k+ R3 U. p
    前言
    5 o- Y, G- Y, Q本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    ) v3 s- ?, `1 J* S/ c: x
    " c1 Y6 V4 I# @归并排序
    4 y9 O1 \1 K+ T, t2 z基本思想
    % }5 Y% q" H! o+ A/ `9 e, {​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。- j; D' @9 n0 k; ]& i/ O0 }3 ~

    + z; \& K8 w2 g0 I! E4 v3 w* ^$ M1 B. d1 f0 E8 k1 Y; p( m  L# r, D

    ! ?4 k( n  I7 F3 }4 _& ]- a6 B​ 合并的思想其实和有道题目的思想如出一辙:
    ' V, w2 l0 |3 l
    0 j9 M% B# `3 X* p1 U: S. I; }! ], w9 t, Y8 X( [9 J( `

    6 @3 K4 e) x  S: S​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    ; G8 X* @% u- p
    0 F8 ~+ ~9 o3 [- j; B" k3 }[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]; R" s0 X, d7 \4 j; X# D7 W
    ) N3 C  L+ [% {- C# ~
    int* merge(int* nums1, int m, int* nums2, int n)
    & Z4 n; E: j8 L! }6 j, p8 i, R{3 @6 w# X) H# B4 [0 Q* J! w4 a
            int* arr = (int*)malloc((m + n));& r) H& O! J' }  T$ Z7 \
        if(arr == NULL), J" E' g( F4 \2 R' Q, m
        {
    : Z$ v+ j% }; _% @" J5 a; }        perror("malloc fail");
    - [4 q, X, c3 E/ w        return;
    ) ^! X1 Q. ~3 A    }* o4 A1 d% Q' B; a+ U- T
    0 s; b7 f7 x/ n% D) l9 ?
        int p1 = 0;
    1 d3 k( i$ Z0 f! j$ A    int p2 = 0;: D. z( C+ {7 [: L# h
        int cnt = 0;3 n0 D# ?) C$ ]5 k  a: n$ |6 v
        while(p1 < m && p2 < n)  D2 Y: |0 Z6 N. @9 L9 t
        {1 ~) P9 S( V) ^* R
            if(nums1[p1] < nums2[p2])
      M5 T/ E  ]5 w  e' J" v5 J; ?        {
    ; k4 ?7 E: t8 {% z# p* w            arr[cnt++] = nums1[p1++];
    ; O# ^8 T9 Y$ C. P: K  G        }% l7 ?) I5 `, I; y
            else! T* ]5 l, j9 X  |- d4 @, u4 ^
            {
    9 ]3 a4 L% E/ ]7 |& g            arr[cnt++] = nums2[p2++];
    & S% u! V% e# _1 K6 b* U        }: `) |6 m2 n4 q% `& P
        }
    $ i8 v- s- c$ F    while(p1 < m)* d4 @2 B! X, C$ `! O% U) o
            arr[cnt++] = nums1[p1++];- A$ }/ V' c  o  d' i

    4 y9 d; z1 W+ z1 ^6 F* P3 f    while(p2 < n)% m9 G4 G5 H+ ]) a) ]8 P8 h' [
            arr[cnt++] = nums2[p2++];; g* K- l% O, R0 {3 K+ X# V3 }) L

    " D) t% j/ ~' m    return arr;
    1 @/ i( d2 t+ R$ [}
    % l" o' r, z0 g" C' T
    & V3 x5 P" G8 F* f) x+ P1- \; R8 i. m& ^3 K1 ~* Z( V
    2
    ( p6 t2 }3 i6 B/ ]3% w6 O& O  h8 }" k  F
    4
    ! w  }2 t0 G5 K" P2 L2 Q52 m3 a( U! b) Z4 _6 \& P
    65 Q/ G) j- g, }8 X, k% O. b, a
    7
    $ U; K# ]/ a5 U" U; i& V8
    2 T, D7 w$ F- k. k8 v$ \92 K7 l/ O3 @+ z% L: s' |! g
    10
    4 o$ j  i! m! V11" y+ D9 Q/ W: L8 \
    12
    , r/ c- V% Z. B. t3 `13
    & X" h! X7 P0 W% h8 ]* B14
    2 T5 f" a7 C+ w155 Y% v, Z- J- p, E1 l8 \
    16% G# Y0 ^% N6 J( r# e
    17% D4 D* X3 b! I" C4 |! ]4 O$ b
    18
    1 D( N9 q' e& _* n- K7 e& L19
    ' l0 F) q2 }2 L/ S3 k7 \20/ m& V( g7 @) r" w7 p$ h! F+ o7 T
    21: H) r2 k1 V) z4 u
    22- B2 u0 q/ L& i
    237 t8 |8 T* j+ z4 k* L
    24% y8 w# x4 H( p7 ~+ J2 {8 r# i
    25
    : {+ J  N  m$ q2 z* u263 _! n; G% U: G7 p" s" r. v
    27- ~3 T2 J2 W2 [. h
    28/ T1 i7 k5 ~% b1 u/ M# d9 e' @0 A
    29
    % ^/ t; |1 J, C1 {6 U1 g( K30% _# m6 E( U' W9 `3 w# L# z
    31
    , P, x7 r) H6 `2 |4 u/ B5 y7 ~# @​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。& q8 l# J) P+ z. H4 y

    5 [2 a7 |$ ]# ~& b递归实现/ S: Q9 U. V0 K5 c% c! o
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    7 A0 {- X, u' C2 }- ], Y# e. F( q. v

    ) H) b2 t1 [) @$ h! ]4 t# p3 Z. [- d5 a
    0 s& J3 t; @. X1 b

      J+ ^$ j, r6 ^; H6 z3 z$ Vvoid _MergeSort(int* arr, int* tmp, int left, int right). m( E9 x8 ^2 l+ S
    {  ~( U9 w9 N- U" A8 e
        assert(arr);
    9 X0 U. T" t& y  ], q" T3 y" U3 }" W5 g5 F/ Y+ l, ~+ r3 k
        if (left >= right)//递归结束条件不要漏了) @1 A+ ^+ I3 S+ ~4 ~
            return;
    2 p" z, \* u5 C' ~0 {4 P! L
    2 k* [9 F9 ]" g' p    int mid = (right - left) / 2 + left;5 R6 h5 b( f4 g# T3 S. n2 p

      N/ V# s/ `; s; f% h' d9 ?" d    //划分左右子区间[left, mid]和[mid + 1, right]
    + O% A- B- R& ~    _MergeSort(arr, tmp, left, mid);
    8 B4 I0 M6 e$ T8 S1 ~0 x5 ~, y    _MergeSort(arr, tmp, mid + 1, right);
    ) y! ?" A5 x% O( o: M
    % O- ?2 x$ o1 U1 a2 m. o    //归并! O, _3 H1 W6 `. d+ l( m2 f
        int begin1 = left, end1 = mid;
    " w" t! Z7 K# S1 {/ k4 P) U    int begin2 = mid + 1, end2 = right;
    & Q5 t5 r* E2 H7 f0 a8 y# ^3 ]    int i = left;
      V2 p5 v# Y5 E5 t5 Z8 j    while (begin1 <= end1 && begin2 <= end2)1 }5 @; B' d' v
        {8 z, M7 x$ s+ I3 F0 g
            if (arr[begin1] < arr[begin2])1 T' V1 ~% i+ G7 @5 o% a  {1 z
                tmp[i++] = arr[begin1++];
    8 {) K5 H: j, X$ |        else
    ! T9 @  T5 v4 L8 }. P0 y; Q            tmp[i++] = arr[begin2++];+ P# u( X5 i% p7 t4 @3 ^
        }! E, n0 p5 f7 }) P( S0 L

    " l+ m- ~. o( v3 Z# C    while (begin1 <= end1), z% U! ~* `$ P( ]" `( V) p
            tmp[i++] = arr[begin1++];
    3 M& [2 q) J3 x" E9 q+ ?$ J8 R    while (begin2 <= end2)
    3 ?$ {" h( t5 w8 x6 p        tmp[i++] = arr[begin2++];# {9 p  k' }: @. U; R$ G* n
           
    5 d5 `; l! ^/ m, R$ n    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    0 |! @' b$ p/ @, s; d    //而不是拷贝整个数组回去
    ' R3 O4 D. L; I3 h& _) a    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    # D: s5 Z* B* W}
    , p) ?: t3 x" [/ i& i) n7 S1 M; t2 Z# N" K. t
    void MergeSort(int* arr, int left, int right)' x& G- u! R4 Q% v- q; o
    {
    : G3 ^. H0 B' l5 D+ \5 ^' b3 S    assert(arr);
    # C; v. F/ [) }5 L$ I4 I1 ?; N- ?
    : {, c% v: v: g& G; U    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    - j# R7 ]. M* S    if (tmp == NULL)6 {- |* n: e$ B7 Y& A
        {. x1 z5 _; X5 V, j5 y. ^& \
            perror("malloc fail");; V" b1 q, X+ ^* V7 Z
            return;0 H# J: L. P8 g1 s3 C& ~% N" R
        }: j+ W5 f7 E7 B

    / S$ a8 W6 F5 E, b, y; ^: V: @    _MergeSort(arr, tmp, left, right);) X1 T* f8 L* F" ?, T! M

    4 x: l& i8 V' Y# |0 [) s) {& v, b    free(tmp);
      \: {* b' y# E% c% E: R7 ~' d    tmp = NULL;
    * c2 Y" F% I$ a2 Y}
    ; P  N1 z+ x& F( @8 o) @: \: o& P6 N; U
    6 ^0 w* P+ F6 S6 ^/ o2 p1
    ! C' Z$ M' z6 p. \. H. a, O2  g! }4 n( U% A- F$ J3 o8 p
    3, F. D- |4 T" U* L9 M
    4# p4 K( H* x' M2 }2 _0 U* e
    5
    ! B- J8 k8 x9 {* S0 _8 i6" W9 F) `/ E$ o0 l/ z0 u
    7
    ' Z$ Z5 c/ a) ]. ^8" h3 a) _) u7 ]. X" v, @2 {
    9/ c. G6 `6 D/ m9 Q
    10
    7 i& T/ Z- p% |- {, P$ h' g5 a11, w( d5 I- e% c9 g/ g+ V" P+ S
    12) J" o" z+ v4 n: l3 }" I! c
    13
    , ?" K1 q' H* F147 k7 M, l5 S0 g' Z
    15+ W* P( ^0 G3 b
    16; B6 i9 B3 z" o' a+ J
    170 H4 d7 g8 I6 Z: C0 }3 y3 q
    180 T- G/ v6 a. l
    19
    4 \& c+ T* m7 w. f, I20: i2 @' l' o$ k, C; o
    21
    ; ^! C7 l) S8 R; a22; T2 V& Z, c. K1 p, x/ E: H1 O
    23. z6 d  O0 Y% b6 d* N7 [% M
    24# D$ p1 }& T! B% P
    25
    / s" R% m- e; o' J268 y: [8 h( j7 I; {' d7 q
    27
    ( Y* z6 T# N! h* S$ S28
    % c) p( R+ Z) h2 c& }298 A/ T. F7 T) C* Z
    301 y' H7 B+ u8 k9 P. N; R( {
    31
    7 X7 E8 v- r% y: X5 G: R* \/ Y32; \  K) K# x$ j2 e- A
    33
    * R5 i6 Q# P" s! @' m8 j7 p" ]- A34' h( w; i! U1 ?  R
    35: E( w* }# I% v& p9 M! X
    36
    # Y. n5 T+ U. g1 K37& U0 Q& P4 e, w4 O! W
    38
    , S3 Q4 S  M4 i39
    ( V: l$ ]0 @6 X2 D* L- x40
    7 P; c3 X0 Z9 v. ?1 D0 I/ L% Q; C5 V41% y6 K+ t4 L8 ]# N5 x
    42
    6 t0 |/ j$ [0 V0 e( b43
    / h1 ?9 v6 d3 V# l" \44
    0 ]8 i! s' A" n% W4 J7 e45
    6 Z- n5 _- s$ q/ I) A46
    , F$ H* t" F" Z47
    3 k* E7 D. s( @# w48
    % D+ x$ f' \/ F; ?49
    ; A3 U. @( ~  ^5 G; z50
    1 k1 x8 J: i: m7 i+ {. y8 g51
    % b1 t) O1 l$ h$ ^( R" ^非递归实现
    6 g1 R( R! t2 \​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。4 Z7 _' g2 z( q* O) w4 J, i

    / l3 G' @; \' ?+ t: N' o* P! F; F2 J
    4 |4 C; ^% \! y
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    6 `( d5 s1 q) w: _# D1 o; O- W: N0 q7 Y
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。9 y; V: j$ j) c  ~0 L% G3 W

    2 p' k1 @, ]1 ]# h( ^6 M3 `​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。- d  a, e) N( y6 h3 R
    . i7 d' C4 o! y& w- y
    代码实现
    . m. ]# ^6 X+ J+ K
    ! g9 R4 z' S: dvoid MergeSortNonR(int* arr, int sz)
    ) a1 ]- e" S. p9 z; E{3 z, f; N6 F. ~; O4 y" N
        assert(arr);
    1 I. V  M3 f: ^, L' p( r8 o7 A7 q7 j' R; Q9 E+ X4 k" }
        int* tmp = (int*)malloc(sz * sizeof(int));  z. O3 g/ G, i+ ?" @9 s1 D
        if (tmp == NULL)  m/ }$ \5 V, @
        {
    " s9 Q3 b. U! G& x; L        perror("malloc fail");( x( _0 j( Y7 I2 L
            return;* H6 K# [7 e  R( Z* e# @7 m& G
        }
    # K( f; F+ h% J( r$ F3 t6 E1 M/ Q4 M* Y, b& K2 F! Z
        int gap = 1;# [9 o/ t7 }: m( T" i% E4 x. \' d
        while (gap < sz), d/ u1 e) K8 e4 ]/ A# o. o5 b+ A
        {8 ^7 G8 w( {9 z- k8 d
            for (int i = 0; i < sz; i += 2 * gap)
    , y8 ~( i: j4 p- L1 {, H        {6 M2 d# F' W( T" q
                int begin1 = i, end1 = begin1 + gap - 1;5 Q/ s+ P1 w( T( u+ o
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    0 g2 O( n# H& |6 H+ ?            int j = begin1;
    $ y" b! {5 v5 V/ H, f. C
    ' o, V4 z; S8 F* {8 X7 l5 {            //归并5 \# b/ M" [" g0 U& \
                while (begin1 <= end1 && begin2 <= end2)
    ! D; A/ `9 |: u0 G- V: }; A# }, e& I            {
    ( O- l# A$ y" }( k' b                if (arr[begin1] < arr[begin2])7 U! }9 Y/ V/ g( V8 ~
                        tmp[j++] = arr[begin1++];5 W* ^; J9 H5 @% ?, I  M
                    else     
    * _4 x' t! D( r4 b4 I: Q" j                    tmp[j++] = arr[begin2++];
    5 N, U* e4 ?% R5 _  u1 X            }
    , B. N* i7 o9 U' `. h  ~# \
    5 Z4 h1 _2 m$ @  v: V            while (begin1 <= end1)
    : e7 h$ U1 `* Y4 w( T, n2 l  e                tmp[j++] = arr[begin1++];
    4 X7 [+ O6 k, Y8 c; v0 R% e            while (begin2 <= end2)% V4 Q( p% O4 v+ _( b
                    tmp[j++] = arr[begin2++];
    ! W$ z$ A7 e* y# ?, m% q$ y2 I" g, v$ P/ N7 {& f6 j/ a  ~( S3 _" y0 D
                //拷贝回原数组——归并哪部分就拷贝哪部分回去6 X: w" O, m0 B# e, d1 t
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    : p% g2 c3 x$ C& _: `# K! d9 R( ]        }
    2 b$ G" y0 R- K        gap *= 2;
    + f* ?; ?6 F( [+ S1 b/ S& @+ q    }' c0 _3 Z4 S  V! @, D5 h

    - p" p$ G, W4 x, ~. ^3 y5 Z}# Y- q! b+ J. T! m+ Q; E& Z* m
    3 D7 p5 \6 z% R4 L" U" k4 S
    1
    8 {  v1 E- p$ w% I& F( C& S& E/ V! h2
    ( e' E3 q! V, w+ l2 i33 L% _9 E1 O, t) a0 D7 u
    4
    * i- ~4 u/ O$ `9 q1 ^$ P4 h5& H  I# Z) G) I" P3 d* X# Z; y
    6
    ; D# N% h; v9 t; l) S7# L& h9 n7 W& ^# |1 K& K* S
    8
    9 ^+ O! W  l- o( F7 F9
    , \4 m% V7 j+ N* y2 t. B10) X- y$ q. W5 ]- S. }2 K
    11  e9 f8 R% e/ s. K# D) W9 q" m1 `
    12, l& p9 W+ x' i
    13
    9 H9 U! E' w8 t, B14
    1 \6 I3 V  X, l  f6 j& _6 A15
    ( Y5 D. l, K$ r7 P1 [166 l/ b2 M8 a0 k1 J* b
    17
    ; P' {/ F7 `" x$ E18% s9 f/ a) N% W, P( y- |
    19$ A8 ]8 E. @3 w7 r% D
    20! J+ S* c* y: a& ~( A
    21
    ' S, K6 l  s! Q0 a* J22
    " c$ Z0 B9 ]! L* V9 P231 d; Q+ l4 Q, @  v* h
    24
    ! Z# ^4 e; h5 u* @  b- n- P  a25, \' e8 F7 k3 Q9 f) }
    263 d- _  Y# [* u# H- o6 E3 j
    27# F8 @4 N" U& k* m# z
    28" M, e: f: O5 m1 |, ?3 E
    29- D& @3 o" V) `$ h. ~
    30
    3 I( Y% G) h: R6 v& d5 _31
    / y; O3 z+ b( J1 J32
    3 X' c6 y9 B! G$ G33; j: ]* w& U% d
    34# G; X# A. w2 Z4 ]
    359 M/ z0 X& ]" a+ Y" E/ {
    360 j) E9 v( J" I3 U6 O9 H
    37
    $ H+ j; J0 O. U0 _9 E38" a( j) \, Q* {! W0 @5 P; I
    39- b  \3 @+ l3 ^4 Q' Z! C
    405 f$ B8 U% v- T* c/ C! r
    414 E, W5 @" z% J% M7 n: m8 B" p
    边界问题
    1 \' g& [9 H; Q2 A* u​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    5 f. B4 ^( i; l% m5 T
    4 k0 Q. q* g# B举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    4 d  ~! ?' B/ I( r1 z) Q- O* M& G$ f, b) H$ U* a

    & m2 L: m6 c) j, Z2 q6 k4 H: {: `3 ^- n
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    % y7 E* g5 p8 ?, X9 _; d* h7 M/ E& Q% p3 ^
    第一组越界(即end1越界), Z6 {8 i$ }. b" T  X# W0 P- P( t
    : K: `5 ~# y( Y. `1 S
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    4 M" s4 z6 W) T! C' @+ L
    % x3 }* A8 W, y3 m1 k+ s第二组全部越界(即begin2和end2越界): ?$ B- U9 h2 Z$ t. F+ u

    , h* Y+ V# s. J4 y应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。  Z1 a  H. a. @. b
    1 o* v% J; h3 i: m9 n) Y/ ?
    第二组部分越界(即end2越界)# D9 ]2 h! b" y: \1 [7 _0 r

    * {8 ?& Q& a$ A' R+ {应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
      a* G  P  V6 t- f( |$ N1 W. ^7 X6 T$ @
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    2 N, {9 X$ e' h( Z: j) R) V
    0 h# q8 ?, b% _​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。/ ~1 R* g3 H; ]( J7 W: g  }. B6 A

    $ O2 x# C" D6 C1 q. |1 j( x4 N) L* V5 ]* v​ 拿两个数组试一下:
    1 W& x* [( @5 \
    , c" F9 L4 V+ Z; m: J9 h; L  p- a* k- B7 n4 G* w3 T
    / y: `4 @6 V- A8 I: v
    7 I& x  o* {% R8 E
    ' d5 Q) @0 Z+ E& D5 [2 W- d
    代码实现2 `: y8 [5 ?& T! C2 f' l  r

    7 D6 X( H+ I$ `7 wvoid MergeSortNonR(int* arr, int sz)
    , j; _2 l3 x) p( L# h- Y, x{  y% G( S# U4 i$ H, i; e: E; b# S
        assert(arr);
    ; D, o; `3 l$ K9 L" r" q: s, L0 A7 ?% ?0 N! W, R
        int* tmp = (int*)malloc(sz * sizeof(int));
    8 `5 {# D% c. b% C. W    if (tmp == NULL)+ }  [' ^! b, w6 j) \! ]
        {% H3 z$ `, E3 y. W
            perror("malloc fail");
    5 R9 y, Q  a# v' ?# I: [        return;
    " n* \" |& r0 j2 `4 w    }
    + h: c& [3 Z- c/ @- a! g( ?" r6 j$ a9 G" `1 I  L
        int gap = 1;
    + {) L# d: {  h6 Z6 I    while (gap < sz)& Y" N7 k- Y( {8 A* E
        {4 ^5 @8 P3 l! z3 P, y1 C  R
            for (int i = 0; i < sz; i += 2 * gap)
    ; b' [4 Y- F2 {1 w" |% a6 R9 i3 w        {
    8 W& P0 z: U9 w" C& t2 W6 ^' H' k            int begin1 = i, end1 = begin1 + gap - 1;
    1 o6 x' H5 u! x4 x! ^5 @8 t" H            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    - M: H, r% a$ s6 k0 X: F            int j = begin1;( f8 N4 Z) T/ o6 V: t9 S9 g' a
                            //越界检测
    3 i# M; Y1 t" h            if (begin2 >= sz && end2 >= sz)3 W/ r. C: T  c3 M2 k$ g, C
                    break;
    5 y3 i& E% Z" b% I            if (end2 >= sz)7 A( T0 \5 x8 {7 x8 j
                    end2 = sz - 1;
    , l; t9 I2 Q) D. \7 o6 m& @            //归并9 v7 m5 Q$ ?$ r  H$ a+ f: s
                while (begin1 <= end1 && begin2 <= end2)1 |7 X$ Q6 @9 f- R& k& F
                {
    , j& L# M0 c* \' t                if (arr[begin1] < arr[begin2])5 G7 O9 z  ^; H+ K) E
                        tmp[j++] = arr[begin1++];) s  M1 M' j0 u
                    else     
    1 Z6 A3 ^' y6 t                    tmp[j++] = arr[begin2++];7 D5 m: W8 c4 u* M9 i5 \( F; ]! X
                }
    0 Y& @. K) D7 I$ e) P) m, u4 O% i% \- r! L1 G& a  }& r# V* w; |
                while (begin1 <= end1)
    , B; p- k% t2 P, P4 J                tmp[j++] = arr[begin1++];
    - A& k' \, p* I+ I' C* @% h            while (begin2 <= end2)- ~! h# N9 |) u9 R5 ?$ ^
                    tmp[j++] = arr[begin2++];
    : K/ ~5 a0 G% J# c6 c$ h2 t, p7 A
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    0 ?0 \% d# F+ ?& f, ]+ l. j            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    9 Z, B5 U2 o( ]& n0 o) s        }
    8 r  `3 l5 a0 d" t. m2 t        gap *= 2;
    & t; [* [( [  y* [$ ~9 s    }$ s; P3 ]  c4 Q8 l; c$ N- X7 ~/ S
    ! W5 T6 e0 J$ x( D/ J
    }
    6 |- E! H$ Q$ w1 U+ L; K8 ~$ R" |' E& a: M
    1) A  a" G  n- N
    2
    + h  H$ @: H6 x" m- r- S* C3% x0 v" B( b/ {& C7 A, F6 U' [
    4
    " x7 E) r. e" X. {+ O- `& L, P. ?5. @7 F: o1 _6 i% K* w9 J2 q
    6  N: N( ^3 h3 u2 {9 _, w+ L+ M9 M
    7
    , b* d6 M) k% U; @/ S8) _; Z; t9 k9 s& d
    9
    6 r# k. @+ h7 V) d, U$ R10
    1 N3 ^+ K' |; R- {' L8 F11( a7 D( `6 a' A/ U4 Q, S
    125 g& C' z" k0 K) G. k8 r" }( V
    13
    ( X% L; |2 L0 |# |  f14
    5 a* b; B) O) Z) \* P! ]15
    : m1 r# G; Y7 J& B  P6 Y16
    7 X# d$ b8 i  c3 H1 t6 p% o+ X$ V7 q  g17
    , ^% a/ e$ G. I/ A18
    , O7 c  Z/ L* R- j. U198 Y1 \# |/ ?6 G/ f0 s. ?/ M, }" J9 C, a
    20
    ' P  r2 Q3 g, e3 U21& q( e* j6 t& j( j, N: m1 x1 L( B; {
    22
    $ d0 [; K* G' D3 @, }1 u1 {4 v. T9 C23
    9 x+ Y( j# Z  [6 k6 P2 T" |$ j) l242 x0 S- p/ |+ A; m- m# w
    259 |. \4 C5 {0 J9 G
    26
    9 B: l' s& ]( P0 h27
    1 h: _* I( g3 L/ r28) u8 ~  h! R$ r, Y: ?( l
    29) l& K3 M( c- ?$ U' H# `
    300 y6 H: ^" K* t. y3 D& n) x0 |
    31$ {6 m% |+ z$ v" l3 K- }2 S
    32
    ) ?$ I# s! w: O! {3 c, Q# ^33
    2 r  M! M, S" u! u0 Y% o349 d( ]5 M7 i5 U3 m7 E# Z
    35
      @- p& _) ], D9 {0 m36" y, R/ v1 u, b' h
    373 A2 N% D" F' C
    381 v1 d% Z, j: q( V
    391 f" v1 d7 K6 A9 Y: w5 i6 H  L3 @
    40
    ( t; u( [) @- A% T$ U0 Y* m41
    5 i9 D4 i2 j# d4 g) ~42$ u. k& u& \% n2 v8 F
    43
    + J  [; p" @4 r# t; N446 [9 W. ?  Y3 ]9 Q! V
    45
    ; v: ~1 D- _7 n& x+ |+ C归并排序的特性总结:
      O% d4 g2 x2 I% Y
    6 H8 m+ ~8 F# y: b  k归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。6 a2 q& r! S$ B- b8 {9 r& X" D9 l2 N
    时间复杂度:O(N*logN)$ M" S8 U  l8 e$ r% l
    空间复杂度:O(N)5 \* w! \9 R5 Z3 i4 B
    稳定性:稳定
    " M6 D" B8 ~  w% l
    5 P0 S6 h) \- G; m7 H6 }————————————————
    " V0 c- @0 }  D9 I  [/ v% E版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    " r& K1 C8 U8 ~) |原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    ; q6 @, g- t. h, ?+ C7 A0 T
    # H; X5 |; \4 O2 k8 S8 S( u% Y& r' J, T; l
    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-5-25 08:10 , Processed in 0.405231 second(s), 51 queries .

    回顶部