QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2216|回复: 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的排序算法】归并排序
    4 h7 P2 L: T+ }: l. b+ A- y8 J
    0 l9 }9 _7 P3 r$ D% g前言
    8 e& T$ m& x# y本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。8 l6 N" [- b: `' o" S
    7 Z* ]  y! {8 O& B2 G
    归并排序& b2 Q  E# J; n- r9 O! V
    基本思想/ ?$ H4 Y; x& q- n% e. u6 B
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ! o3 a4 a! f9 x- C7 o  g
    0 ^5 T  t3 S# @2 c. a/ [  K( b* D; Q9 Z& q
    $ S. q% J" Q0 m$ O3 |6 `
    ​ 合并的思想其实和有道题目的思想如出一辙:6 D# B+ C+ {( n! O! d% f2 e( g& N
    7 r6 V  ?9 n+ |! j* w. R

    5 E$ P9 Q9 R; s$ q
    % u" r+ j  q+ b7 K​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    7 J' e' z/ _4 B# f! W) }+ J3 N
    4 {( ?% h1 W( S[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]; f0 U4 y' ~) z% m; f2 y$ h( V$ \

    - b/ C+ y& y0 d: p" g! x+ P+ A. nint* merge(int* nums1, int m, int* nums2, int n)
    7 E8 U( V2 G. Z( D/ ]1 g6 L{" i) n9 u+ |% t# g
            int* arr = (int*)malloc((m + n));- p2 J7 o5 r+ R% M- ^0 ^' `. G+ d3 n
        if(arr == NULL)4 x2 T: W! [( I+ U
        {
    - h6 ?, O& y* N. S        perror("malloc fail");
    / D" `8 o# S: }% k; @        return;% L0 t/ ^7 z" Z6 ?) r5 k
        }9 e, H% }2 ^. V% j  `  {
    * A' }- L! j$ i1 h  R# O
        int p1 = 0;9 ~* B3 i" y' F
        int p2 = 0;9 A9 t' Q9 [& {2 n6 U# s) e6 c
        int cnt = 0;
    # v* k* r2 H4 X. y- w6 V    while(p1 < m && p2 < n)' d% j( T! r( i* h2 Q. w! E. p
        {' l8 ^2 j+ n5 y# E
            if(nums1[p1] < nums2[p2])& L! I: S9 N2 [% T) ]) o0 p/ x
            {
    ( x  R6 g/ U% F+ I            arr[cnt++] = nums1[p1++];& a! W# |4 d% z7 ^( c7 X/ f
            }- e+ D* }' s) ~" N$ u4 i4 e
            else% B" z% q& t( w4 ]
            {2 |0 g& }  k2 \0 ?
                arr[cnt++] = nums2[p2++];
    ' b) f* [5 E, A9 R/ Y1 e3 I3 U$ [2 i. F        }
    : ?6 {' q) A. D$ m! W) s    }+ A# a  v2 ]+ c% u$ f
        while(p1 < m)
    0 z' Z: s8 T0 P5 f3 N        arr[cnt++] = nums1[p1++];
    ( C) G; ^1 p4 k: [$ \& k$ G* h3 }# b/ p9 h, h' `
        while(p2 < n)
    ( v0 v7 x( ?; A2 E3 [# D9 c; u        arr[cnt++] = nums2[p2++];
    % v* N, k. e& m- j3 I, ^3 L% u7 c% R$ ^
        return arr;- V- _6 n% R# G5 t1 ^2 S  Q
    }9 X! D, Z( o8 K% t

    ) d) q( D' O7 I, N3 B1" z; ~1 {4 w' E
    2
    ' i1 O0 U& X! s6 ]! A3) d2 `' K/ r' G" m$ X+ R/ I2 J
    4
    # R* ^$ K- Y9 c1 |" O9 R# b5+ a: y3 R4 o. E; e! Q2 I& L0 a; C+ F
    6
    / l( n2 \" c9 {; p" V# I, H1 s$ }) U0 t& D" g7" i( c; N5 V4 c9 x
    8
    ! Z% ~2 s+ |* ]" \1 |; C3 |9
    6 _% P1 |  @* ]: h6 Y10
    : G' Z5 w0 S* M$ ?2 b8 g# u- c115 F: ~- Q8 d! S4 e- V9 L' \
    12
    2 K. j* z/ B- M: e- K; U' D13
    5 v& U1 E  ~1 d# v9 t  e149 G1 o6 `, S& ~$ Y( B/ J
    15& ?% D! D1 f% i: Y* u: m/ G, q
    16. J- z' k" F5 y( b  @* }
    17+ }0 G4 u7 O0 o. }. l: x) a" H! S
    18! u! y3 C+ p1 t3 ]/ b+ t& M+ h+ w% A
    19
    6 o: v/ P# P7 Y( S20( f' E6 i$ G7 m  G6 @: b
    21
    7 X2 U6 z" g3 k& {22
    / J( r9 D4 P" C  C) I2 ~) r23
    7 q5 N6 S; e' u- l& R& f24/ V1 A2 h/ k$ n( R
    25
    ) f# F# _0 K  I; U! v: s1 E" H7 O26% Q' }, ^$ e$ l/ G) k/ E# d0 k
    270 A) m1 ]1 J+ F; b" w( ?* @/ S
    282 r; R: x# E! s$ h, H0 Q
    295 f. {% r: a; v, ?5 @# v
    30, {/ x9 y; W, o, b: j
    31
    $ h& l$ y/ J- E+ y' t- x6 b​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。5 M" s+ S2 a# i6 G6 `9 h: ?+ e
    3 r) \+ Y8 N6 ^; y* F& |+ e% b
    递归实现
    2 p, ]0 @+ w: j0 r1 r/ @7 O% w​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。  S/ U1 ?# h; u9 Y

    . S% R3 _$ g( \' B" B& g$ O3 Y' T8 o  b

    & L3 q% ~. _( A3 e3 O$ X% {: P9 M+ C5 h1 l. P
    9 j* ?# t; r* r7 i/ m
    void _MergeSort(int* arr, int* tmp, int left, int right)
    0 ]  U0 w1 Z9 y3 f$ l1 C6 |* X{
    6 N5 s' Z" u- \0 `1 V$ O& o    assert(arr);' d% S$ q; p* Q- x- }  i, ]- Y

    ' c4 J: E" U6 X* Y' h    if (left >= right)//递归结束条件不要漏了  A) E* R+ K' ^2 [9 t7 J
            return;, P0 F7 h& }, C3 E/ ^
    $ p3 n9 s# h& |8 y, d
        int mid = (right - left) / 2 + left;
      D7 Y8 t2 w" H: q
    * C$ o- m. y1 ]6 g; I, D! u8 i    //划分左右子区间[left, mid]和[mid + 1, right]+ n* j/ O- i2 v2 L9 _) ^  j
        _MergeSort(arr, tmp, left, mid);
    & g( Q8 `- Y- }0 U$ {$ a9 e    _MergeSort(arr, tmp, mid + 1, right);
    5 v1 D; \* Y- A+ _* [9 O* `" k- Y* A5 `) q% R" f
        //归并" k3 T4 ]; S/ Q
        int begin1 = left, end1 = mid;
    ) \7 f. j1 I& K$ |7 G& g    int begin2 = mid + 1, end2 = right;
    ) c' T( u- A; Y: b    int i = left;
    * r9 k7 [8 ~4 C4 U* J4 k    while (begin1 <= end1 && begin2 <= end2)
    3 `* v# @% R! c* W( o3 W3 z    {9 \3 y; U; l1 {2 A' I4 d. G: j
            if (arr[begin1] < arr[begin2])
    % V1 U6 Q# @  [9 C$ G. S9 `4 L' o- e            tmp[i++] = arr[begin1++];0 h& {) |9 X$ @
            else
    * W8 Y4 B3 E+ G5 C( T. P9 a            tmp[i++] = arr[begin2++];) c: s, x' ^) ~/ B6 k) w6 K
        }) X& O: t+ D0 K. a2 Q5 Z) O6 u) M

    - I) ?6 B  U8 w3 L    while (begin1 <= end1), M7 t& d7 z6 z5 a. k7 Z
            tmp[i++] = arr[begin1++];& J- T" @$ p* G% h8 W# V/ x
        while (begin2 <= end2): S% `; C! n$ ]& T/ |
            tmp[i++] = arr[begin2++];" P1 D0 q/ l' P3 f8 ?" A7 o  s
           
    % l% j9 N$ Y- Z& J/ J3 m    //拷贝回原数组——归并哪部分就拷贝哪部分回去4 A  ^4 e3 H. K5 h
        //而不是拷贝整个数组回去
    % t6 R" h/ s8 ]6 M- g* b    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));8 V" x% }! ~. i) O' q  Z
    }
    ; ^2 f  m7 y- D. u0 V* R4 {1 \0 @2 |9 D) h& W: q3 y, u( A' Y4 C' g
    void MergeSort(int* arr, int left, int right)& f6 G( k5 \8 C: H! F5 R) E& R: |
    {3 y2 R! |9 q- T5 t
        assert(arr);! _5 i5 g3 u% ?! Y+ L5 ~. d7 i

    ! f8 }+ ], _7 m: b; B5 w    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));- j) J1 T7 R2 {, ~/ x" Q& A+ J) _
        if (tmp == NULL)) X  J3 f; w# l" _
        {' }; z2 S  A* ^
            perror("malloc fail");, Q2 }# b' c/ D
            return;
    7 }: \0 o+ L$ i! A! s    }) I1 f: T+ ~0 T3 i2 o, Y( x
    # D/ e! t* R3 a8 C- |
        _MergeSort(arr, tmp, left, right);" G# J+ ]1 i& e

    4 h& ~. |; b7 y% F' z* A    free(tmp);7 f2 Y3 r5 s( r' C4 L" C- ~& Z1 d
        tmp = NULL;
    & ]# h/ A& e9 l& M; v4 G4 q) d}
    ( ]! F$ C) \9 r7 z( H& n* n' r( k- ]9 U1 p2 k6 m7 q4 G  k
    1
    : X- R2 x7 M+ t* C- G4 C; _2
    ) p4 r2 O+ f+ z, p6 K5 Z8 w33 h: w2 K  \9 ]% n1 g: S$ u! z
    4
    6 l) f8 M) o8 x$ k# b; p# _* v5
    8 \0 A! D9 A) Y5 P. Z6
    * `3 J' |2 P' q' {* |7( X- C6 T5 _$ F, y, |5 o
    8
    1 @8 P$ m$ \  \95 O+ W7 ?! @/ H0 ~' W
    10
    % t! m0 N& Q  X# m" P1 ^11
    & p& Q* s) ]7 _: l. ]' ^12
    ' m) [& @! \1 N+ _3 {7 V13! @2 M" g. r+ x( A+ ]- \( y
    14
    ! L. \1 r) T3 n$ y15
    ( S2 ]5 p) p" L3 x16
    $ h) x1 ?( a& \+ S6 X9 ~% A5 x17. T" C  q% L! z+ k$ b8 _
    18
    / ~( B0 T; g- F6 b& U# ?% W0 {19
    4 C9 f- ]& ?! S; |# t! P' _20
    8 N1 ~& n; t! f0 F21
    8 U1 L  \, V; r% }22
    , ]: Z- x5 z$ @6 z23
    * M- c9 H6 h2 \, \: y24
    % R7 p' n4 M: A# V! A25. ?3 w+ y1 ^% `
    26( |) L2 n2 v- \
    27! t- A, F9 S8 v: q+ m
    28" ?4 o& z5 I1 d- R# G
    29
    5 l& Y7 E; K5 s6 H. O  L" b- i30# M+ e6 S% {: R4 L% h, H
    31
    , w7 S' I5 ~7 S) a8 U# |7 o8 a324 e5 ?3 x+ X* }5 B) t" c; `! D9 ~
    33
    - c* J: ?/ a% j" W/ ~9 Z8 i' q346 a) X/ w6 b' g( @" B2 w" v$ f
    35
    ' C4 B6 ]; V  C8 a1 P0 a0 C36
    + P+ \7 @. R' t37
    ( M! C5 Z$ w) |/ Z6 k/ L  H38; I" G2 z# w5 U2 l3 q" r$ @) A& s) i8 f
    39
    * n3 q, Y* y( P9 U( X400 m+ b+ v$ R! t" u( x# G* i
    411 x' l$ E$ X0 F
    42
    0 J7 h% q- F0 X. O( y  f+ }43
    + s# d# ~+ B: R3 O9 ~; W' k1 m0 ?44
    - C, W  W: f: H6 h45
    1 [6 H3 d7 ]3 D6 f, y' ~46  ~+ Z9 Q) A1 I0 z: v( K
    47
    : d+ k1 H3 z2 b+ P7 i48
    3 z! g- {; x9 w* h& v# ]) Y49% f( G+ B  c1 m
    50
    % I$ a7 [* @1 f+ m/ o+ \( b, L51
    " u5 L1 F7 {8 i; X* V非递归实现$ r- M9 I( T% `- L1 V. `6 s* E7 [; F
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。6 t" s7 T: B( ~* K9 s
    + p. T- M. k# f+ p
    9 d, ?% G) _# A& B4 A* G$ r! M% P4 p
    1 }( P) i3 U& T* ]3 o& o
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    5 f, q! R( i9 A1 F7 F" h! t) @2 P0 R/ M/ ^( [3 J
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。5 T5 u! k( K7 W- j! [" j* S5 s
    4 j4 R4 V+ b! }( l/ ~/ {' j
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    . b, G8 ~, ^' c' S2 q/ U9 B! ?: A' t) p1 h
    代码实现; c) N9 H- c$ @: [$ z6 f
    7 w9 f7 Q6 N+ U. H; E# \
    void MergeSortNonR(int* arr, int sz)
    & P7 d( R0 N0 M4 i% i% E3 |% p- m{4 E, F. {' N  w2 I9 F7 F  d
        assert(arr);
    6 x* E0 a4 z! g! p* F
    $ @  J; {. t5 F* C' u3 C! D6 e; `    int* tmp = (int*)malloc(sz * sizeof(int));
    2 G0 P2 \& @" z    if (tmp == NULL)
    8 p# @# E/ {* d; C) l- q    {; r8 K. `$ _) K% e' b5 [
            perror("malloc fail");
    3 d2 \- e1 ^5 a% A- _% ]2 i0 T. \4 c        return;( x: K+ L; |, u/ ~6 X6 T
        }! [7 o" P: \1 _/ I& p, _
    7 M- E- K5 }5 J* s. r5 G
        int gap = 1;, o2 X% h1 o  M! x, }4 n: m& {
        while (gap < sz)
    . I( X/ |0 @/ ?; h8 T- V    {; b. q% X) A2 ?8 x6 A
            for (int i = 0; i < sz; i += 2 * gap)
    , r( b2 s& B4 ^        {: g( H+ D/ \3 G" z/ }6 z
                int begin1 = i, end1 = begin1 + gap - 1;
    % ?/ `* F( Y) Q9 ~* G! ~% d1 X            int begin2 = end1 + 1, end2 = begin2 + gap - 1;4 u. Q, K4 F9 v3 @3 D0 v" _
                int j = begin1;$ l8 B5 m$ g0 o6 z; A( b

    6 w: ~" D' w6 l  P" z6 O            //归并
    6 |! c0 V0 @) B6 |2 D, N            while (begin1 <= end1 && begin2 <= end2)
    / ^9 G; g1 v: {; ^1 O/ y# a            {
    4 a" K, A) G" Q% f4 Q# k5 l                if (arr[begin1] < arr[begin2])
    6 R9 P" q8 q* }! M9 O                    tmp[j++] = arr[begin1++];8 c; o" t' ^, J* o5 t* h6 S( D  K
                    else     " H! ?8 ^0 H; P6 [; ?9 S
                        tmp[j++] = arr[begin2++];, \; I0 k2 k3 i6 _
                }" k& E" g7 C# ?6 g7 H9 e0 a

    2 u/ I6 d) L* q( V            while (begin1 <= end1)# O- D( p4 z! P) N" o, n3 D! L
                    tmp[j++] = arr[begin1++];
    , l- a) Z$ d0 n4 O, z2 n) e7 k            while (begin2 <= end2)
    5 w9 a, ^* r& L' w3 m- a! z+ c                tmp[j++] = arr[begin2++];
    + K. }7 b1 ~: F9 A- f) s1 Y; x7 p* l, b
                //拷贝回原数组——归并哪部分就拷贝哪部分回去) D/ ?5 `5 H0 ?
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    7 n/ s- F: }, T( F" s        }, h' x# J+ `% M5 J  i, r
            gap *= 2;* L0 A: s8 K  {; ~2 E; G
        }
    , L5 k+ p+ }5 e) v& i. H! z4 V% z2 e$ _( k7 G, k$ X# [  @
    }  M: X1 x0 j/ o- ]9 f  O
    7 V& x; L' d, F) O
    1
    * I, t* w) P5 U7 }2
    6 J+ t: @2 @" @9 d6 ~3. [% E$ m- ?7 Y5 `& y/ r: ^( J' D
    4. r2 Y  y7 R# {' ]2 ~
    5
    ' V8 y5 r- N; G8 ^% r' @62 A5 A! _8 Y8 F2 A5 O/ J8 U
    77 Y5 j4 e5 R% J0 i
    86 L+ T6 J3 l7 z7 s1 E0 }
    9
    - ?  Z+ {% Z4 h1 S10
    1 A6 V* l+ t. X. u) W113 v* k% m) W4 k# `! Z* `
    12; D- e/ l# r; I
    13& Q  n) t% u# |( X
    149 M  _* ]9 W, W. X  x
    15
      w4 n: X( k6 A% ?, _' k16; o$ X8 m  \( G0 r
    17: t( O9 Q& ~. F) Y& k5 E
    18& t; R! v# Z5 m5 u7 ^
    19* i0 h0 x9 l: v# _1 V; T  M  N" Y
    20
    , \, ]4 ?8 o. D- x9 Q% W& e21
    , K9 U& o( o& }22
    / n/ M# g$ O* J0 X5 Z% c; [" w233 }2 R" x& i, t1 x2 Z2 f! z/ w
    24
    : B# A, h. F+ a. y: _7 J25; Z: N. X/ G$ N) B; t
    26
    5 j9 y' r9 t; r9 ?27
    % l& B9 T* M; D& N. |( e! r284 _3 S( w7 [7 ^* @9 ^
    29
    " R6 X; K9 u/ w, f! |+ r30
    * o  p- g; _( `) x4 f9 K# Z31
    9 n; M) V5 h+ z$ k& W) f4 S( f32+ X) m( X# t9 E  V& x* Q3 b& u
    330 o% y* p1 ^7 s. S2 T
    342 d  G) Y, ]; W/ x# @
    351 c% N2 Z/ I, v* |" R9 Y; H
    369 F' E9 G# j! L' d7 a
    37
    0 [, L7 N5 m, A, F/ e0 A9 A38
    6 C& t3 w0 a% }39
    8 `4 [! o2 X  s9 @/ x40! v0 b2 {% Q6 ~2 B  ]+ T0 L
    41
    + R/ V1 }5 y- w. ^边界问题
    . L9 ?9 S& g' q4 {4 V​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    ; e5 P% o) p* Q, Q- P
    ! w* ~6 k5 x3 r" a# {4 a  q8 X举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    3 c  y+ S- x. n9 B) |- G8 K8 y6 o' E2 `# ^* A# Q

    . ^4 C. \7 o$ K3 \' H- |+ M1 Q1 M: a" I6 W, y5 U/ P
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    6 A3 O6 h* J# X5 u
    3 O5 c" B, q3 w2 i第一组越界(即end1越界)" z/ e  L& S& ^  w5 ^
    " d$ u' K! c" c' q8 N) e" _; ?- Q
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    ; W# \- W" k  L
    ) R6 Q* c3 I) A: ?$ i( x) Q第二组全部越界(即begin2和end2越界)
    6 a  M: N+ x/ o2 i( m' V. v0 x3 c7 F  U  ?' {+ B$ ~- R) c4 [
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。; b8 c+ R" G* T4 i1 u9 a) @& Q/ t

    ) a) E& N# ?& Z" h第二组部分越界(即end2越界)# Q# E% K$ Q5 Y& T2 n
    ) ^2 C8 t1 X* w, @7 T. \. }
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    + u9 Q# Q8 u9 e, b% B, j
      J$ e+ f) B. O8 v) k# M​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    % K' D/ j  v9 w& ~0 l; E) w: m$ \$ ~# L- l& s
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。4 U  p. b8 h( X; n
    * Q( }/ G7 O/ R: j+ {
    ​ 拿两个数组试一下:
    , X2 w0 S1 r  n& r7 z* i% L
    ! h" g2 M+ s0 S3 C2 y, n" P; Q; g, _5 Z" Z

    2 o9 c( \1 ?$ `) {/ f/ Z, E9 Q) |3 K' ^2 p
    7 I# l, H3 Y! X5 n  W( u& z; {
    代码实现& u2 o6 Y2 _; |
    1 L2 r- U/ g4 J* O' r! }
    void MergeSortNonR(int* arr, int sz)
    - ?# r0 j% R+ {& c8 G; ^{
      x) d; ^: B3 O  O* B! F" b4 }    assert(arr);
    2 G* h. \, S: P6 b: w2 F0 [9 |
    5 q' h) H6 k& \. i$ @1 I& h5 w    int* tmp = (int*)malloc(sz * sizeof(int));1 v* ^7 @, T( m) h
        if (tmp == NULL)
      s, O7 x% g1 h! t    {
    ( `# ~1 d! H# {! o; \        perror("malloc fail");8 W! A' q- t. ~* ], O) n
            return;
    # T5 K2 u# ^6 X6 k) U    }
    ) O1 ?8 Q1 ~! ?7 Y8 e
    7 D  ^& N" T, h$ I* E% v; }    int gap = 1;, n: m# a! M/ U8 j' I  E
        while (gap < sz)
    , H1 r5 h' C1 d/ g6 a6 Y  ^    {
    & |5 q/ h6 J$ u8 c. g        for (int i = 0; i < sz; i += 2 * gap)
    $ s4 A5 {2 i8 F5 l1 V* m9 K        {
    ' g3 e/ I' i6 ?            int begin1 = i, end1 = begin1 + gap - 1;
    - |" ], D! q1 S- |( m$ @5 P+ t            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    8 `$ G' w7 @/ z5 R- a, f+ X# V# K            int j = begin1;" Q$ J& D/ l1 U& V7 x: {9 T4 I' x3 c, \
                            //越界检测
    * R* Q' `( t; P! O, I            if (begin2 >= sz && end2 >= sz)# u' W1 ]7 c1 [
                    break;: k/ U6 F# a5 T3 U5 R- C1 }
                if (end2 >= sz)& L1 y7 U! d! h' L( e
                    end2 = sz - 1;0 ~" ]( K/ F. K8 s
                //归并) [. P9 t! K2 A: k$ @. v& |
                while (begin1 <= end1 && begin2 <= end2)
    $ n- q  H$ j/ I* T3 e3 j4 n& ~  ~            {
      ]* |% o# _: d3 l  }4 }                if (arr[begin1] < arr[begin2])$ a5 V  d1 F  o  O  u- ~2 S* K
                        tmp[j++] = arr[begin1++];
    . {6 w1 M! p1 g5 g5 p: H# v5 Q                else     * P' r$ s: [& [  W5 K
                        tmp[j++] = arr[begin2++];
    % }- K$ @/ c7 [. g            }
    " Y) F8 ^% `$ o* x9 Y9 |. K5 I% w9 i8 R# |: [0 m
                while (begin1 <= end1)) Z! u6 n2 d6 K; W
                    tmp[j++] = arr[begin1++];9 j, u7 c- e+ c9 [+ P+ ~
                while (begin2 <= end2). Q7 x) V  x3 J" `# B9 z9 U
                    tmp[j++] = arr[begin2++];
    2 I' ~7 g5 _. N. h$ @. ~+ p) Z
    ! `  ]2 z( \- e' J            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    3 e( a( `5 q5 t' K! Q" W! H/ n' l            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));- j, G% A; H$ r& J
            }
    ' c* Q7 C, n; t        gap *= 2;7 C! X* ]4 \3 P
        }  w9 q6 M/ k$ W6 f& a8 L9 v( |

    # y$ Z+ p# j1 ?}
    - G# x; u+ n8 S! \: I7 g* ?1 H0 ^) n& ^  R% ~, e$ d
    1) n2 \. |# k5 q7 c* m0 J% F! `
    2
    - u; K1 |' M" o0 ^4 s! z& g3 n3: ]: \3 i# F: \# d  f; b* w+ f! j
    4
    8 T1 M/ Z# _- Z- g5
    ' I' x0 `. `: s# W. }, M0 L4 K6! i# w' g0 R1 r, s: o7 [
    7
    ; W3 j2 H: F! c# W1 K8
    . I9 w" N& h) i3 u/ F& X' T) a9- a+ L* m6 t" z
    10
      K8 j0 \5 _( t/ g; K' T4 g' w; P11
    : j* i& q. q5 q) A12' \" ]# c  A, k2 y4 [# a9 l
    13  X2 O( ?9 [& c: K
    14
    0 o1 u& D) Z& V2 d158 F; N; _2 t( E% Z* l2 O) c
    16
    . p& i/ Q  y( ?17! N6 G1 H6 f0 z& X
    18: L! \& c8 P" g7 _! g% A
    19
    : ?" v! H. ~0 V6 M& n; Y* B: W5 c20
    $ A5 e9 S/ x6 ^21* L9 r; c  }4 {" d3 I4 P
    221 |; S$ G* y! l2 J2 J. S* Y
    23
      n5 b7 Q" J1 P1 I. x$ r7 }. o2 W* h24
    , \# ^* A( w9 Y; ]. ^7 ^25
    4 N6 k2 C& ?5 G  c( X# W- h  }' a26
      H- p  M) e7 m) j$ e& |- E27
    6 v7 T  I# s5 M% Z) p: b28
    * S0 i; P$ W7 L; V. [29, {7 c" Z# Y( N; Q$ w2 p. {
    30- V2 R, x/ w0 u
    31+ S, l0 v  \  d& r0 X& E
    32
    # O* z0 J4 M4 u: H* P33
    * L  C% K7 B5 v' ~34
    4 |4 J3 n& B; o0 H9 j+ X* y3 R35
    & z4 E2 z/ n' I1 w/ m/ q6 p36
    - ]; }; m7 c! G* g# {3 X* a: w37
    3 w6 `& b+ k4 n3 d/ Q38' v5 P0 h' q4 K5 p. L" N
    39: m& \6 ~7 s/ s6 P
    40$ F9 b8 s( y: m  X9 ~
    419 S7 R5 j) d/ g
    42
    4 H; n% T- @+ s4 ]; b# B1 @! l& @43
    9 m& P$ I* }- ]44
    ' U9 X$ p, }: X% Z45
    * Q8 H5 ~  C2 O, _归并排序的特性总结:/ O& f3 `" F. B3 \
    : l3 \9 M) {; _8 A; \0 b
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。  C/ i; ?9 @" {
    时间复杂度:O(N*logN)! q. @$ B, b5 V( G- Z$ S
    空间复杂度:O(N)
    / t0 I- r* z1 o0 M4 J; _) y稳定性:稳定" X6 ?3 h4 n# w5 B

    3 ^' [6 w0 K# I; j  G————————————————/ J" H: ~  G/ j6 d' [
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。; t8 Z& k7 y6 @& r/ t* e
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    ) v9 V3 B/ y+ |+ j
      O( `) k/ ?& S+ O2 U, L" V' K2 r0 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, 2025-5-10 15:33 , Processed in 0.430961 second(s), 50 queries .

    回顶部