QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3336|回复: 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的排序算法】归并排序
    9 J+ O% x) h$ }$ g# h' l: r5 z8 I4 U8 K8 I9 L/ d* L% e+ j
    前言
    $ m# X2 J" l" W( p9 F) J: y* t本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。/ A( M# M& o4 J: ?

      D% ~4 W8 ^0 E! R& N6 r- h归并排序4 n- S  P3 m, j/ _; C, \
    基本思想$ ?6 l' Q( g. {& I' u* |
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
      i# n0 i3 {+ n$ S3 y1 r, l1 L+ k; b

    7 y5 e. s, _; e$ Z$ g( B& e9 v/ W8 Y, A2 U
    ​ 合并的思想其实和有道题目的思想如出一辙:8 ~9 C4 j# J' R% `& u
    * L: @: W: m1 t* H, J# e

    - U: b8 k& S& }6 `( h  m# M% m7 x/ j1 h& L( O8 A3 b
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    4 ]! i1 V- T0 H, U  \
    + v- F7 x( y; ~5 l$ ^[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]  k! A. `5 t$ a9 q  l, P
    ' C/ b) g+ m, ?' E! y' h
    int* merge(int* nums1, int m, int* nums2, int n)
    ; l" m, `; O! c! X( e7 B+ D3 |{1 U( v5 z: @* d6 f+ ?( Q0 m
            int* arr = (int*)malloc((m + n));  p% l: b4 G$ y
        if(arr == NULL), P0 O! f2 G% \1 A. W$ o, L; M1 X
        {
    0 E9 J, c0 g- J" {' w) H; P; ?        perror("malloc fail");" B5 k6 z% `: I. {9 A) w  G" g/ p
            return;
    ; x- L# l4 [0 B& F    }& E' T& @/ f; G5 d3 u2 {: P2 r
    - X4 m# H6 D( N2 i1 V2 g
        int p1 = 0;
    2 J' [) y; P5 O+ f# l7 B' @    int p2 = 0;
    0 q5 G$ n% S( x0 Z! s    int cnt = 0;# z" S3 ]( n7 x! [! N
        while(p1 < m && p2 < n)
    $ y, {  b" s% ^# U, @- E' J* f  a    {
    ' O0 {' [9 ]+ e) t0 [        if(nums1[p1] < nums2[p2])
    6 `* x) L' l" T/ R' y, J        {
    3 |; q4 L; V, ~( L            arr[cnt++] = nums1[p1++];/ r: S9 [) C6 u
            }
    ' ]. A9 x3 o: H/ D8 Q$ r        else
    1 K; k: R# n: m$ {+ w  y        {
    " _; ~" O* {! C            arr[cnt++] = nums2[p2++];
    / _! @- p% w/ ]2 [  K/ ^        }
    0 g- K: B: K; P; C$ E% \    }: y. \9 [. I/ d3 R; r' L
        while(p1 < m)( j: D# V- G, _
            arr[cnt++] = nums1[p1++];
    # l( l% E' v+ L! G+ t; F9 K5 h) H3 v3 @3 S# X$ a1 W
        while(p2 < n)) Y' }6 z) d6 a; S, j5 C
            arr[cnt++] = nums2[p2++];1 @' F6 m: [  v+ i0 W* J

    1 X. Z( [2 K( M% d7 f% i    return arr;
    & H; i; I0 K( t/ g& r* |}; G' `6 }1 W% \$ V( L

    6 z9 y) {, H6 C6 Y19 \, T) ?$ R* c. U; a3 l: W
    2! }$ `0 e9 m0 A& c1 `
    3
    ! k6 s& P- ]( A6 C4
    / q! i5 a, W& j0 \56 Y4 I- |* ?0 r: x: t& u  h
    6. H& p; |  e! x9 o: W7 W& {
    7
    7 y' _9 L8 ^( g( R0 u, R8
    ) R7 V9 U, M; R# o$ K& N' U* U3 S9
    8 W6 H" D3 J& B/ U3 w5 K; a10" V: \5 W; b% j. G6 J% b5 e  O1 `
    11
    % I9 \# d9 o; l) w- w+ ?12% g6 j( ?2 h- B2 t1 }9 P
    13
    ; c) v( z: [/ Z) _14' Z6 Z0 {! L( ]  t5 m
    15
    1 o) `) a/ K& r( u- ^) Q  I16
    * w$ Z8 P2 y$ e5 v& }  q3 F) L17
    - k# m3 G7 |) H2 M6 _0 i& F, |0 o18
    8 x2 y+ W0 n) P! s0 a19
    $ G7 ^0 s3 W5 ~7 e8 P20
    4 D" O# k/ W; k& X21. F3 q/ j1 \" `/ Q( D1 O7 z
    22
    7 n/ H- ^' b$ t7 w* U& P23; `* L2 E/ |& M8 u* g
    241 K3 o6 D4 q# c9 P) K8 C
    25
    3 u" ~3 P5 ?5 l6 u26
    ) [* Q+ c7 e7 P- ~27
    / n# o% C0 a# D28
    ) \- }8 k, M9 |0 [( R2 z29
    " d& F* {5 D+ D* e30
    ) f5 o! e) [6 i3 N% [0 h3 f5 F312 }4 `' G3 v$ L
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    3 [" ~% D  r! Z8 Z& x3 L& Q- _4 }/ ]8 K8 t. c) C
    递归实现
    5 @& b; x4 x" b+ L3 |​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    . i7 G6 e# N4 z; U( }& w0 c$ [; b  O4 W7 R& h/ u$ Y4 e2 O0 }
    , d1 F' ?+ C6 s( `+ P' K
    / b$ i7 l- D0 o) J
    + ]8 A7 i5 i9 e

    1 L8 E* Q# i9 \' X& x& C% Avoid _MergeSort(int* arr, int* tmp, int left, int right)
    7 S/ Z: R" c/ A% V% b: ]) n{8 o4 U0 J1 r  M' A
        assert(arr);& y! l) [" q, ?  {

    $ ^% _1 x2 D3 h2 y2 a2 F% F    if (left >= right)//递归结束条件不要漏了1 X0 P: H8 ~, Y
            return;
    . c! i; V% }/ i8 |) z: i8 w, ~
    " Q' v' I& r+ l/ f4 l7 ~. I    int mid = (right - left) / 2 + left;6 Z( O% ^, Y+ `1 B. I

    , A% Z9 q: j3 F    //划分左右子区间[left, mid]和[mid + 1, right]
    5 x1 s* E0 Z) @% w8 u    _MergeSort(arr, tmp, left, mid);& ?( J0 V- c2 ~! H' ]
        _MergeSort(arr, tmp, mid + 1, right);3 d4 Q8 O) ^2 {$ v1 v
    / d7 ]- H7 ~; ^- R) J7 K
        //归并
    6 U5 h" R* O' S    int begin1 = left, end1 = mid;+ o2 P) r6 m9 _% \5 E0 q7 P8 S
        int begin2 = mid + 1, end2 = right;
    # ?: p& Q1 q5 |  X0 h1 I    int i = left;, l. A8 p& b% d! g9 _& t! S
        while (begin1 <= end1 && begin2 <= end2)
    " J- A! I- F6 o& S2 N    {. h! ~! U2 T* w
            if (arr[begin1] < arr[begin2])
    - K5 j5 Z0 c# p            tmp[i++] = arr[begin1++];
    7 T7 }/ H0 j6 J- x/ H6 C        else
    4 E0 g# |( e* r& I) I& q            tmp[i++] = arr[begin2++];
    & b  a7 }/ w$ ~    }% _9 W- ]: e4 ]! N1 [: j2 N) i
    ( y. Y' `3 i9 u4 A2 A9 S
        while (begin1 <= end1)" Y# l. l, U3 ^: b( @
            tmp[i++] = arr[begin1++];# m7 Q0 K$ _0 }+ ]: k7 Y! g
        while (begin2 <= end2)
    9 x; e1 O- S6 P) N- A* B        tmp[i++] = arr[begin2++];9 [  S, a5 @8 H* Y$ D8 w/ M
           
    5 F9 D& Y* \# _3 t; r1 b# @    //拷贝回原数组——归并哪部分就拷贝哪部分回去0 W+ X  G% L0 U
        //而不是拷贝整个数组回去7 I) h1 E- Q9 s2 v( W9 Q
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));6 n0 j" N+ h6 n' M  V% J  h3 D
    }3 `9 a  A* E5 \! A. v" b  q) Z% ]

    8 M9 T' C( t) X) }9 H% n* c' ?void MergeSort(int* arr, int left, int right)
    : ?2 x+ W# _/ u( g{
    ! D0 ^. T" a5 a5 m' D" k, P    assert(arr);
    " D; U! {. s  P
    : T" r; J. ], [# w, X5 ?9 G    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));$ r  r! A' ~0 g0 I, {
        if (tmp == NULL)2 u. B7 }- B. Y
        {
    . S( ]- Z& g0 l$ m9 B        perror("malloc fail");4 f& H% `! e! t) x5 x" Q+ Q
            return;/ w' r$ w9 c2 e1 D4 v
        }/ f7 z& k1 O8 u: V8 {2 D
    . k* A& w% y, Z/ J
        _MergeSort(arr, tmp, left, right);1 ~' b4 f3 r/ l( U( O' t
    $ t5 Y2 N0 G4 H
        free(tmp);8 Q+ `1 C6 @% M; w# b4 L% u3 h. A8 m
        tmp = NULL;+ j7 G  p2 \2 ~
    }; z4 ?+ q) }7 O& m
    ; t0 W  N5 J. B& N
    1
    7 p) J7 e$ H9 ]  I6 ^* |7 K6 U3 B2* i: w* T+ p5 f" \- R8 {7 M
    37 \8 N- S7 h- J0 ]2 \
    41 [8 G0 L% \7 r1 N/ Q) q. H# M
    5( W% N: R1 y* _0 x* \: t" a7 j: K1 P
    6
    ' o+ h8 a1 a' @+ i, H7
    ' o% G3 |" i7 n0 \# Q' o8
    4 u2 V5 g6 R! ?: q, G+ O/ w5 l9
      b1 x$ k' v1 i9 E1 G6 i" V10
    ! |8 d) f9 r6 J( A! C11
    ) z& P# ~4 \! |1 u4 e/ D; C( e12* ~5 V9 p7 O/ }+ l7 a9 Q
    13  @, ~" O3 t: [) Z9 N4 U% ^
    14
    " @$ C0 \& k& N  t6 o15& r# n1 `: ]* }* S
    167 N2 ~: V3 s9 j7 U; w
    177 o& D$ w$ W  H9 ]+ O0 ?9 U- i* L
    18
      w$ g; B$ @) s% T! N+ P5 z6 v19
    1 q2 M: H3 k2 O20
    3 j" J; k6 B9 b$ `: r. @5 y21
    / e. m; u3 k% X6 }22
    ' g% Y0 F  J* E9 N. K23
    * t! o, }+ z4 N8 Q8 i246 L! w4 A# w( m% H. |6 C6 n+ \% f, R
    25) a3 @! R4 y* d, X! \
    26
    5 B3 m' p, _* E* Z2 A, E' V- r272 ]5 r4 t5 b. D; X
    28
    ; k; D1 C  |, w5 J7 l. y& J293 @0 n. i9 |5 |, U* M
    302 r7 i. t% d9 S
    31
    : y  Z, n" i" z' W322 \7 {5 p$ J7 H& ^) l7 e
    33
    $ m, K2 z0 X1 _6 Q3 y2 r343 C9 g2 X5 h' C  p1 k7 o) U$ N
    35
    . N# }; @. N6 v& N, s2 J36* V  O9 x/ k! W1 y2 r- {
    37
    ) J6 E9 J! O7 I8 e+ t% `: R* {38- \( D; \1 `1 }1 l% r: n2 x
    39
    4 P, c$ w. w# |, e1 `( [! a9 D40
    ; f7 s( R+ J( X0 Z6 Z  v413 i! v$ D! [) B) a7 L  E, m5 c9 N. b
    42  D: q( g/ ~8 r% D: I
    43
    * ?- g7 f9 C1 P& Z* g, s44
    - H- `+ w- R3 s$ v$ I% u45
    & @/ E1 v5 x2 j5 e, P% w, o46
    2 p" `- V# N4 A+ J4 i( {47
    $ M8 ]- ?  }& B# a48$ P/ A- U! R! p. w. ^% k! W
    49
    4 ~9 ~+ M# {3 \4 n50
    / @$ T4 N$ Z! `51
    : w8 S. m" R, k非递归实现
    " U+ ^2 c  r$ o5 ~) ~7 o) j​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    % Y( e- `+ u0 b2 I% o" c( R, m
    , ^& j8 w. Y+ R1 c6 Z/ f& v; I) p# i) G, }. y
    " X' X; t  j! L, X/ `4 e; ]
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。9 P1 @; M! @6 B6 D

    5 L+ T' [% I! Q* q" ^. [- d​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。1 r8 \% g( C) ^# R$ |4 E' |3 z
      ]8 `( ]% A& x1 v" S5 N' o5 X8 Z
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    ! b) L2 @% B% }3 ~6 `; K6 P2 C9 r9 h' k: V5 q
    代码实现' ]7 o' |+ K+ K# T1 Y( y
    9 W; I$ K0 f. a
    void MergeSortNonR(int* arr, int sz)
    . s7 v0 r, ?8 S{
    ' P# c7 `! @1 a" \    assert(arr);
    : B, K+ s) V; I" d2 {% I2 [" `1 w: D$ N( a3 Z  o
        int* tmp = (int*)malloc(sz * sizeof(int));' ]' W* x" s/ f
        if (tmp == NULL)" _2 @8 [$ C# ~! d/ r. c/ I
        {* c( ^9 {3 g* v  R
            perror("malloc fail");* ]6 U" ^8 R! G5 d. i4 o! `
            return;: `" u! e6 r2 d+ g0 A
        }
    / v: c. b& C' u$ R8 K
    # o7 N( I4 G# `( b6 Y    int gap = 1;
    + L: a% u( W: y, t) w9 _8 g5 F8 p    while (gap < sz)" w: \$ M* U. o3 C
        {
    ' i2 s- }" [. r% z- x  f* R        for (int i = 0; i < sz; i += 2 * gap), K0 V# _; ~' l- \+ n  ?$ I
            {
    7 j; c- R- P- F6 b4 H; F5 |4 o            int begin1 = i, end1 = begin1 + gap - 1;
    . y& ^/ _2 v- m, G9 r6 D( ~            int begin2 = end1 + 1, end2 = begin2 + gap - 1;8 B2 W& ^- \4 s# r  }
                int j = begin1;
    , ?9 f5 I1 l  t) e
    , _* `9 z0 L; ~8 O2 R- D, f            //归并
    5 y# n( d3 Q, q  z            while (begin1 <= end1 && begin2 <= end2)
    % ?8 O6 s3 I: [6 x9 Y, e            {
    - V, |# g: K  E) ^8 ?                if (arr[begin1] < arr[begin2])
    - F: l' d- a$ z. ]- u' R                    tmp[j++] = arr[begin1++];' M' R- U8 ]2 n2 l) y. B1 q7 x
                    else     & V$ L1 W) ?$ Q! ]3 c" m
                        tmp[j++] = arr[begin2++];( W3 K4 R1 p1 I: Y: q
                }
    7 X) v5 c) {. q! y& C: q
    9 I* C5 U8 q( N! I5 u            while (begin1 <= end1)& _! y/ F8 l2 }
                    tmp[j++] = arr[begin1++];; m7 B. G8 }7 u& H  Z) P9 \* K
                while (begin2 <= end2)6 z- N7 T2 C, C5 a0 u5 }5 q
                    tmp[j++] = arr[begin2++];
    1 r" y. W& G* U9 P2 G
    ' k, b% [/ ~* i* j            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    7 l, D8 E" Q9 z  x/ l            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    : {: q4 y; R! U6 g! R6 A" d  p        }4 V6 g4 c5 s" y4 V: e9 ^4 _
            gap *= 2;
    5 I2 R5 {) t* s0 q0 \% ]: i    }/ Y7 F4 i8 M0 ~: F, N

    " [% f* K" T4 K1 |}
    2 C7 x5 l" k8 X+ C& {/ V# X& C' f% w5 p' P7 h1 h2 _- _( O- y, m4 D1 ~
    13 |% ^0 v  z3 {* T, V2 ~. w* `' `$ Y
    2
    ! t! r2 X) k- W0 \3
    2 y, S3 b4 ^- j2 R& X+ \4
    + i+ |( f7 d6 h- `2 y5
    0 I2 ?% @7 u4 {! S+ m, |3 G7 x6
    $ T/ A+ b0 G2 ^8 X9 Z" z( f. a7! R/ s1 A6 A9 t6 b# D7 C  G5 u
    8* b) m5 D  W8 L/ @7 ~
    9
    : O, L2 j. [  k: t/ r8 Q0 I; v10% G8 Y9 o$ k- R5 d% v* u; |
    11! C2 q4 e4 n. H6 S
    12
    / i5 A0 L+ B4 H: x! V13, q4 E! N1 f, c. `% T; Z. ?
    14
    ( a$ [; }: g8 p+ E+ n2 ?15
    1 }" |1 J/ y% _6 \4 V* G! g16
    : L3 I- B. z) r- U5 f% M172 g! K1 l/ c. W( d( ~6 a
    187 u6 P2 [2 v& m) O0 v. A  L6 ?
    19
    ( O+ I4 g, b6 _+ Q20
    6 T% R7 z/ I, w/ i% }2 a3 G21
    % ]9 ]0 `- J9 a. A6 C5 ^22
    : V5 W0 r2 G3 n, s$ \4 e230 D' y/ |3 I0 ^: J# b9 P, G! P, \
    24
    0 d- F" \" h* l, V1 ^25
    + ?0 c  b. f% ?5 n26
    ) U+ j2 Q$ q% Y: g6 \! h! w276 ?# {( y( z, |: n# b: d; U0 Y% t
    28
    ) ]9 \' k  i+ P, B$ E29
    - P7 M# @( z  o% ~0 n! i30
    + k* B5 u3 G1 ?9 U31% w  N9 s% d" }8 u+ ?
    32) B; O+ G1 w% Q4 K. {1 x! F
    33
    ) W. ^  x, z6 x3 f: @$ l34
    % ]  e7 O* U& \2 |5 o4 d7 j35
    , B3 @3 R, j. J) p360 m& g6 o7 a) o, ^1 o
    37
    . c  K5 m' \- d. z4 z38  w* Z& d5 [" [$ F8 r
    39
    * D& O8 x6 @% [( C40
    9 N9 `( O$ o2 Z2 G" q41. D4 _7 O/ p# H, i" u. J
    边界问题( r. X! @+ H  `
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。5 l- Z$ r# ~2 J" L' M5 m' Y

    : h1 u7 l- i2 D3 q- y, ?  w举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:5 O) J6 w# Q0 j5 l
    ) l% z7 K" K: E7 R# Q* @

    : H. ^/ j9 k% K0 ^( @6 E9 l5 N1 }# G) h8 E
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    ! R; e# ?5 g/ V. p8 y
    , f- [) Z% U/ P2 c3 d) N/ i第一组越界(即end1越界)
    4 |  w( U7 }- Y  _7 ~6 T! g6 T; i+ B& o: ^( Q5 [7 X
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    - P% q6 c; K; J! q! o. W' l' X% U8 x# i+ ]6 y  M' F* F
    第二组全部越界(即begin2和end2越界)
    1 {- ]8 y1 D* [3 x7 z0 h0 G0 O7 R. \( j& M
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。0 Q/ @/ I) G, [( X, w
    2 B( e6 x' o; s* f0 v% @
    第二组部分越界(即end2越界)$ H' r% b- Y( v% U. z9 j

    2 @3 L$ k$ `' R" a8 E/ x  j6 C应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。( ?; {& \3 T* |- H/ y2 T9 t
    1 P/ o" [, X* ~5 _5 s. P
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:6 h+ |/ r5 O$ U0 m- \( H, S3 E; P

    - |& i, U6 ]: O5 i1 @) N7 o​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    ( B& v" n  b2 v  ~" O- l
    $ U& K/ D, }6 _4 h- Y, g; o0 c​ 拿两个数组试一下:# X! u( V: T$ x9 N+ h) [, r( s' Q
    8 d, H. L2 \: {7 K) ]8 {  o1 p; B
    ' H( c) O5 m! m* k# m3 a% g2 v$ c
    0 T- [: g# M9 K0 C. A

    , O. \6 n3 p# ]2 Z/ C  N8 l
    ; ^- x% \( W  n- H8 z; y/ X代码实现5 e# B# p3 g: a  ], R

    ! |3 C% c' r+ P# z+ Dvoid MergeSortNonR(int* arr, int sz)
    6 N3 z2 ~0 ?  _{
    / X% p, P- v6 f    assert(arr);0 V; M3 r! u6 h3 o- {

    2 ]% U' c8 D8 ~    int* tmp = (int*)malloc(sz * sizeof(int));* y/ M9 H" Q: z" M; t0 ~; u3 e
        if (tmp == NULL)
    7 w; _& L6 c. Q. c" N1 B; O# N    {$ _0 u7 |! q5 Y; l" f6 s6 B
            perror("malloc fail");* F/ o$ l: u: X& G3 J5 p
            return;
    : ^) r# D% g7 G    }
    " t, e' c0 y; J% I4 d: D3 ~+ ^9 j$ ~( t- o
        int gap = 1;) I9 f9 t" A+ e) d6 y; Q
        while (gap < sz)$ ^2 T( |/ ]) \# d
        {) @. _" a0 x% G
            for (int i = 0; i < sz; i += 2 * gap)
    6 O. S% ]+ W: ^9 e/ C        {4 W$ i1 [" `* z5 M8 a7 V8 P
                int begin1 = i, end1 = begin1 + gap - 1;
    + ~* Y$ @: P* F& {9 t6 X            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ; w8 f3 _& K+ d" H1 J: J& ]            int j = begin1;: ^: ?' m( y" B% [
                            //越界检测: u7 |9 U' J' }; e& B
                if (begin2 >= sz && end2 >= sz)0 Q( L4 _& b: i* ]# w$ K4 Q$ n
                    break;
    * V: G( f4 P' V( k$ j4 Z8 e# M# m            if (end2 >= sz)/ e) y& u5 d# E
                    end2 = sz - 1;
    : Q7 R8 Y- t& {6 @0 J, Z: [) n: J4 x5 K            //归并5 F) i7 }1 I$ b2 ?  _, l
                while (begin1 <= end1 && begin2 <= end2)
    : |5 s( I" ]/ e8 V* {( s8 P: ^            {
    ; L" E  a) S6 h! {& ?+ `5 u* f( D( E                if (arr[begin1] < arr[begin2])) t* X; g9 |5 m& |. I
                        tmp[j++] = arr[begin1++];
    : f9 [8 x2 W5 ^" n( e- o                else       ~" f7 n. J  Q! O
                        tmp[j++] = arr[begin2++];
    ) z& L# W: R5 v/ L            }0 \+ y" B3 q4 F, d1 n+ L4 i" V8 ?

    $ {8 @9 ^! w1 ~            while (begin1 <= end1)
    - z. g4 ]2 b: d3 }5 c  l, `                tmp[j++] = arr[begin1++];
    / J( K( |7 A' `) z            while (begin2 <= end2)
    ) k' [% X# j0 W0 U) t                tmp[j++] = arr[begin2++];
    ! ^/ v4 u9 ]4 Y) z9 e3 `6 t
    5 I5 P- v  s' ?2 ^" Q            //拷贝回原数组——归并哪部分就拷贝哪部分回去4 I# G/ r! ?& H& p* S9 v
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));# g7 {! C5 ~0 l7 r
            }2 j* ?% c6 j9 B3 y) @# l
            gap *= 2;
    0 E9 h8 S" L( j: p  |% _    }
    " t+ i; K7 m# J  m& C" a; W8 y, ]7 _3 R* Z: q9 G1 H# G8 m
    }
    % ^" q! d* P4 i) D; W6 B+ i9 |2 d% S9 K+ u  m9 B
    1
    : y, e' g1 p9 f: V2
    & k* {7 S/ r8 E# j% L3; M% ^1 E9 \: S9 j' h
    4
    9 y5 ]  C) ^; [: H# I55 ?" G, q( w/ x; K
    6
    " y. T  c$ @" r76 c4 M$ p7 `; J/ T! X6 i
    8
    * T% O+ U7 F/ L- C% W( y9) s& \& n- C; W, z0 Z1 \% o
    10' `# f3 X3 Q9 ^( ]: J6 ^: k
    114 g5 d/ s7 M; S5 q  ^! {4 N
    12
    1 ?1 o7 M4 G1 K) i0 g% r8 p133 ]& T8 B  s/ g! C
    149 Y5 J! z8 q0 L% F& s5 I4 F" f
    15/ X# ]5 \0 ^' i/ Z; }
    16
    6 K( `. M1 X# ?0 x* k17, d7 h* L: L7 \
    18. w9 g+ r* t' a% C7 B8 S
    19% v3 j6 a# J. x) g
    20
    , ~/ [( l2 C* }2 L8 e" N21
    ( t8 [5 p* I/ G6 A* t1 z22/ g& V7 N) S9 r/ e7 K; R
    23
    ) f5 ^* {% c$ J1 C" Y% ]. H247 `3 |$ F0 S2 _1 S& b* Y3 }
    25; k5 M9 r1 l, j+ K8 q, i: a+ `! c
    26+ e" F6 A* t" E# K& ~* C2 W; G! O
    27
    : h. J0 b$ ^5 a28" W$ I" U3 v7 {8 \- V
    29
    # U0 X- ~3 Q3 L) [' T) a" V30
    7 n$ x* w+ m3 W+ L  G3 v+ i  n31
    ( @8 c- D2 y! T( L- Q32
    5 g/ a% }& y7 s0 n" q33
    ; M" q! l6 J  H34
    , G' A& R0 N, P% ]35
    , d; I# c' o) \2 l36' y- X( y9 t  o) M& e
    379 q8 w- L0 Z: G" \
    38( H3 t& t7 @/ c" O) M+ s6 }+ q: X
    39
    8 a0 C; p" b3 z4 s9 s9 y402 m( E, o/ F+ y: C/ h9 O
    411 q, A9 K% N  W4 @! i$ Q4 j
    429 C1 t( G- _* V% g9 [
    43# g- k' Z- d7 K# o6 r0 I
    44. ?4 h$ |7 W5 M
    45
    + L6 q& ^- }) |* ^; y* q, p归并排序的特性总结:* r! ~+ Y& u) J& X2 y+ u2 r# g
    3 q# u  f$ c) d1 Q( J9 u% z5 F
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。. P3 o! Y1 m& ^: V1 y% T
    时间复杂度:O(N*logN)
    ( }" @/ |9 g+ j. q空间复杂度:O(N)2 p) L& t, A3 j! O6 Y- I# B: Q
    稳定性:稳定
    9 H, i3 m. o( t5 S5 ^
      z; E* O5 c9 _0 h1 I6 y6 V————————————————
    ' ]% l& X* }! j' z& G, [版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    : z+ y  P% i% J! N6 ^原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    2 A! N0 O5 |3 k$ W  T8 x+ t. U% k/ }* j/ |- r  Z! P

    ! o% y! q& g9 I" d7 g
    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 04:03 , Processed in 0.519019 second(s), 51 queries .

    回顶部