QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3271|回复: 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的排序算法】归并排序
    0 D4 m( ]% {: V5 R( q
    3 U" ]: e6 f$ T前言: J+ q  x0 ?$ \" M% ~
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。: v/ o+ Y( Q3 g7 A, n' G9 f) C3 z  n
    0 L% n% U! X3 M7 Z  K
    归并排序
    , o6 ~" x2 m/ M; P9 u6 o基本思想
    , k9 }% B1 ~# w​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。# E# s* A' A2 n

    " ~0 H( g$ j/ N  g! u7 \' X: R. E6 y1 g& @& |
    ( ]7 |3 `8 y! D% Y! a
    ​ 合并的思想其实和有道题目的思想如出一辙:4 v* j8 g2 k, ]; u, m+ I

    3 o5 X5 a: [( `3 u' J
    ' O, C% h- L. b3 E" y0 w3 X) X5 ]$ f) z3 m/ I' K- T( X
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。$ z( c6 D/ O  ^5 E' u$ I2 J

    4 a" ]( t9 u- T[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    2 b* @. F" j2 b, u
    ; I' k9 J. a+ l  S! [int* merge(int* nums1, int m, int* nums2, int n)
    + H3 _- C- F; d- A+ J{
    3 ~7 C2 f* T7 L# P& |5 Y" o5 d# b        int* arr = (int*)malloc((m + n));
    - D+ z2 s) Z3 x" N& @    if(arr == NULL)/ R, D- @. G. h! O* y+ k
        {
    - [. q3 d% q; u" A        perror("malloc fail");8 G/ U, N2 L2 B8 h8 Y: z
            return;
    2 ?- q7 I0 D/ t/ x" ~, C    }
    # m4 x+ }# C" K: _! j9 R9 F6 i! E. A( u) U5 b- T
        int p1 = 0;
    $ I* s% T' S0 \    int p2 = 0;: \" s2 g, \( P: R( G8 r
        int cnt = 0;& q$ R- a7 E# Z" I* L6 T/ m. {
        while(p1 < m && p2 < n)" B) M. c: r: n+ q( x! f
        {
    " O& e! D7 j/ ^' u8 D0 j        if(nums1[p1] < nums2[p2])
    8 \9 \2 X: `* G& g% @$ N: j3 Q7 u        {4 O" t- N; l8 H. ~5 @, P4 q) W
                arr[cnt++] = nums1[p1++];# E' E7 [( {+ P7 f* @" h
            }
    / o1 f! j/ x  e+ A/ }8 D6 S        else
    4 h, b- c! `+ T9 I" |/ X        {# H/ C  g, g9 L' K9 L7 U2 ^# i
                arr[cnt++] = nums2[p2++];; Z5 h/ o9 O0 v- }5 G
            }, ]9 R6 S  q" I7 [3 A8 |1 a. s
        }5 [6 L: Z3 Q( k% t5 w
        while(p1 < m)6 h0 C4 |( C- M5 Y; n+ d6 t
            arr[cnt++] = nums1[p1++];
    1 a% v$ f6 u' T' m' G7 a4 N0 k; ?6 b
        while(p2 < n)) ]: V3 v% [2 X( U9 ^# i0 K. D
            arr[cnt++] = nums2[p2++];
    1 h" a  s/ N) t* D# R/ J* ^' Q' d0 C6 M  k6 n/ l* D
        return arr;
    2 D6 e0 @3 d6 z/ ]# X" v7 z}" l  T" j: F1 i- J; J

    & t/ b1 S5 R" n% e, b1
    . t, K" r& ~# f* X4 {. J4 T1 u) q. p/ p2
    7 x' ]( Y" P& s4 @# _. z6 S& n3$ t, B8 G, o) e+ ~8 G
    4
    0 r4 z2 P" \' z% F5
    $ s* @, z. _! p/ @' k6 W4 l6
    % U9 _" p8 S1 q$ b# c3 i4 Z: e; `1 N79 ]: @) r2 ?1 o/ F% ?- h
    8# Z6 h. z) d9 V' G  M5 S
    9
    ) P2 V3 k3 p6 o" o( o10
    8 V: P1 N7 M+ d% P0 H11
    ) V' v+ N# O& ~, D! B; w) ?& b12$ @5 t7 H; W6 b) Y( f
    131 {( s( Z8 k  t" h
    14
    - ]  o  T1 m( V5 ?15
    7 e# y* L8 u9 ~16# a+ x) |, b! }: a% l( U* ^
    17
    1 [. N/ `- q0 ]8 u! E/ v18  f6 V5 B, {& A1 l5 l, Q
    19  f, n' K6 \; }! s  h
    20
    3 Z  o& k, M+ j; E7 V8 ]% }21
    ; |: H" p. |" A. R8 S4 d22- o8 M; d' r' d& T( q) L
    23
    : R+ @  _- m; O" Y  t24
    9 z- c8 n$ Q% U/ }& i9 |25
    " e4 f. _* f: g% t. P267 Q$ q0 S" |, Y, w
    27
    , \( ~( x' I- `( w28
    6 N) Z% A8 i- E: `292 t) w$ M. R& ^! n5 h3 q
    30
    - p1 v$ [$ s0 i' ^; n& q! o& ~31
    # F! r- f/ L2 t$ i$ i. o3 b​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。, A+ e" D% ]7 U

    ( i! W9 J- _4 }7 G1 U4 z8 a递归实现
    & o) F) B6 a! ^( A- \- l! X3 @​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    ! @' f8 M+ ~* e3 J' `
    , o. A* R! |# F! |1 ~' d2 U1 {5 l+ U; C+ I
    % O5 Z# [8 \* s& Z3 [

    4 e8 [" q. c& Q, m: @8 _2 _8 L4 k* e: F% z4 w
    void _MergeSort(int* arr, int* tmp, int left, int right)' L5 U. r$ A, f. k8 j
    {
    7 X( i1 P4 R' ~& Z    assert(arr);  p7 u. Q7 U7 B2 `+ }

    % o. {4 c" z6 l    if (left >= right)//递归结束条件不要漏了
    : |4 `2 I. \% H/ G' {. X: G        return;
    0 V. b4 n. t1 D# c* ~/ H% q! f. t
    " P6 g4 t1 V1 W( \& X; d: F    int mid = (right - left) / 2 + left;
    6 d" w! i) N' K% c" W" b3 v% C/ e7 Z) Q- J5 l
        //划分左右子区间[left, mid]和[mid + 1, right]
    $ P1 O" e7 ~6 x8 A9 V* L. L2 Y    _MergeSort(arr, tmp, left, mid);( L2 W% y7 O8 d3 {
        _MergeSort(arr, tmp, mid + 1, right);1 @' `* B1 K/ G5 J& K& @8 G2 }, I
    - I$ j7 y' }' N( c) J6 W
        //归并$ S( p* b1 L* C7 p& Q; H
        int begin1 = left, end1 = mid;
    " p  e- e4 z4 K/ Q    int begin2 = mid + 1, end2 = right;
    7 g% \- d+ k2 n    int i = left;
    ! G2 S! u( ^7 W* I$ K! {" O6 n9 ^! ^    while (begin1 <= end1 && begin2 <= end2)! _5 R) Z! ]0 U7 d
        {- g3 U7 n/ J- d# X# C; p
            if (arr[begin1] < arr[begin2])* H0 S1 Y. _, M
                tmp[i++] = arr[begin1++];7 S! Y, a  L- l: w( e
            else9 m7 Y* r$ u. V5 t4 |
                tmp[i++] = arr[begin2++];. X- ~' j6 g. {
        }) H6 `/ Z* R( N7 B' u* R9 @+ I

    $ z: i- o' F& A* v9 d    while (begin1 <= end1)+ L! u% s' C: \3 v& M
            tmp[i++] = arr[begin1++];. i: ~8 Q; ~" ?, X& b0 Y
        while (begin2 <= end2)
    $ K( @8 ^6 V8 g( E7 o1 k* _        tmp[i++] = arr[begin2++];, |1 J  u# Z, X; p
           
    : r4 K& D: U) ]" s    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    & [! F& ^4 l9 y9 |    //而不是拷贝整个数组回去
    $ a1 S* X0 M+ O( l; D- C( [    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    ' w% T" M/ G* P8 i  k}2 g, J# c# U  G( h) x6 [: Y

    " t* N9 e! C% p* F0 pvoid MergeSort(int* arr, int left, int right)4 z6 n" e; T! r- U8 C+ _/ ~% D
    {
    , _1 A- v2 C; C' R# R1 p' p7 S' e    assert(arr);: Z  E6 b( Y7 J6 }/ s
      p. e# y8 b; ?7 o# l
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    , d' v, j1 F; Z+ H9 a3 k, `    if (tmp == NULL). n: M1 a$ T# f  I2 t' q- U
        {, [+ E6 V4 u! l4 n9 ?1 e) H9 t# J
            perror("malloc fail");2 f+ i: X9 y8 X- `! M
            return;
    3 H- l0 F( H# R: J. j/ r    }8 R& r5 W; Y# i, ~6 B; S

    : ?5 a7 v# F" j% T) S    _MergeSort(arr, tmp, left, right);1 n4 f0 S+ c' g! T% V

    ! @: o: M) `. f    free(tmp);% x! j0 ~' W% u9 M, ~
        tmp = NULL;$ }' ?# |3 {, t; W  O2 Y
    }- s. a  \4 n' a0 r' y% ?
    7 P3 z6 j' C5 B6 \4 y# k, p
    1# {& s( J8 O, f3 _( c  T: R
    2( d4 f" L$ }+ h0 K
    3
    % Q7 j0 C; I" ^( f- ?' ]4
    + Q9 D& ~. v! E+ f5
    - h- ?7 K; |! G) D( E) C6- D% @. t) T3 L! H2 p6 K
    73 G+ Z) z% l) O! f
    8! H9 }. o- D! z. o5 V8 _4 \/ }1 j
    92 C& w& |+ H8 y  m
    10% Y( L" ]. `& I, ?* |
    11! P/ t( O, @# ?
    12+ C1 `' Z, J* o% l- F2 X
    13
    . G& b7 q+ B* j9 F3 e  `; F14& w, y* E0 o, B* N$ J* L9 f0 u6 p; H
    159 W3 c3 A' |' k: _& _) \  U
    16
    4 ]  y' D9 [; t. w173 i$ @, n' F! z4 Y
    18
    ) D/ r9 m5 E' ?9 t5 z  t) e0 q6 \8 Y19% C# F* D  V0 O6 K0 r. m) O/ d
    202 i7 u) s1 w# @, X! \$ X
    21* K  o+ ~3 K! p8 ^. O- J# Z* d" `
    22) y7 k- N- m) P, x6 N: A
    23
    % H# t7 h0 s* e4 U24
    6 [+ }4 S, K; U  Q25
    6 G. [$ D2 t3 I9 ~  C: @: {/ d26, _, l. |5 K- U$ T4 r; e9 e
    27
      A2 n6 r* c1 f28
    9 ~# ]) A, n  a9 V( b292 O9 a7 d: A/ @6 n, a' B
    30: J3 d" Z# [1 ^1 @" p. ^1 A% ^5 e
    31
    & ]$ B4 s- Q8 M0 m32( f$ e! \( e3 A
    331 M) I) B% j5 e, S- ], s
    34
    $ v6 z$ V. e9 j5 k' k. `, ]* v35; g" |7 A8 y0 I3 I) S: E* g
    36
    8 E& y' o6 X& U& E! z2 r37; C6 T+ W* _1 {4 H9 P. @$ E# d% t
    387 ]+ ]5 v# g$ x
    39* J9 \7 {9 B( |" e; g
    40- g9 y; L: L/ Q( Q' K5 T
    41
    8 B* I$ j9 {" v- u# h9 p42
    " ]& y5 ?  T: O, a43: W/ A9 p' X6 [  T  `; G
    449 P, {0 E9 C. B
    45
    , C7 ^9 t* n5 A" @46
    + P( ?; b) a+ X) P8 o9 X47
    2 T. n: u; \& D48
    5 ^5 I* H9 [, Q+ E/ v# p. t& o, a49
    ' ]) p. Y# P; Q: k7 M50
    ; D7 j( ?4 r2 O% R& f! w51
    5 ^6 [: u5 B: L- o0 H  {) f非递归实现
    " b, [' d2 S/ ?0 e/ x. k​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    # S  @0 l) {2 f. B3 V9 R$ W" H$ @& k" ]- g2 \

    9 v6 ]6 k% R9 T0 j; V
    : V& i! H4 J2 |- }0 Q7 |# k0 {& J+ f( S​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    * {9 K9 R8 T, {
    3 E& d* P* o+ {4 N0 }* }​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。8 e! g9 q2 [: T$ ^

    , d6 u2 c" @6 m% k1 h6 O' L​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。1 |6 L0 k0 v1 ?0 f& ?  b; |

    4 A1 w3 {9 s* W" G. d9 j4 m8 S代码实现+ _* F+ P1 y3 P; u. ]( v5 k
      G) m' S; Y; I1 J
    void MergeSortNonR(int* arr, int sz)/ {4 p9 D& N: U* s8 _5 O6 J
    {
    3 z$ p# t+ [4 @& o4 x; j/ K& E3 u    assert(arr);1 x& z$ z0 [: R( V

    * |5 Z" N9 o& r$ o$ R- X: c3 S" U    int* tmp = (int*)malloc(sz * sizeof(int));
    ; U- u. R9 l3 D  J* v: \+ P7 _2 y    if (tmp == NULL)
    ) k2 D( K: Z' }    {
    5 ]! [, @! ?! n/ K4 d- O        perror("malloc fail");  O2 [: ^6 g0 @. d, q' q$ o
            return;9 \+ |9 n8 w7 K
        }
    , g: t/ f/ Z5 v# r2 ?8 ^( Z5 S! o: O( f; C: @1 m
        int gap = 1;
    / w8 x/ \/ Q* ?' H! w- ?    while (gap < sz)& `0 P8 E7 w- {, N; f) ]4 g. n1 o
        {
    . s3 @6 x# l2 `! X        for (int i = 0; i < sz; i += 2 * gap). j8 `( F( J6 L* f& l
            {2 T( k$ \0 @( `
                int begin1 = i, end1 = begin1 + gap - 1;0 x7 \% @* Y" d8 o9 W, _) F
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    % v8 Z- ^& _0 ?# `% F            int j = begin1;
    $ V1 R" H) P' M* Z
    0 j& G8 I6 a5 |: t- A$ [9 v            //归并
    ) E' F" `8 W6 B7 V            while (begin1 <= end1 && begin2 <= end2)  {1 ~$ l5 I; `; N$ H% h; R2 m
                {# G* w8 K* r& z) ]! `% H
                    if (arr[begin1] < arr[begin2])7 G4 M  t5 k/ |9 o' |/ {6 z
                        tmp[j++] = arr[begin1++];2 n$ n* {' Y1 {) `- I* O
                    else     8 o# K3 n$ N; M$ [& E$ P# u
                        tmp[j++] = arr[begin2++];
    ! y, i9 ~, t" L, D            }8 h5 s$ I  J$ O  D+ |' o" \1 v& y

    + U: S8 p' c4 s6 X  `( F            while (begin1 <= end1)
    $ w9 e( A( g% T                tmp[j++] = arr[begin1++];; D5 F/ ?+ O- a+ R- J
                while (begin2 <= end2)
    ) P" n& ]* @" ?) Y. l, k7 `% K; I% [                tmp[j++] = arr[begin2++];' n/ m, m7 B$ V5 @# Q
    ' M# F, A* ?) t) j4 n; j
                //拷贝回原数组——归并哪部分就拷贝哪部分回去. i2 V  _2 t7 W0 m$ H5 w5 L. w5 A
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));3 ?0 A  U7 y5 C, `+ \  N4 O3 `
            }
    - \, |( t( P% Q& C        gap *= 2;" Q) L/ M; U' G% ~$ {4 @
        }
    ' w# s' N) Y" L2 C* G" h6 Y8 T; i8 I& e  O
    }+ O5 p2 {! ]! ^9 {) _  l5 \

    ' ~" C0 V* ]3 |  M& K1
    ' X8 P8 j& J  t2
    4 ]0 K  R1 Y0 |, D3; q% y' s" r4 A( m) w
    4: H2 k  d" W; O. j' D6 U
    57 E" W, f. X, n
    6
    & Y1 N7 {5 n2 N6 N* M# G! L79 z4 c6 H* d$ G4 C3 T8 V5 v
    8
    / u. x8 H, t3 {9
    ' P5 R" T6 o& d# z( A10
    ( ?$ H6 K5 N0 e; w# [/ C11
    " x; y5 A6 S9 G12
      n7 ]0 C3 y4 n( f6 c. h  X13
      ?* V; G' G9 f3 @  S14
    + J. Q, K& R8 X, c: y0 I- y+ o15
    & p6 s" |# b3 K" V! R3 m0 r4 Y* V" S% m* D16$ R* f" F: Z2 Y: X7 D
    17! K( R0 t1 ~( m& e8 {* U
    18
    1 O/ m, Z' ~( w5 b19! b  r3 u/ ^" v$ {5 M+ j
    200 z. ?* n. D# w: V4 G
    218 s  }7 ~/ O5 B& F0 d+ P! a
    221 }( b( X3 {3 ^) p: k2 o& k
    238 v+ m' K# _" W+ Y
    24
    * f& O1 i) }9 ~& Q9 E25. U: \# W7 d, ]0 Z$ m
    26
    8 m1 G& y: [1 X4 K5 J274 {; m0 q: x5 D: H% K( P9 p
    28
    2 a+ }. p* G4 t6 U0 u29
    % @9 T/ r! A6 |' u301 N1 N8 j6 \; O0 W! ]9 a) H; v0 ^. i
    31
    6 U$ w8 G6 p- O2 ?& B/ \32
    $ y% Z! r. }+ I4 J33+ K& p+ I" V/ z3 S1 L- r% X' g% x" u
    34
    ' g& l* D. Y& P" D9 M$ J5 O( J1 x353 n( S% L; B! c& {2 |( V/ X
    360 {7 L7 A2 X- d2 O& t' z  n
    37
    5 e; [2 k! I& C% S  k; }+ v9 \38: y* Y6 p0 d/ Q* A, `: H
    39  \: q: \. V" Z
    40/ C$ C/ |' E# ?% c. ?' L! M0 a) V
    41& w  z0 z; J5 f! w7 p' V' R
    边界问题4 `0 w: }2 P) S9 _
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    & z( c1 j4 a" _6 [: n1 Z
    0 I9 }. B- w1 S7 Y) Q' m9 N举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:/ \7 u% @* n8 n! o& W4 X# f! k

    0 Q, L$ [  g7 W$ ?
    " X; j4 l4 ~! [- @3 b& j0 v$ |/ t/ L; ]" _
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    & P5 B( r) y' e' ~+ ?9 f
    2 {: Z3 ?9 T/ J: [0 f, ^* W! y第一组越界(即end1越界)$ E1 Z9 q# H! r1 f% \8 d2 d0 p
    ' G. z. p0 m: n4 W' N. j
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。0 R) P+ V. j' P/ A( o& @

    9 b/ i. s- h/ i: L8 R( o第二组全部越界(即begin2和end2越界)
    & e5 F+ q' Y* f4 b: o/ C* {* e- m  ~0 R9 f2 Q' }0 T: `
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。, j% F* b" q7 q; Y2 m
      Q' ?. s" P, ?" h  r9 N6 K
    第二组部分越界(即end2越界)
    2 R  z  T1 f' k# f+ h/ Y& Q1 F% ~& l0 p: w6 R8 a3 Y# v5 H  k) f
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    5 K$ S, B& M3 b. Z
    4 ]) R" `) [, C2 P7 Q  H' h4 P​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    4 A. R" p' n, y2 G/ u
    / d6 z9 o9 a' G$ _" e7 t4 U​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。& Q% L$ t7 x, J8 _9 q

    , U8 Q6 y/ o9 x4 I9 x- Q' }: d​ 拿两个数组试一下:) d& u4 t6 J7 P5 n& v  v+ Q

    & `" a8 ]$ S) h/ n2 H" I. x9 a
    8 d+ P0 D$ N4 ?- M  c: D+ Y' Z$ h6 C  U  ?- @3 [: L
    ! j. |' M# v/ B! T' F

    6 T' P0 I: ?5 t- n2 O8 \代码实现1 v* m4 K* `3 T" n* \3 h( o
    3 J  k( O# u6 c' C/ k
    void MergeSortNonR(int* arr, int sz)( m9 A% u' F4 e7 t& ^6 e0 }
    {
    1 e* L* O1 F- Z# W- D( z    assert(arr);
    # T5 w4 w# p( J# j  V4 a7 u' `
    5 I* \1 _( Z  a5 p7 T1 g' x) {6 y# N    int* tmp = (int*)malloc(sz * sizeof(int));
    : c1 Z# F, f) Z. k: G    if (tmp == NULL)
    + e+ m5 |9 v* t% y    {
    4 U) K7 C+ [. f9 u  c# `7 h        perror("malloc fail");4 C1 w* H7 y- I# y* F+ ^; Y3 n% {" T
            return;
    # D3 `9 q1 X+ `6 q' e% B+ }    }6 v. j0 Q/ @9 X2 ]/ J5 L7 h
    5 i3 y9 h0 R9 p) T- i
        int gap = 1;
    9 v. S& Y$ W+ W7 F8 I( P& E    while (gap < sz)- _% o% H* }" q/ z- X
        {* ~+ P% |' z' B* P* [1 j9 T& m
            for (int i = 0; i < sz; i += 2 * gap)
    ; F0 e9 _* V$ ]' i        {* N# ?6 B' ^7 N. y3 q5 ^
                int begin1 = i, end1 = begin1 + gap - 1;
    1 e; c" r  ?% a$ h- U8 ]3 N+ Q            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    4 b" f; m4 e$ x$ ~            int j = begin1;
    ( n2 G) @% A( m. w$ X                        //越界检测6 X2 n0 s! D. ]) n: c( b$ Q
                if (begin2 >= sz && end2 >= sz)
    # ]7 W  _( B- \. z+ n; P3 P5 I) D" w                break;" K2 w3 c3 t7 I
                if (end2 >= sz)! ^0 e& I$ F0 U) [. |& s/ c
                    end2 = sz - 1;1 [, c6 C/ ?' B1 ~( I& M, H0 ~
                //归并* p/ v1 K) l6 ]6 [0 d" ~, h
                while (begin1 <= end1 && begin2 <= end2)
    + L/ m; [! W7 o            {
    $ c- i' j: ]9 j4 t8 V0 B( e                if (arr[begin1] < arr[begin2])) R4 j+ Q6 b; Y$ X$ }% z: l1 p( s
                        tmp[j++] = arr[begin1++];
    6 h. M: n! t3 M& H5 g" p1 p                else     
    - q; a3 P, m9 p                    tmp[j++] = arr[begin2++];/ z- V  B/ {4 @: ^9 Z$ t( W
                }
    8 s) E7 [6 N" O9 x) l# M6 {) O. D* j' h& Z( l/ g' G2 F! c
                while (begin1 <= end1)
    & t$ `5 ~! O* {+ ^; X                tmp[j++] = arr[begin1++];9 `1 j+ r2 d0 N6 z2 \
                while (begin2 <= end2)% ]0 y% B+ W) L& }1 [
                    tmp[j++] = arr[begin2++];5 {- U4 A  ~" b$ ?0 X; b  G

    , n0 T2 [3 e& i3 }1 G) L            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    ) N1 d2 P6 i5 A            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    ' Q0 s1 ]5 V) l3 S! d& I5 B        }
    " Z# x( g; w$ u        gap *= 2;& H. e- A/ h0 e! |: S) H
        }( `9 q9 S+ Z2 h$ A

    , F; E  p: }. o( `) }+ K& o& K" ?}0 o* ]) \; w$ \8 Q6 u) s8 n
    6 ?9 t5 a8 x& I( z3 R
    13 w1 W3 t" n5 d
    2
    4 D/ e* w4 I& O; \  E* j7 L' ?3" c$ P8 P3 O$ l
    4
    1 {$ \% m! z, u2 x51 p' R3 @# W, P# R/ ]0 P; h
    6* O% [: G4 l: v1 i- p0 @
    7& Y* o4 e4 \0 o6 S9 N$ H8 ^
    8
    ; Q  \) K0 |$ j8 O3 Y  g92 c7 B5 t" W& C& i% J$ I
    10
    $ Y% C! X& Q9 \7 B( |* c* L3 Q11: b8 n- v7 H* d) g1 i
    12
    ; i, |+ P+ ?; P5 V' N3 N% b136 _  y+ G) ~) q/ C7 ~5 z
    145 b2 \  K, G& ^+ r
    15
    : {! c) J9 i3 K7 e6 M: j16+ Y0 j. n) q  W7 p0 B3 I9 r
    17
    8 F6 J2 P3 j. j! Y, _18
    2 k+ H& A8 f5 y8 P; `+ V, q2 K& w191 G" ]" O! a# G5 M! |, V
    20) G! U6 [8 J/ W- z: L# e
    21
    " p5 i# C1 b' k0 Z* L22/ ~; _9 o- \- M! }, @
    23
      R# O1 ~0 v6 [- v9 C3 M. A24. [$ Y1 H( b7 I/ @" X- d( g
    257 A% J$ Q+ j! V. b8 v5 ]
    26( C" C: s( f4 q  Z6 [& S2 ^
    27
    # ]- m  {7 g2 h4 R0 L28) Y; E! R# Y$ L& A: @$ c& Z
    29
    & F7 i; B  H$ D/ q30! r% r7 y2 h! O' k" q7 J
    31, Q' O9 j! b/ m7 z
    32
    , g4 X& Q8 D5 m. r33$ t4 M- J& k8 H
    34
    - E. l+ S/ i3 Y4 w; Z, |35
    ) W; c4 U* P7 c5 q8 V2 a* O36
    0 |! [. ^0 A- H0 {: {" c# q37
    ; O" |% O/ a" q7 y. F% v8 X38
    # w8 p* t. y. j# A" {$ f39
    . D8 `8 n, i% q6 H1 i7 t40* F$ P, |& }# v" B, |2 V1 i" w
    415 b7 C( b$ L. L6 U% x/ T9 Q
    42
    ) g# u& a' b* q1 u. r) j43! h9 k- L, p7 g  G/ q
    44
    : G5 a$ p' v4 e$ x; Q/ y! j45( n3 m* r: h- w" _
    归并排序的特性总结:
    + g) R7 b9 j' x( L7 \
    " }# p- r1 h0 p$ l! M归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。* b; I0 @# M- e# Q$ u/ @- Y- G
    时间复杂度:O(N*logN)
    6 O9 y; U1 I- i% v空间复杂度:O(N)) n( u+ w+ X2 _1 y5 r/ j0 G/ _
    稳定性:稳定
    " ~( b# j3 J+ p* g* m! [! J/ w! f, j4 N# F( r3 Y/ p2 W
    ————————————————, |( U( P! L8 i# E
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ' f) U' z( C. }/ h原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    , Q* V5 s1 ~6 a% w  L6 u+ p
    " L3 e- p& O, A8 n' L! }/ D) G% j6 z/ V/ r" m0 E
    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-4-10 06:19 , Processed in 2.253015 second(s), 50 queries .

    回顶部