QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3335|回复: 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的排序算法】归并排序
      s  D+ K1 D, j* f
    . m4 H" e* M1 F前言- ]) V- r, C% n! W3 \- f
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。0 \' f! {; C* }7 O( _
    + ]1 `9 l  {8 L( P( i
    归并排序
    : {$ }6 u9 A+ k' v' h基本思想/ ~4 {( `0 I0 K$ ?4 X. F8 W% h
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。) @3 Y) }) m: y, x  |; r; X

    + q& N( V1 v: ~. E; `( N2 \1 T# A$ k6 b% z: k7 Q

    8 g1 ^, l% e" d) `! H# |​ 合并的思想其实和有道题目的思想如出一辙:, X1 `9 }# ~# L/ h
      {; q7 \' q  [( F
    7 {, E3 L5 _: g* z' l7 w

    ; H* p- |- \/ r$ E& U( R6 u3 P6 f​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    ! L- E7 u1 N1 b* P7 x0 S7 b' }, D* N& f' V
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]4 H0 p4 R) o- M  j$ |  U& t+ A: s

    , E  \4 |1 d6 \$ nint* merge(int* nums1, int m, int* nums2, int n)+ u: y5 x: l) T! N
    {" K! W* b4 j2 D
            int* arr = (int*)malloc((m + n));
    8 ?5 P; r  _; a$ o    if(arr == NULL)9 h7 Z/ L0 f* l" M
        {
    ! C2 z6 ^5 D; w2 ], @$ \7 z6 v        perror("malloc fail");# o2 j+ p5 H" F9 ^
            return;) J% b/ g  X0 q/ X9 ?8 b+ H
        }
    1 U! s* @& O' H5 K' P0 P8 r; v+ \, J; O1 w$ Y. J  f5 `
        int p1 = 0;; S9 u0 J, u3 r
        int p2 = 0;+ K" P# P8 T# L5 w. T
        int cnt = 0;
    1 [/ ]) R6 _+ r5 V! [9 I& W    while(p1 < m && p2 < n)
    ) p% s. M8 r. s2 ~! E4 R    {
    6 T8 U! P% v6 f# @' r/ m& q. N* f        if(nums1[p1] < nums2[p2])
    ' }- }- \2 S* F2 J$ y3 ?        {% A4 G" A7 S! s# i$ O0 g. I+ m
                arr[cnt++] = nums1[p1++];$ B" S" z0 z" z4 Q& y
            }
    5 Z, V% [0 e( Y+ |. ?        else
    0 M' s( V8 \+ ?- I9 B: z        {' [9 f! g# `9 k
                arr[cnt++] = nums2[p2++];
    2 T7 a2 r: B- V) n/ `$ m* \        }! W7 r3 [* U1 T' `: U
        }
    ( T/ z/ h5 ?# W, K7 Z    while(p1 < m)+ g% q' w* }2 k3 D. G9 X2 [
            arr[cnt++] = nums1[p1++];
    ' E3 K2 T$ F+ e3 L7 @& \
    $ d3 w; J: {4 i% P# Q6 }2 Z    while(p2 < n)+ c) S! |) O2 v4 L7 O
            arr[cnt++] = nums2[p2++];( Y8 `* @  L6 W/ ^1 s! W

    / p5 g( J) ]% n% i6 {3 y    return arr;- Z# j6 _2 n7 u% R8 _4 A6 Z* U3 j
    }
    " O: M+ a9 P7 |7 l2 D0 |- ~4 J+ ?* b9 I* I3 T
    18 B7 A/ v3 X. o7 m* S. h
    2; V1 |( c1 W- K; x8 E. K; ^( T
    39 E* W$ J; X, v, U& [
    4
    ! Q: Y6 z8 x  R! a# Z6 x8 I2 a5& _+ Y% F% A. ~  l! A0 V0 O
    60 h" O4 ]3 C& x8 _2 |) f0 {
    7
    $ u0 W9 J# L4 \8) X& y3 \% d! m( J1 X3 Y
    9" ~# |; U# c- R
    10
    & Z1 F% R4 {8 }* h112 O7 V! K8 O0 n
    12' @9 N1 i8 `6 _  Z# J/ |# B3 _$ H/ v
    13' ]' Y4 g( Z  C2 I' A; y
    14, V. J) Q1 f& q5 H! m7 A
    15; B2 `+ Z0 E& ]# O- ]3 p0 |! |( Z
    16
    6 v: ~$ `- g& D( `/ e# y( U" w$ M3 E17
    9 E/ t* v' G5 y" Q. l5 ]18
    5 [$ L7 m. N% W$ f3 I# b4 i1 z19# t! c6 U* B4 {  t
    209 B8 v/ T& t" x) C# D' M! ~
    21
    # ?4 c+ v+ Z/ i6 a7 C$ ~229 M9 x( O! H$ }+ x8 V1 A0 m
    23
    ; O2 B2 l# }- f; {24. e! L7 ~8 I7 R$ ^# q, ?( O
    257 z; u) P! k0 V7 h* L
    26
    . b: D) A* I7 ]; _27$ g2 L: L2 _8 T8 i; w% ?# p
    289 W* n- e; |+ n3 m! Q) D
    29; ~2 c) A2 P' b) v
    30* I' i1 y, b! S
    31
    7 o# q* W  M, `! Z; ?9 k/ Q3 K# @​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。" W; g+ A7 s3 O7 _, w5 A, K. l/ P# s# U
    ! T! Z: u. Y2 d& O0 B3 U4 z
    递归实现
    ) J, j' W" a% E% i' ^8 C; Z​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。( ]! ~. {+ s; ]. A" _8 U
    ! _4 A8 ?$ n) a* C' F2 {! A4 `
    3 v0 E) ~& p! }
      Y7 R0 h. S5 c4 }. a" \
    " R3 k$ e# E( U9 w4 G9 r

    1 R  @- n/ X2 e: s, V3 o' Yvoid _MergeSort(int* arr, int* tmp, int left, int right)3 q8 r0 m) k% i& M" N2 u, ]. G% i9 z
    {
    1 T& ?% ~9 _: `  l; Q: C4 H; r    assert(arr);7 N/ ^' q, u- L; l, x

    " R9 ^& J* Q! ^8 }7 V+ L" \( t% D    if (left >= right)//递归结束条件不要漏了
    6 }) i/ R# O- O6 k        return;
    ( g! M& t2 g( X6 X8 u" `* F3 \) h( _  Z3 K* j
        int mid = (right - left) / 2 + left;
    + ~0 O4 V* N8 d' o4 O  v  v
    $ P0 m2 q' p; Z. O! C    //划分左右子区间[left, mid]和[mid + 1, right]2 m$ H0 o  y# T) R" v
        _MergeSort(arr, tmp, left, mid);: f2 F& O1 }9 f* Q7 R2 y
        _MergeSort(arr, tmp, mid + 1, right);
    2 u: y8 f: v* n0 E( J
    $ l( f6 b2 ?! P1 @6 ^. k) j' Q- x    //归并
    : V( k2 N) D3 X. m    int begin1 = left, end1 = mid;) U5 ]) W/ V+ h/ x5 L  [" j: b
        int begin2 = mid + 1, end2 = right;
    4 W8 H( J, l8 ]; h0 @$ A5 m    int i = left;
    : A$ e. @$ E  i$ t8 K9 \    while (begin1 <= end1 && begin2 <= end2)* _! b- }& y( }: o" s6 |
        {/ j0 l+ F) Y" d3 D$ {4 W- U' X
            if (arr[begin1] < arr[begin2])6 `. u/ [7 b# @2 D! z
                tmp[i++] = arr[begin1++];
    1 Q0 T( t3 S7 E) z( U) t( D        else
    ' o; n6 U. E2 `8 _8 y/ p            tmp[i++] = arr[begin2++];8 U# m) W" L( C% [
        }
    2 \- y8 _5 p2 k3 n4 v0 @) h: S9 r5 Q: w
        while (begin1 <= end1)
    5 L8 z+ O7 Q" G& r) o8 U$ D/ W' k        tmp[i++] = arr[begin1++];6 c# E- `" `8 `' x7 ~% u6 J
        while (begin2 <= end2)
    ) c6 t8 f! w8 M) L  Z        tmp[i++] = arr[begin2++];/ T* d2 O. a/ Q6 _$ c/ A
            . I& k, w; s+ d3 |7 V
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    % C% @- A/ l/ O' S: Y3 r; W7 g    //而不是拷贝整个数组回去
    * Y, A! b( t/ A& R- j    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));/ i5 Y7 _$ }- V& @- F
    }
    6 m0 D) j& r! ?6 n/ k; u; v1 x
    7 |) U" i" f' s7 c2 x1 `8 f  ?void MergeSort(int* arr, int left, int right)
    $ U" F7 R- Y" C% @; Q! Z" h" h{) {# Z7 D4 R6 Y# d6 j( \/ O. `
        assert(arr);3 T8 _7 Z: n$ j; C2 {
    $ r" ]+ b3 a. G! u- ]
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));& ^; M8 v2 r1 T9 r# ?) k
        if (tmp == NULL)) p+ ~3 [" H! t( G4 P
        {  a, v$ J, n$ K2 L  T3 ~# \8 G2 {& A
            perror("malloc fail");
    4 ?% X2 q2 C6 w! b  n  v2 f        return;
    : c) H2 `4 m# I    }8 x1 y1 b! C$ y3 j: I6 Y! v
    ! J; V: A* X$ k# O5 {
        _MergeSort(arr, tmp, left, right);9 k: K$ u/ W: N9 x) {

    ! x2 u8 [7 X3 n    free(tmp);- Y  y5 ], g& z7 b# |
        tmp = NULL;9 e: s2 ?3 |- N
    }
    4 P& b& z) @* C% k; h$ \2 k! t9 J* t
    10 p: Z  f% A# d, X' Y- B, G
    2
    : C  o* j8 f, J/ k8 R' k" q3 x3
    ; _$ p$ L4 b3 m' I4
    " b- @: F( u( R! U( T- I' H9 S58 A' y3 }5 x/ p" c6 N3 F
    6
    / `5 {* t1 k3 I7 J! w7
    3 ?/ ~2 r' h, E, G4 R3 O8. O% \/ G8 E* }
    9/ i# J0 }4 N0 c2 `- Y
    10
    ! S1 K9 z, a" }& F  J11  q9 k% v& b2 @/ P* i. T
    12
    3 M5 X# \. J: J- p! w13- V$ m2 H( @8 B
    14
    0 f& \2 D4 |4 r% a6 d15
    0 {, c/ K& {+ s8 L: R16
    " O. [/ F) f9 c, n177 G& ~  T' |8 p4 M4 `3 V: _9 b
    18
    % o5 T1 H9 e) S2 |& e9 G19
    3 o! N: G8 |; ^; C4 ]207 ~# l+ K+ E7 ]3 B- R0 D
    21
    4 b7 @9 W# f1 Q, R. j8 E22$ Z8 M+ ?: A4 }% f
    23
    8 C! [) t4 G) _1 i& K) w24" Z$ X% F9 o) W
    25
    ) t5 k8 p+ k( u4 W0 {6 L* q26
    : [! f3 D( _2 O2 D5 _$ K' g# T& k4 f' G27
    1 e& a1 r) Y( W3 b$ L28( }/ E5 b* d* X5 x/ Z4 K
    29
    . g+ P! ^  ?2 b8 o- E0 E  Z308 e. A4 \8 m5 Q: k
    314 c- v6 S" r7 X' P7 ]9 I
    32
      v2 `. b* \% W# ^. `4 t1 j8 U33
    ' B& C6 j3 C% @/ Q: T346 [7 V& u) P+ E# C+ `4 z3 A9 M7 ]
    35
    6 y- `: L- L/ j' c% X: N  @36  O4 F; h1 G0 |6 F
    37
    8 _8 g0 S$ v1 f0 ~' J+ d8 M38' z0 D) ]; a; X# P8 T0 }- k3 W
    39
    , h3 U; N0 K# y  a40
    : e4 ]3 z2 n" e, R( u& ~) M41
    9 }9 u7 k( y& d" u! x42
    ! z- F+ V. i7 W$ u9 k43  }5 c3 {+ i+ ?: z( A" h
    44: z0 z9 D  k) s7 |
    45
    ) Y* @- Q/ ?; x! g. e" l463 ?  o  x7 X% n  |% Z$ D1 m
    47
    * b0 q% V! E# |4 k48* i- y% F0 a! x  O, y7 |
    49' o- h' j3 p! m) Q( F
    50
    6 G7 T; M8 o1 A$ ]51& p4 O7 `- L/ D: v, x
    非递归实现0 X& N% x; _1 ^  f
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    + Y8 _2 o6 v2 g$ s( N
    # {) f4 ?! ?( \& H$ _: x* p6 n5 X7 W4 F6 d
    % D/ N& F1 l; c' N9 D4 D
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    9 @, x# l% ^5 Q# S0 [
    0 Z7 H0 \, {' i​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。2 z- q& T+ Q3 e7 W9 k
    ' W2 r. U' A3 ~# r) V7 R4 I
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    2 i0 w5 @$ `% B5 T: p0 }& C1 B6 d+ s
    . Z1 `$ i9 `6 u# i2 ^5 K% x代码实现
      p3 a1 P4 s3 s7 {5 ~) ~; I8 w5 b! U& n, W- S$ h
    void MergeSortNonR(int* arr, int sz)+ R' p4 O4 r/ d% y/ n
    {
      ^' O0 H+ w2 R5 ~1 x, J4 Q2 k( i    assert(arr);8 B3 @" u7 {8 y+ I( E. u

    ' i# H* j$ X: o, L    int* tmp = (int*)malloc(sz * sizeof(int));/ K0 ^# ~; Q7 G1 D
        if (tmp == NULL)* a+ \) b3 ?0 M/ J
        {
    + [* J- \% N: e: [8 U" t        perror("malloc fail");
    3 X7 H' b; }, N2 R. n        return;: s3 v& @: c6 @: s, v# k/ a6 S1 {
        }- x; t* }% `9 \6 O& }3 c( Z
      [( _6 N1 U. h+ V3 G
        int gap = 1;8 F# y7 ?, N! @& N3 U
        while (gap < sz)9 {! o% r3 b5 k$ x. L% r
        {3 w& w4 @) R5 c; e2 O. m
            for (int i = 0; i < sz; i += 2 * gap)) U- J0 y; K% T! O; L% D9 S% {
            {
    " }4 u' G2 S1 K5 F8 B. l0 `5 ]1 J            int begin1 = i, end1 = begin1 + gap - 1;
    5 y0 m# Y( J/ A            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    * W$ p0 w  i2 e) U: \            int j = begin1;
    ' y: x$ P% N/ T! j# S& a8 g
    # c# f0 p6 i! S0 y6 t, _2 G1 A3 r            //归并7 d) ~: F( B: y- X# i' l
                while (begin1 <= end1 && begin2 <= end2)3 A: ?0 a, l  |; ?
                {
    ' d% H4 i- I6 Q                if (arr[begin1] < arr[begin2])6 E6 X/ H2 t. o9 m9 w
                        tmp[j++] = arr[begin1++];: P3 t* X3 j7 \4 X
                    else     
    3 D, X' x/ F* V$ M+ a  L7 [4 q) ]                    tmp[j++] = arr[begin2++];
    : r) F# x8 r9 S  o) Z. p$ U            }8 o7 P5 h% Q( H( U( G& r! c8 H8 ~
    ! z" [: b8 L/ i' Y: x
                while (begin1 <= end1). j1 ?9 c9 }* i, J
                    tmp[j++] = arr[begin1++];, j1 K6 Q3 j* h# k0 D  S
                while (begin2 <= end2)5 p1 M% O" W  v( d& t9 Y9 S! [3 c
                    tmp[j++] = arr[begin2++];
    % p2 c  w/ ?1 G0 J7 P$ i. `7 I' w+ v4 p' D
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ( v, V+ y6 L" `            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    " f. f$ L; ]( V        }
    7 p. K  |. c' ~2 l# x! o        gap *= 2;
    ) M$ C6 S  K4 T# p; K/ Y    }9 P- }$ X4 q- ~/ q% }6 F0 S% Z
    : W0 z5 j; j* u
    }
    + y6 K4 K" Q2 O: q) r
    7 x: \/ P1 ?- Y! B4 e) c13 A. G1 E$ C" N$ p$ {
    2* A$ r. a7 p& u7 K+ ?+ |
    30 S3 U. ]! r: `: C8 D1 q& `
    4
    ' C. h  T6 U/ w; p5
    + k0 Z: ^$ Q' a0 w7 ^! ]68 T$ K# q$ V: W. Z- }
    7
    ' T: |- L6 p# o% Z9 x8# |" r/ p" Q* D. @# |) h0 k' ]; |
    9* {2 H. j5 |. O' i$ w2 R% L3 y: m
    10+ T. H  o6 s: R
    11
    ' c4 n: a" `9 M, F% F12# Q; C3 Q7 ~$ _$ m3 Q
    13' a1 R/ A- V+ B5 H# S
    14
    8 D/ z8 t, o+ O: p4 G% `15
    7 G* w) L/ g' E1 n16' G' D, v0 U0 M
    17
    ( M$ j6 [" m2 i- C18. n, e% m8 i, x# Q# s+ d
    19. X/ ?' R) V6 ?* G' L, j7 d$ H' W
    20
    : }: O* o5 Y7 M21
    $ P; R' v" Z! |) z22
    8 r4 J3 |( |, D" ^23
    / x" a. M1 E; E, C24( q+ s. F' Y4 a! ]
    25' }( ^5 h) k+ r/ l
    26
    4 n1 }# j& d/ \27
    6 E' a1 c1 p1 _: C- i4 J; }8 l7 y) {28* X, {/ @" B0 N7 o# a9 k
    29
    ) ]" H' v" I" T; z% R304 r, D. a0 x$ p
    31  V4 V' [; R$ N- `
    323 [$ L( o/ u$ U; m
    33- E8 ?: S& G+ ]* ]4 L
    34, F5 {& o( K( e7 _' J- A
    35/ C. W0 L+ H" P4 f$ P' v" r3 g
    36% M4 i. [& G+ f" k; \- R
    37; D1 b2 l8 C# `9 l# t
    38
    ! |; D& @2 \7 n39
    3 U5 W/ Z5 {0 N9 r+ M& j7 J+ v8 G40( [% c6 v; j- p  ]3 d& W) N2 ]
    413 K1 L6 r; ^# [: x2 L% x1 E: Y1 U4 g
    边界问题
    6 N, z! Z. k  k) D# c​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。  ^& L" R! `0 t
    ! T9 f0 ^" C0 s/ O7 s$ p0 u2 _$ h# t3 w/ V
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    5 t  p7 J% w# _: v( f
    & A$ p# w! Q) d/ X" {6 A, ^/ Q: e( Z  b: ~6 d1 Q+ R" \2 S

    # K0 j& Z* x8 ?( m8 [由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    / E7 D  `9 x* V5 d% r. i/ C3 l8 O$ W) V! P. h4 d% b
    第一组越界(即end1越界)
    1 ~1 H1 F5 r3 Q( S% J( r
    4 p# H& t9 p# ]# C2 g3 H应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    % y1 [! P1 [9 j; T7 {9 s
    . P& m" D1 E" R' y2 n+ T5 r第二组全部越界(即begin2和end2越界)+ L9 A( I# B- V; E
    * Z  p! E4 C( R% I8 |
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。& s7 d, V6 @& |+ i/ s

    - D/ m( Z) I8 y9 ?# h5 E. U第二组部分越界(即end2越界)
    4 k) Z& [2 o7 E9 G6 L4 e6 P# R6 @  c, g
    : H0 ^  s3 w4 v0 ~7 i9 S3 k应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。. l4 Y' c& k& o

    1 t0 y/ e9 m! P0 f1 @- M% Q: u​ 其实第一种情况和第二种情况可以合并为一种情况,原因:2 ^1 W2 ]4 I- A% B0 C' g
    & C" S! X" A  x# t% }" _+ e
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    - U7 e0 e6 G4 R" p/ E+ r& S/ _: Q+ K! N0 \' S0 t
    ​ 拿两个数组试一下:. J0 R- p5 F: H7 _6 @( G3 E" b
    + G  Y# Z( L; ^: \( N& V
    6 u" W% I: J' v. h! F% F

    7 E& g8 v" E; i' [$ X( m: N9 |2 Y# g0 n4 M( R

    ! \* s& }' x& A" ]/ L  \代码实现
    4 s! `4 X% H- ^' @1 Z
    4 ]8 m1 G; r- _0 T- V' mvoid MergeSortNonR(int* arr, int sz): k1 d. K1 u& H
    {
    $ f# X' v4 ~& Q' u* F1 Q  P! O    assert(arr);
      X3 V( X7 Q9 R2 ?, P7 f
    - u0 s+ d: }* E2 _8 S    int* tmp = (int*)malloc(sz * sizeof(int));2 K0 v3 h. J. S4 i$ M" r. U
        if (tmp == NULL)+ J* V2 r- T  |2 m
        {/ Z3 I5 r7 w- F) U
            perror("malloc fail");
      j1 Y; D  Z* \" }8 S3 [5 @        return;
    1 Y% a- P( o. Y& Z    }
    ) E+ _* C& G! H) A( ], [
    & z/ _2 [, h9 i    int gap = 1;
    & ]9 p( ^" v4 e$ S4 \: I7 |4 N. J    while (gap < sz)+ k; S: @$ i; T5 I8 M$ b2 z
        {" x$ `# w8 f. A4 a# S2 z
            for (int i = 0; i < sz; i += 2 * gap)/ b+ P' u, @% M. K
            {
    & u# b' l; Y$ p* i! U( N            int begin1 = i, end1 = begin1 + gap - 1;
    ' P+ L$ j( ?, F: V8 [            int begin2 = end1 + 1, end2 = begin2 + gap - 1;$ r, I3 `' ~1 q5 ]" S+ D
                int j = begin1;
    - N3 d. E# w3 }1 M; z                        //越界检测3 ~4 f: o2 q* |
                if (begin2 >= sz && end2 >= sz)
    , u2 ?" k' |3 Q  C% G  e                break;: h1 e  y- F* z4 w  g/ _
                if (end2 >= sz)
    $ p5 P% A& g9 h) z9 g                end2 = sz - 1;
    + [' x6 i5 ~( `! |1 F6 Y% m7 D            //归并& z7 H1 X; X* c. x2 D
                while (begin1 <= end1 && begin2 <= end2)0 Q- T: \2 m! H7 |$ [
                {
    ; z: H6 l9 k( s7 c  F6 Y5 ?                if (arr[begin1] < arr[begin2])- \* [" d, S8 Q0 ?0 L: K4 u8 y" d
                        tmp[j++] = arr[begin1++];
    3 ?8 Q7 w& u& U3 ~                else     % F% h5 n6 w2 C) k4 f/ }
                        tmp[j++] = arr[begin2++];
    5 m  C/ z+ y/ m' j            }
    2 `6 D) p# ]/ X9 S1 L% b2 {8 L  p
    0 r7 }6 f1 L' i7 c+ v4 G, `% P# g            while (begin1 <= end1)
      V& L0 u1 g% W* [- c+ F6 O9 O! b                tmp[j++] = arr[begin1++];
    - j' y( E; W! F' L2 m: _            while (begin2 <= end2)8 [  l1 _! _/ I. v- L
                    tmp[j++] = arr[begin2++];" B% S* y2 T6 L0 K

    % d0 R0 J) n" W* O4 P- ~            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    + S* N3 d4 Z* g4 P: v# _            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));6 r. b/ h' b7 }% l1 J8 c
            }1 V7 I/ c' d4 T% W& t- l& Q' D- c
            gap *= 2;
    # @. C$ u% ^' A: G. W    }
    * X( S: [9 p! o; i* H3 d1 w( r+ }5 t, m, E7 |' R1 b; M9 o
    }( v6 T3 d6 a3 Z2 Z/ V

    2 z* e2 K2 O3 R9 d( `1& g* G8 J/ X4 Q( w8 d2 Q/ r# q
    2
    5 R+ ]4 i# S# Y; W% d* v3
    ( {: T/ W  K) o' C2 }7 D% i4
    1 n: o- {- g' W5% ]+ }4 I7 |4 U0 B, ]: J
    60 v) g$ v* l. ^  `& V
    7
    - Y, f+ U1 g) y4 V$ k8 a4 i8- s+ Q( c; l5 t6 r
    9" F6 R; K$ C0 Z- [5 ^* B8 N
    10( h  e3 a( H) M2 L0 e2 t( Y3 v8 R
    11
    9 e) |7 K8 |; B; {  U& y12; I  I) M& Q0 s) i/ X3 P
    13  e& _$ g' X, o, L, g& B! ?9 W
    147 o0 [. f0 v  z3 J1 x5 ^
    15
    ) n" Y4 P4 y, D7 E16- E: E3 _1 \) k; z! q
    17
    0 P) j4 e, X6 c) l4 _' a7 Y18
    / e  M. g2 B8 N4 ^' k5 T19
    ; B3 f7 l, T% S2 p& Z* Q- L5 @20
    7 N2 B: B8 l, A9 }217 e3 j' q$ ], N4 B3 O: S
    22' r3 t$ ?3 ]/ y9 A( V- B0 O
    23% D+ x3 @8 ?5 }
    24
    ' e7 r3 n7 J( R$ O0 ]25
    ; e5 F6 a; E% l9 O0 M5 t26
    8 F2 O% i: u' A' a27
    & f- }8 m! M& x, h! G28
    - I, c( r# U( W( Z/ X295 S7 p6 s7 w) o7 J
    30
    - R, R1 H( ^$ }( B8 ?; A) V31
    4 U# r; N' L  Y$ T, i5 A32; d* p2 w, o- {  a) u9 n' v
    33/ K3 y3 |' `, d  V% h
    34
      n! Y! S8 J( L) X& N. x; u35
    0 \$ Z" D2 G( J& M36
    7 ]- I8 H5 x- A! ~: d376 ~+ U. \- p5 o- j; Z" k
    38
    ! G) ?6 D9 j$ r* |3 V, b39
    # ~: o. @, m+ l) T& j. K! Y3 a40
    9 R( H) X% [* O9 g41# K5 h+ L2 z; B8 W! |/ Q: U& k
    429 P& |. u8 A3 _
    43; X- l5 T9 _! E/ ~
    44
    7 r" R& B8 d/ s' l9 l0 \& U2 P457 _% E+ @8 z* u0 d* C" Y: a
    归并排序的特性总结:: M# s9 s5 H6 o3 L! ^! s
    . m: }& X0 P6 D0 z. o
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    ! q$ z5 v( q5 m5 K. @, K  a时间复杂度:O(N*logN)
    9 O) M$ ?" s% X空间复杂度:O(N)
    6 s1 g5 X# ?. |稳定性:稳定$ J0 ?& h; l) _2 A8 p7 H- r
    # U! F+ F( w9 B: d3 R5 r
    ————————————————$ }7 c( n! c( ]  G+ G* j2 \
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    1 O6 k3 `  t% O7 T% C: |原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    & U* m" C9 d' C6 o  r* @4 n3 x  ^, Q: n1 n6 F

    . K* a2 A/ T/ p2 r! ?0 I. [0 y! x
    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-8-24 03:40 , Processed in 0.436429 second(s), 51 queries .

    回顶部