QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3320|回复: 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的排序算法】归并排序: R6 W. o8 D( z& A, W
      q* ^, C) p! ^* X4 q1 K9 E
    前言: K. v4 D! K2 x$ m6 t" }& S
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    & ]$ F* H( F1 z1 @  Q  d5 z4 ?  \  x" v- p
    归并排序
    ; _4 @' |; x! {* W4 @基本思想
    & V. r" \1 _. e& I0 y​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ' x& A& V. d: b( m$ I2 @8 K. E. D) q
    ! z7 q" P# B  Z; E5 z& Z! J9 u
    % l' }. x" }& d( j; k9 E1 X5 I- `
    5 @) \& r: Z' W: ~1 S. \& r; H​ 合并的思想其实和有道题目的思想如出一辙:
    $ h4 Y5 L9 s' g8 v' n% [& ]+ z+ o9 p( X9 B+ W4 d5 t& y/ H

    3 Z4 Q4 Z" h* `# k9 m: p  S  C5 u6 L$ E) U/ J& W1 U- e( t& t3 G* C
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
      E8 @0 N3 u9 j5 r, M
    % f! m8 F3 L0 L/ w/ A[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]: J- I; e- G5 f- \, k
    8 K0 k. f8 |, C: W5 |
    int* merge(int* nums1, int m, int* nums2, int n)
    " j9 [, E) I" X" M  W( N* L{
    : I% a4 s" M$ q* e, X  {( G        int* arr = (int*)malloc((m + n));4 Z, T; G  w5 ~- C
        if(arr == NULL)
    3 ^9 O- @- o6 Y: k$ H) P9 }    {
    1 a5 P3 {: T/ h0 G. B- J        perror("malloc fail");
    3 p2 ?/ b+ s% K- |: n8 t5 z) C        return;
    # N1 C, F7 w6 F% u1 A( _    }! f( t. x9 p  O, y( k
    " A! V9 g: v. Z  f8 \9 Z
        int p1 = 0;  s# g9 `6 r( P9 r; N; g
        int p2 = 0;
    2 a& ?4 _+ f, h2 x( O. b9 S    int cnt = 0;
    2 @% k6 s! G# ^* u" v    while(p1 < m && p2 < n)
    8 |! x' e# O& R( P    {/ g8 h' |$ O* V
            if(nums1[p1] < nums2[p2])
    6 h$ o, L, j% h3 T        {
    9 S/ a; o* v7 x7 y            arr[cnt++] = nums1[p1++];
    / ], W* N& a  i& M9 |        }
    / b- E8 [4 b6 K, H# ~5 D( ]        else. _3 P! u4 h! X3 f4 T1 N9 q! z
            {
    ' t, E0 k8 {  U3 f            arr[cnt++] = nums2[p2++];
    , V- j( H2 b* \        }
    3 [- [9 ]/ _  w! {; Y/ ?; k% x, c    }
    ! m7 w6 X3 X9 {* g+ l7 o$ B    while(p1 < m)
      @2 V, G9 M3 j0 v9 \5 |        arr[cnt++] = nums1[p1++];( I6 }+ c4 X3 c+ n. }& k" P" d
    & Q* e: ]1 }: X/ f% B
        while(p2 < n)
    6 Y  i1 q2 ]# u1 E        arr[cnt++] = nums2[p2++];
    8 P& }: J" k  c& B0 `
    0 X+ B- a) B4 v    return arr;! d: m, M3 t. ?# ~! u
    }
    : T( Z% D. }6 R: {
    4 ]1 @) k) X+ \' e12 D1 o. F  r  F) j3 B
    2' u( T8 N! u8 r/ j8 `
    3& q/ S8 S4 A3 k- e& o
    44 G6 m; P* K' A3 x  o- k/ c) x
    5% X) ~8 p' X; L+ e" h" _
    6; J4 q; g9 c2 u: [+ }
    7* ~. p: C8 f/ m
    8
    % U( d% f9 N0 N) ^9/ l( A1 L3 F5 \
    10
    7 i" J2 Y9 N7 M3 \( B0 }11
    " a% f4 m  }* J# P6 f127 V& d0 \6 r  f
    13
    - i+ b# ~3 v/ r# j) p0 N/ e/ M$ f+ C14/ ^  n$ }: U/ P1 ]% V& {
    152 T) B- ]% F5 F$ W+ G
    16. x5 n$ `$ m* I4 R$ O) Q/ ^. f
    17
    5 \+ j3 B9 X4 o# Y# f/ G18
    ! o( b# q* V! y5 D197 ~, T, N0 g0 k2 F
    20
    3 [# k1 {: i" B/ F) t( t, j21* _9 I; K. z/ \' _& M" k
    22
    $ l* \1 d4 n+ p, [5 H$ V23
    ; G6 h4 O8 E$ k243 _+ G; X4 q6 m7 |( e0 {) e
    25
    ' C# q+ Q5 Z5 @% u( L( |& Z26
    + @/ J7 A! X6 X( f% g! W/ ]27
    ; T( H8 G, J! l, h28( H: h& Y' b6 j5 B* I  ~- F
    290 [$ V4 a9 j# W2 A  W8 Q0 Q1 A0 ]# t
    30
    - R) n8 C3 G% y31* P9 K2 I( R& P- X  @( a' J3 a
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。4 s" r7 d- i" _4 R
    1 _$ O3 {  U5 W9 _) o8 v
    递归实现7 l& ^. D! g! ]
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    0 ]; i: p" ^( l5 X+ n( I) i. ]# n' {3 m- d$ d# G: D: w4 L$ R" M
    - M+ v* B5 X: P- }

    - Z8 I/ O8 w# v" |( ?; m
    : T( b4 u2 n( L6 v1 T# ?: @& T% ]: I- J- `  Q$ H9 z) R
    void _MergeSort(int* arr, int* tmp, int left, int right)
    - R' A& }1 W- c: \3 {2 L{
    . p4 T% c! X1 c; O    assert(arr);
    " r2 b0 t, A# e
    7 G5 {' R  ~/ P2 [) z    if (left >= right)//递归结束条件不要漏了! [- |. |4 p3 p8 r& @) B4 ~) m
            return;
    # b: w5 @, X+ {$ w/ y9 x6 j0 @; r, n+ k' S7 b# ^
        int mid = (right - left) / 2 + left;  Y7 S# f% a( G; Q" j# @8 _
    & T9 W5 s; g: M0 L, E& o/ c
        //划分左右子区间[left, mid]和[mid + 1, right]+ Y: x: H( x2 Q0 b' F% W# {0 T$ n# Y
        _MergeSort(arr, tmp, left, mid);
    2 b6 e0 `: O+ u0 W; ]5 z; L7 a# _    _MergeSort(arr, tmp, mid + 1, right);; g- H! ]' ]: J1 B

    & X- x( J$ s( z& d( w    //归并8 Y! m- C; `. a
        int begin1 = left, end1 = mid;
    # m- y! O/ ]: C4 Q# ]    int begin2 = mid + 1, end2 = right;2 C) \3 m. G+ q
        int i = left;9 i, F* Y  z3 [' B
        while (begin1 <= end1 && begin2 <= end2)
    9 b9 S8 T" D4 t" j$ _    {0 f% F5 x' s2 O6 A- J( _( _$ C  H4 y
            if (arr[begin1] < arr[begin2])
    , a& c3 J+ Q: N+ |) C( C3 j7 |( n4 V            tmp[i++] = arr[begin1++];
    " G3 ]; y- `6 X2 n* K* A7 ]        else
    : N9 |+ H1 E  s! Z" ?# Y            tmp[i++] = arr[begin2++];& a# L3 |2 T5 a
        }7 ?* y7 q8 s5 g1 `- Y% W

    ' O* S2 |! t8 `& F0 L/ k. ^7 h    while (begin1 <= end1)
    0 u) f- V& H# w( G/ d$ X) e        tmp[i++] = arr[begin1++];# q! C4 m0 d% D; j; J8 S% S; F
        while (begin2 <= end2)
    & k3 {3 k- L% G& G. o  ^2 p9 g        tmp[i++] = arr[begin2++];
    ' F! n6 R; q& u       
    ) P/ W! p# G2 t4 w2 m/ Y4 f$ R    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    4 O% V) }6 ~& @$ W: {+ I    //而不是拷贝整个数组回去& m; X7 Y; z+ g) O6 S" c
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));6 ]2 Z' Q3 G- H
    }3 n$ e! F) h3 Z9 x' d' e& [2 Q5 F/ Z
    $ K' x: H* ]+ N7 `/ B% Y
    void MergeSort(int* arr, int left, int right)  F+ `) p& b- @
    {) s/ w" V( S) w% X7 L
        assert(arr);
    ' x$ Q9 n  p: m! O  A' D6 T, o3 e' m- `; w) Z
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    8 e1 S) [5 m  Q9 \% Z6 z& h5 Q2 {4 p    if (tmp == NULL)
      f! ~+ J8 j% a  l! ]  p3 B    {
    , B6 y9 o! Z- s3 Q; w; C        perror("malloc fail");; M, i9 f4 j; S0 q! v6 `! O
            return;
    8 D1 c! _5 P0 R: D% }    }
    % j- m2 F( w' x: I7 z$ ~; Z! v0 ^1 y
    - O, v7 p' T: {" Z% E9 l) n    _MergeSort(arr, tmp, left, right);" G+ b" l0 D, b; P
    9 |( n/ j$ h' R  H
        free(tmp);
    # a8 ^; K' P+ j8 [3 s) k    tmp = NULL;
    9 S4 y2 p: W6 I2 z# d' K7 P$ H0 X}$ @! b' W+ n% A& b5 \9 C3 o

    3 z1 r4 I. g' b5 F1" H5 J5 s' w* a+ p/ z! e; H3 M8 N
    2
    : l9 p0 t. y) N) v# Q3
    ) Q% s* P+ W0 l4$ M5 B# w6 X, e. k
    5
    7 `6 y+ r' G& i# b3 m# ^/ t8 E6
    ' X" B3 g: j. `+ j0 t7
    . ~' G: |# k9 j+ g4 S8
    + ?6 O+ y$ ?" V" z* i9 ?9+ X( J8 W2 I* R* p, A# W; i
    104 i% n2 v4 ^; j' L2 ]" e) G  \
    11% N- m' R: `8 h! k5 e9 X$ k* i, c
    12' {) K, e+ B6 \/ ^/ A% g) C% c6 g
    139 y( Q0 I' O# r' _+ S
    14
    4 N8 y9 L; I2 m3 G! N+ a7 r: p' E15/ a; N' w( N, |3 |
    168 p7 X2 h+ U5 K4 N4 V5 {. x
    171 w, P$ q) }5 P: u' e
    18- Z! D5 h% S$ q, {* s( d, D4 Y5 x
    19
    + }3 k, Y" j8 t207 F( f. u5 I  I) j" u$ H" ?( k
    217 J! n. S% x; _6 n
    22: |* q+ P* v3 W
    23
    6 ^; Y( J- i" s( D/ r247 A9 N1 y2 s9 F: w
    25/ O  \9 G4 O. _6 i' a. F9 ~# V1 Z
    26) {1 j$ f) t" u
    27
    + W# M0 E+ ^# w' Q/ Y( r; \( W6 Z28
    $ Y; P( }" E# @7 l  f1 L29
      p4 Y5 ~- R" y; v" ?: l5 J! k30
    " T. ^' r0 ^/ T" I1 A$ q31& W+ }( r/ K5 L3 z7 ~# m9 D6 _1 ?
    32
    ) W& U% O6 Z$ K7 T. M; S9 H33/ _' F5 f9 K( m( D7 `$ k
    34) i* x: K% R& F+ \" i" ~; h
    353 P9 ]$ ?9 k% Z$ v% w) |. i4 W
    36
    2 i% [2 j) O) _  C! M! }, _37" {. Q. x6 P2 m9 ^& p5 P
    388 q6 ~( Z4 y, }, V' u* j1 j  s0 k$ V
    39
    ( U8 J- N3 E, D40! \0 S7 r1 K+ t! H: U$ ]2 b: Y
    414 N. Z# L" y# D* i
    42
    % v, Y+ ?% A% P5 V# a% m' E43
    $ G1 p- ?* ~1 f" c$ @, O44
    ! H: d% _7 |& Y- @1 J45
    9 N4 S4 f2 ^) B: Z/ x46' m3 W$ i* c1 L4 {6 {
    47) Z' ]0 n7 y" v. h6 V$ |4 r
    48
    - W1 K& j' Y2 J" G+ R' x/ J49
    & T8 S6 C+ Z1 b; u50
    ' t/ C( C5 w# N1 z1 q; `$ q& ]51
    * S4 \0 G5 H4 Q4 P! H  B1 w非递归实现) H* f+ L# J  Z& T6 q" f
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    % O8 v3 r# E* b3 l+ V0 N" e* @  p8 ?. N4 b
    + R$ T4 @3 ]" s- t+ N
    : `9 g# o' ~$ o& a  Z- u! H+ c
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    + l) i8 t6 u( K/ z" ?# A% p( W8 A: G. }5 }2 V
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。, `% f! z* }- L0 C* u  U( L
    + h, ]; }& u! Y( s: Z7 u
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。# @7 I! a  y( d( V9 G4 A- e, y

    + f: z' `5 i. z  t4 @代码实现% L) s: b; p0 ~, G! c( K8 I& s9 H' Z
    3 T" g- C1 B: M$ [
    void MergeSortNonR(int* arr, int sz)
    ' Q7 [6 n- t, W{
    # d/ g9 }( I3 i2 i+ Q4 \( U    assert(arr);
    0 ?$ `2 V  E$ x5 g, I0 x6 I3 ?: o& q
    9 z0 x, x) m2 N    int* tmp = (int*)malloc(sz * sizeof(int));
    & N  }; [; k' {, P) x* x& Q    if (tmp == NULL)
    & U( {8 H, w$ |) z# n( }    {( g  w4 B6 i. d: g
            perror("malloc fail");+ h8 q  r6 ^) Y0 M5 C8 Q
            return;
    6 U1 v( e! q+ a    }8 t4 @0 K, v; H. H

    5 `1 \$ e1 [/ T& w# m; g* E    int gap = 1;( U! [1 Q2 k% O. C6 q
        while (gap < sz)
    , B% u3 H# W$ Q    {
    ; s0 @! P1 \3 m7 U0 ~; X        for (int i = 0; i < sz; i += 2 * gap)
    ; X( Z. G( g, T, m, p# W3 f        {  l4 q8 q* R6 \
                int begin1 = i, end1 = begin1 + gap - 1;
    + Y1 z5 b) p; j' O            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ) B7 Q: p- J; Y  a3 b            int j = begin1;
    9 \4 C# z0 ], U+ e( n
    ( s# L, |' o$ i! R# b6 K) ?  n7 J            //归并
    ! c. R% S) n& |6 c2 y9 W- ]            while (begin1 <= end1 && begin2 <= end2)
    ; ^. H8 C; D' b) j5 v% }; B) [9 @+ P            {
    : c" Q( ?! V! N+ c  R# b3 o) L& M                if (arr[begin1] < arr[begin2])4 j) a+ ~' M& I$ F# h
                        tmp[j++] = arr[begin1++];$ t- D) u% j' A" C# o
                    else       s) C: \, f) [. A: d% `1 z
                        tmp[j++] = arr[begin2++];
    ; C) @0 A  _* q- M8 t! z1 ~5 Q            }
    & n3 n* A5 }: ~, w8 l! ^6 q3 r3 ~5 J$ l8 ~- \' Y) _) V- e
                while (begin1 <= end1)7 B* u- c  G# v
                    tmp[j++] = arr[begin1++];  a8 t& r# G7 \) v
                while (begin2 <= end2)
    9 l) A* h  B& h                tmp[j++] = arr[begin2++];
    0 E+ d0 N4 S0 g9 q( ]# h6 ^( [* V/ a4 E8 {- D/ [' _( \& w' {
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    0 p3 `0 Z8 T+ ^$ N! [6 s  w9 O# J% V; i( t            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    2 }7 t) Z. @9 J; S4 y        }
    & E: c' a" a8 {6 ]0 N; g$ V8 @        gap *= 2;) i: A7 p$ W# L/ U8 m0 Z
        }
    $ W+ i" p5 ]3 X7 Y  J! J. ~: N$ I2 p, C* T
    }, L* B0 A, |0 T  y; k

    ! A* m0 j  z; r. Z7 R1
    : D$ _/ P4 x$ ?: U* F4 R  E28 n7 i; o1 e/ p, D- Z
    3
    , i- L! _0 j9 o  T4 e( A8 f4
      x4 z$ T. Q- ]1 d2 ^5
    7 z' N7 U6 b( S4 n5 R/ W6
    & y0 t7 }. I, r# u$ V" l74 b: h  z& D+ U* G
    8  i' {+ w. s+ u: P( U" F
    9/ K4 A0 d' E# y/ n, l# k8 W: o
    10+ H* r4 r7 a9 k+ f+ H! ?# n
    11
    , ]" A* \) n8 Z1 g. K+ S12
    # H" m) |' a# c. ^- D, s13
    1 X2 [6 T& Z- {/ j1 _) R1 x14! l3 x& C$ d2 V7 o: J
    15
    . S* k1 X  d3 @9 H1 b168 d+ t: G; v$ v
    17
    / M+ Y* W- l' }; X, P& h, B18
    / [: \% ^3 v7 D4 U( M19
    5 @; Y+ a0 u! b" |: N20
    + Z/ H3 B+ Y% }) c9 C4 [! r& i" R$ I21
    5 P/ }  Y# o2 R. b# Y: v. h223 t0 g! b# }+ U$ o1 ?5 v+ a4 L& O
    237 }# d; r* }$ J! _9 m- g
    24
    / N5 F2 W3 F4 f) ^% f25
    - P4 h+ I1 R0 \+ v. m26
    / e- Y0 x, p! j3 G27! E$ p" S. v4 |2 g/ i' J
    287 {! |3 W4 b1 h& u& U, G
    29. }' O( C+ F0 y& O1 W4 @( r
    30; W, w2 H# ?5 a- K* }3 [) E" W
    31( Z! g, G8 L' n
    32
    5 v2 ]; H7 m% w6 A, t33
    ; g: [6 {: j$ D9 i9 C- [# a34! Z. Z) s6 s+ E% ]8 Q
    35* s; Y( v; |8 T8 ]# \) V; C6 B
    36$ E' ?0 I0 _( c9 w& W
    37
    / S% g' ^0 `% Z# C' A3 ]) C& R+ ]38) ~( g8 _( ?0 }4 I) T# z9 L+ y
    39* S- c6 ]$ L, j# a  g
    40/ E# R) t; K' x1 C3 P
    410 w4 s3 U6 _3 p% U* n4 b, v4 N
    边界问题9 i; s1 P7 S$ B6 Y
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    7 \( \8 |/ s/ Z( D8 s( B6 U* f0 f# R0 E6 I% ]% |
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    + Q8 A0 P: v9 q( u7 D7 C+ M, O
    " D4 t2 U9 v& v6 |7 a1 `' M3 i! |' L1 e# |0 c8 z- i% ]& q

    - T  v8 a$ [. {' {6 i由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)% [) [5 h  l, x3 o4 B
    . ^" a( X, n, L2 S8 r8 Q
    第一组越界(即end1越界)- j# m, a# Y6 R4 G% {

    / {7 Y) \* V; N, B0 }3 w应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    2 G! R1 {8 U4 o6 I4 T
    - p; x3 I5 j: w& P& y7 T1 L第二组全部越界(即begin2和end2越界)1 n; G0 }3 f4 z

    + @8 Q% R7 l! n# Z6 R应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    + V# V. c* t( J& U5 n
    0 M" r0 Y- I  |; B4 }1 B& w, b第二组部分越界(即end2越界)
    ) k: X5 y; X- T5 b6 V  c8 \; |0 E: X" \" @: |" _
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    - D$ N) l( \" f5 t& z9 y1 O9 g7 a6 m  L2 o! W% T8 V0 \& d1 ?
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:8 b5 k4 H3 v2 k! ~

    $ p7 [$ P6 @* i1 ?6 b; R* o​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。4 `1 C4 j! y0 n5 }
    / t! A' ]8 G8 E
    ​ 拿两个数组试一下:$ N0 y* C! s% ^1 e% Z

    4 K4 C- C& b! r& Z. _0 i# F) e* ^# F( s! b0 ]4 q' X

    - I# K# @4 Y" ^% i1 \" X8 g' G( y# t4 R8 R8 b7 O  T: u
    ! q# d* ?' q" m  M8 H6 Y0 d3 Y# {
    代码实现: s3 v, c, i" \: }
    # x. R, O' W- r+ m% c2 X
    void MergeSortNonR(int* arr, int sz)1 P1 y& d7 n+ p6 b# p" y' y
    {
    ! Y$ A. J+ m" n6 @    assert(arr);
    / p. A- u" j( F+ Q- Q( I
    $ a3 d: B+ E1 v- B3 U) V0 j0 Z    int* tmp = (int*)malloc(sz * sizeof(int));# j" r* b7 F6 f
        if (tmp == NULL)
    7 y1 u  o2 {$ a8 H; b! F8 u1 x    {
    * B, I0 q3 f& i7 _# s! k        perror("malloc fail");
    % J  W+ q' e! b$ L# k  u5 R        return;
    9 A" T: A5 g: c4 S- y! |    }
    1 `" B( i3 s4 k2 ]5 C0 I& k; B! q
    8 x) ]) j$ y. f- X- l5 X    int gap = 1;$ G) l: r" x: f
        while (gap < sz)% P) q( h; V2 p) Q( m2 Q4 h9 N; Z
        {$ l3 T; e. f2 W0 T
            for (int i = 0; i < sz; i += 2 * gap)  u( T7 k1 \1 v
            {) A& B$ h: E; V
                int begin1 = i, end1 = begin1 + gap - 1;7 e( D* X% _& e  |9 k$ g0 R4 L
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;' V8 s4 H+ B2 P2 L% S
                int j = begin1;' O- K! D4 t6 O* U! P( Q" N
                            //越界检测
    0 D  L8 l6 }) h6 F: Z8 G            if (begin2 >= sz && end2 >= sz)
    : H3 i' Z/ ?* @, T                break;5 C" m+ K. M- K
                if (end2 >= sz)
    9 E/ v0 J' A. p6 T8 E6 L+ z$ }                end2 = sz - 1;
    " V( `6 I/ D9 d/ _) o0 }$ w            //归并! j( q! g, a- M/ U/ ?
                while (begin1 <= end1 && begin2 <= end2)# c# _$ x/ J* A
                {
    0 k: y' m  u; p3 T& ~! z2 E                if (arr[begin1] < arr[begin2])
    - v- S- T* R; X1 x1 C7 }$ q                    tmp[j++] = arr[begin1++];
    $ Q: V+ B. T* G# \. j                else     
    6 @$ x. c& k. w% f" {                    tmp[j++] = arr[begin2++];; V! J5 y4 ?* n, D" E3 _0 x6 l2 e
                }
    5 |/ r8 _" O6 }1 P- j# e4 v) n1 L
      d$ Y8 M* {# c2 F% r* r            while (begin1 <= end1)
    ; I; d9 ?2 g8 a6 S5 C6 m, s                tmp[j++] = arr[begin1++];8 T1 T/ J( s# d; d+ q
                while (begin2 <= end2)
    * o( H8 l% V. Q; ~3 @% B                tmp[j++] = arr[begin2++];/ l+ L: W2 M. F4 P9 `. ?" n. L' b
    3 Q1 V9 l" x1 O# }5 M/ n5 T
                //拷贝回原数组——归并哪部分就拷贝哪部分回去8 N+ `) z# n/ x( {
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));9 ^& r; |3 X  ~' m) j+ ?
            }9 g+ e5 l$ v& q: y+ k
            gap *= 2;5 y; a, s8 k8 `; E4 r5 p' F6 J1 I
        }
    ' I- I4 T9 c9 [( g* [* D! g" \
    4 H2 ?* K  V' @# c; j! y}$ J1 z6 D# W, t, q$ u1 N9 G' A+ Y

    & h( q( J/ [# a1
    + h% E' @& H7 Q8 M. C% N2* f3 }* M) r% U, Y' n
    3
    . v$ w& E/ M: k- W& v4# s  y' h. K7 f& K# G, _
    5
    ( n& l1 g8 f# R7 T& t1 y& v6& [9 t, A, w8 r# A
    7
    : x1 A8 I9 M3 J/ t8" W8 A$ ]( f; \4 W) e2 z
    9
    : N! F( S3 s: d3 ]106 e( g/ x4 }# ^# I9 _, @3 z
    11
    - ?8 U$ v1 X# _$ U/ W123 T- C% d# i; a
    13: j& ~; q' H, T! Z7 C
    148 ^, q; _* c4 U  j( O
    153 x) b3 P; E- `3 C
    16
      _) S8 s7 b, @# z171 Q. S3 Z0 }% G; w
    18, `+ g' ?" U: U2 W# H
    19
    " n7 r) K/ b: w* m" n20* t0 p# h: R" l4 x6 y
    210 r* R3 y# M0 l+ T( S: y! @* S
    22
    2 Z/ d9 V6 A$ ^1 X5 W& c9 k0 d3 Q6 }239 s. D9 ~) r, u, k$ R( A  R
    240 V2 [7 ^: y6 G+ V- j
    257 ?4 D" b4 k: m% g
    26
    ) j4 R# O0 n9 }4 V" T1 x27
    ' h  `2 |+ s$ q1 ~4 d) p; n28
    " j) u2 Y. ?: @+ E, W7 ?2 P29
    / S- P' d4 i0 a5 F; M30* x0 K: x: Y4 c8 U. R5 X7 O+ Y( ~2 l
    31
    6 M" A8 o! b. G32& [' R/ a. y# ]9 ~: F" C) H: _6 e
    33
    ; f- {# [: T( J. A5 m. D34& k7 X6 d3 p9 _0 _+ k1 _- `+ f
    35
    5 h! K) C" R% F$ a( P36
    ' a: @! C! ~' B37& \: E: P/ Z- L: A
    38+ l, h. H9 ]; d
    39( @6 c3 L: M' @! e$ }- |2 X( k' W
    40# S6 B& ~4 w+ ^3 R3 N0 {
    41: {' D2 \6 q1 y& L
    42
    ) p  U+ \4 v% b+ J+ q& v43! z5 D* b; ]' n9 \
    44. G1 n" n. E( j- y) |
    45! ?4 d, G- ]6 ]6 h8 x+ d
    归并排序的特性总结:
    + v, l; `# t* y; ]( b! X  G# R' N  f( D4 y8 O$ @6 X( ?) j
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。( _( {' ^! ^+ ]$ Z3 Z
    时间复杂度:O(N*logN)6 d. x: w2 `& p& ^, j( j2 x
    空间复杂度:O(N)3 t$ [$ B  @* l/ L- S+ ]: u
    稳定性:稳定9 J9 _. }  O* [8 y4 D" y* q  i( z! e

    5 [, F( t% M8 I0 r, c6 d————————————————) `$ A$ R* _9 s9 c% i
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    # x  M3 d$ w$ o& k5 R原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    / R% P: i/ h0 {' g, I. o0 k  A
    - j. n" v( Q1 F0 }
    ; i# ^1 Y: ?: O% w5 f9 v3 G& V
    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-7-9 13:50 , Processed in 0.510130 second(s), 51 queries .

    回顶部