QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3274|回复: 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的排序算法】归并排序( Q; I& o4 g$ Y3 P' a1 u5 [
    1 i' X& p9 Q# y) D0 B7 P  H
    前言
    ) b. ?) N; \$ x本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。! p4 A- B; n0 b! N+ D: W3 g
    ( z0 R8 C, `, j& }; h5 H
    归并排序# Q. C& @( t: x7 m  ]; d0 U; g' J
    基本思想- |3 e: f2 N) @
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。) o4 |7 C) x, c# Q( F

    8 ]2 u/ r  i4 ~  K0 g/ Z" K! O
    ! u- ~& r2 |7 B. c$ O* F! ]
    % @* R8 w6 U: e: u: y. O  U​ 合并的思想其实和有道题目的思想如出一辙:
    ' M/ j6 }- X3 M8 v+ e( B2 |
    & x4 r6 ~( r) m
    2 A- z2 `6 W% M7 n/ w9 Q4 z0 q( r2 e* E
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    ' o+ ]. k3 w. f' ^  x9 Q/ j: ?# m7 W
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    & D. m6 Z- A1 W( {! A% R( M
    ) G: I, X/ V5 {$ g; rint* merge(int* nums1, int m, int* nums2, int n)
    8 G! G/ p/ z) v( t( H2 z4 b{
      q$ @$ P3 Q; M) d" I        int* arr = (int*)malloc((m + n));! j, P& |3 J+ d. T/ Z1 H; q5 k8 R: ~
        if(arr == NULL)' L" T. r- ]$ y1 ^/ n
        {
      \# b: u! }* d$ a% ?. j        perror("malloc fail");
    & F% l* @" _6 H1 m+ U        return;9 T$ R4 Y: Y7 v% _
        }6 w9 B5 m2 x  R+ q! `0 M/ Q

    : k0 F4 D9 S' |6 B    int p1 = 0;
    1 }. _% T3 g, ]1 n$ L& `5 h: a    int p2 = 0;
    ( }$ p4 \' w. g3 S    int cnt = 0;9 f+ }7 o) O  ], J/ j# v0 [) Q, T
        while(p1 < m && p2 < n)4 {/ p( }3 C! _- _. t2 a* N
        {' _+ d6 v( K, S8 W# c# s
            if(nums1[p1] < nums2[p2])
    ; s2 x6 }  [/ l$ |2 c        {  V  ~) L, g& R6 D4 |
                arr[cnt++] = nums1[p1++];0 W# c1 j' @5 A+ l- Z" n
            }
    / o- R  f) v1 z" O+ n        else
    : t, C/ e( q8 Z  B, s        {9 J2 f7 Z. B9 H( X1 y$ g
                arr[cnt++] = nums2[p2++];
    - l& Q* N; Q' \  k( S* f        }4 ~. X# ]0 p; j! j
        }
    7 N; Y- c5 U0 P    while(p1 < m)2 _. h  ?6 |; w2 ^. T1 O5 O, I
            arr[cnt++] = nums1[p1++];" Q  i8 K+ G. `$ [6 B. M/ z. q/ ?, T3 x

    2 N+ Q( `/ q5 w; B' X    while(p2 < n)! B" L, \) |$ q; ]6 I) k1 V
            arr[cnt++] = nums2[p2++];+ A' g/ S7 A! ~& Q; V  }

    9 x$ c) ]! a0 [3 y    return arr;6 Z0 }9 z& x# o3 ]
    }& Z! C! {+ D5 K# o" c: y

    ; ~( a- |) u$ S& _5 N1
    0 r4 u; z! @' U; x3 U% k2( w# k. h3 R4 k$ G- e9 R! P
    3
    6 W$ e4 q& d2 x$ A+ L- s$ D4; ^" Y$ x, j# d/ Q+ Y. b: R
    5
    + w- f/ ^! w( s$ a0 M& v6
    5 L4 Q( l# n1 E7
    & D, i+ g+ W/ u8 g6 L8
    7 X4 ?9 `4 B; M1 E( M  j& i9) u! o4 V" U0 a% r
    10
    5 ~- b9 d: `  o- A6 b9 R. g11
    $ K" Y+ ]* `* n# a( h( A9 O126 S7 O/ _) f$ D) A2 _
    13
      x' A6 {7 [" |' r2 q0 H# H- ^149 F" \% p. |9 I" P& ^/ G) t% g9 ]
    157 V; F% U" H8 {0 `+ ^: z. w: l
    16
    8 c, `* q, ]" K/ B  w2 h2 n17
    & M% C9 d4 P3 A8 V( k# `18
    1 G: M) O& S4 k/ z4 Y19
    6 a; n/ P: N9 P! u. O5 `205 h8 O5 k  ^7 \/ M
    21
    9 g8 T2 n8 e, V3 W/ l22+ y  U6 T2 L. z4 x# s
    236 N8 ~3 x4 U) b* n
    24
    6 h/ G, U& v2 D! z25. {  K1 q2 J9 \$ o6 X8 z5 @
    26
    ! g2 x  \7 U' b9 O- t& e4 K) r27
    " \( r3 c% B  b0 ~28& S3 m4 F3 I& H/ x# x4 }+ ?
    29
    6 k8 s8 G- f' g6 [( G8 a$ c30
    ; _1 v4 Q+ V+ S  N% v31
    ! s& X; @. d6 a; L4 q​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    2 g) F4 B6 ^5 `1 V9 R3 x4 ?8 [0 H& v; l
    递归实现' P$ O' S1 x3 t2 C) r
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。& V0 A# o9 o3 V- G& Y/ `8 c/ N

    , x# f2 N7 k0 S3 X! H' |
    % D; Y$ u  c' T5 l$ R
    : \! _0 Y. r* z' X3 y- _: o# `. y

    9 D% e# {; e1 o) ?8 Wvoid _MergeSort(int* arr, int* tmp, int left, int right)
    5 t: f+ i5 h$ S3 \{) E0 |; Q2 p8 g) Y2 E( ?: N" l
        assert(arr);
    * E8 T+ O8 m$ \- g9 c6 E' m& j( N. S$ r, F" {
        if (left >= right)//递归结束条件不要漏了
    % V4 S1 [, U) ~4 N; Z+ e9 j  V        return;; B9 A- a3 J. q
    6 g) m; S# q6 ]
        int mid = (right - left) / 2 + left;( W0 M- V; j8 Y( _+ I2 W. i
    2 f9 |( [0 w6 b2 a0 M" i; y& g
        //划分左右子区间[left, mid]和[mid + 1, right]
    + ^4 s6 E5 C) j% a    _MergeSort(arr, tmp, left, mid);
    1 {! A! e0 C) y9 A- D/ ]! H8 F1 y    _MergeSort(arr, tmp, mid + 1, right);
    ( X' ]8 b6 b' R1 G; {1 ?
    $ ~9 y2 W* E1 B& n2 M6 m    //归并' r* c: r# y) V" D# \& C
        int begin1 = left, end1 = mid;
    ( ~& n0 Y/ u. L% {5 P0 K    int begin2 = mid + 1, end2 = right;
    ; o! _& @, |1 K3 n+ v    int i = left;8 ~) j. w& C% c9 M0 P
        while (begin1 <= end1 && begin2 <= end2)/ y, F2 U2 U( _
        {! P. v2 a2 L8 o% C8 S
            if (arr[begin1] < arr[begin2])7 s7 ]( F( x/ L6 \( a3 t1 G4 e
                tmp[i++] = arr[begin1++];
    9 u$ o% L1 W; s- {  |% ]5 c        else) T! {: y" e. g: h( Y& D
                tmp[i++] = arr[begin2++];. K' Y% I$ D' w# Z/ F, A
        }
    1 |7 e, S4 D/ y6 U/ P  E+ Y. d0 Y- [3 I6 R
        while (begin1 <= end1)* N2 r& V* E$ G# Y
            tmp[i++] = arr[begin1++];/ _( u4 T5 G, h
        while (begin2 <= end2)5 h  Q& g+ U5 }; x9 j) r
            tmp[i++] = arr[begin2++];
    / y% Y. U4 w/ l+ j        % K. B/ ^1 m, S
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    # B2 V! B7 ]" B  l) l- ]# p" {    //而不是拷贝整个数组回去7 N% G( L/ \- f6 C
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));/ P( U+ C4 x/ Y3 ~
    }' b% A" q* A, v) \; g

    ( E0 L; Q+ K1 {9 evoid MergeSort(int* arr, int left, int right)
    ' B% ?$ S2 T# b, ]: X! U{
      |9 D/ Y- j7 _8 Z: k8 W7 l7 [    assert(arr);0 }5 P- r% t) X3 v7 }5 u, y
    % u) Y7 k2 ?+ L* j
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));4 q" z. C" g; \4 S# G1 \
        if (tmp == NULL)' z# o' W$ X1 h% @! ^- R
        {9 ]! t1 H; y- p3 F
            perror("malloc fail");
    . N% ~: i  K0 D' j        return;! \/ n7 @# C; v: |. K9 v
        }
    # A$ a- p4 W/ F: q) s
    + u# i4 ^5 ?% _    _MergeSort(arr, tmp, left, right);
    & I' m, z  s7 O1 k5 S, Q- I( h! i0 R
    + e* W% M  k9 H; J+ A9 y    free(tmp);; \7 K/ w/ ^- V+ h0 X6 W8 @
        tmp = NULL;+ o% o! s) f/ j, @" l- ~3 r
    }# ?9 i0 q' y! T( G) X8 J4 ^

    , q6 Z& w2 A7 R- S6 [1
    1 N/ A3 j; u1 ]  S5 J27 Z8 E& D2 p( H0 I* G1 q
    3
    / {: L2 j# N* c8 s7 F! h49 l3 A. S+ o6 O% v
    59 I, t. H$ N# X
    63 @0 U& \9 n1 `3 @; x7 j  ~6 b
    7
    . I, [% c/ Z+ j) W7 X8
    , V+ Y( D% J0 V/ w6 u. b9
    8 X+ H3 _; Q2 z9 n* t* t10
    . _; b. f. k- [9 r  a11
    . D7 I) K: n1 o* W12  l1 b$ k6 ]+ o4 O$ B" L
    138 X' X: c' J% @
    14: O0 M/ l0 c: P% ~0 g
    15
    / _( f4 a! }( I* }: C4 y4 e16# C7 t5 P7 E- }! h5 U9 q1 `
    17: C& R/ L; u" D7 S
    18& c$ z. Z& [; P- z9 F: {3 b  O
    19
    7 c6 J. i- q8 t5 ?: t  q) y20
    $ M) y  y6 s  O2 K9 @; I+ W9 g9 E212 f9 l. ^! Q" l8 T
    22
    # r, j' _. Z( f7 s) u* ?23
    6 O+ \/ R) P) R24- o7 L" G8 j4 q  T. j+ u# V
    25  X: u% s7 A& k6 v: u( q8 }
    26
    ) h& v# I5 d$ j) i' _5 q" F0 `27+ [  S1 `9 {, F9 Q5 P
    28
    9 S/ a$ \$ @% t1 V29, L5 I  f9 @' Z7 n# P' i! V
    30
    0 e0 I4 \: t( U( R. `4 f% |; {" |317 J1 V4 L3 ?$ ]
    32) e1 Z0 m5 _" `6 p- K$ \8 H
    33- ~, e( [* }% v4 H4 X
    34# e1 \% b; x  X, U# s, D
    350 p2 |$ u9 }+ V1 I9 J! O
    360 \+ R% q& I- v
    37
    + v; P& s7 g/ S% \387 u+ F7 h3 B$ G4 [; i' c
    39
    / }' ?2 E3 o* o) u# X406 K1 A: j/ t: L5 s3 H0 J% _. n& ~
    41$ |( o5 d0 [8 J! e6 N$ M
    427 F! ?! m1 L. F1 [5 {
    43
    ' e5 J2 {( Y. v44, z" d3 J" i4 q
    45
    4 q) J1 J! ^4 i2 n4 B; z) c46
    - |- n: S6 ^6 D# c9 C0 q4 H/ ]0 Y47* {9 ?1 z/ }% q
    48
    0 e. |% L* ]* `: N& `3 @# X, ]/ M49
    / k4 a9 c) P; O503 U- _1 i% `7 L5 l3 D3 L6 X' E
    511 X, I& |" Q* g7 w
    非递归实现
    1 C9 y* D* x- j​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。; A4 i" B0 \- l0 b. d) I  C( |
    % A& a- V- f  W5 G  R: Y: u7 d

    7 n7 d2 C0 c. H
    2 T+ v& b5 h( r- a# t​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    8 i* l6 P7 a! N3 @1 u. z
    1 t7 u5 a; J1 [9 k$ y7 C​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    . i$ A7 b- }4 b
    ( Y7 ~5 m) |. L# s​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。- r( F" X6 l/ }# y, |# N$ V' w2 Y
    4 O+ Y* h$ v" f; `% z
    代码实现
    0 C) ]6 W6 F+ J! b4 }/ @3 P
    , }# S  {/ K/ mvoid MergeSortNonR(int* arr, int sz)4 Z4 W) {# B4 ~7 I: d
    {
    ' F2 H  r) b2 v4 {4 _    assert(arr);! S% x  K$ m) m4 m% \; T+ B

    1 p' n- n. P# T5 I' \2 h$ |8 T/ {    int* tmp = (int*)malloc(sz * sizeof(int));6 E/ I% u  w* M5 {6 }0 R
        if (tmp == NULL)
    : ^( e# B; m1 E) u- L    {+ P. R" Y7 y3 _/ e3 ?' x. q
            perror("malloc fail");! W$ P# J3 A" \- H, S6 g
            return;
    & r; Z  N+ X2 |) \& ]. `    }
    5 ^! W0 v) n; d  s; W& z- G8 C; N3 |6 `5 `# \/ R) S
        int gap = 1;2 x* x7 @  Z: C( _
        while (gap < sz)1 z2 q/ C" q$ Z) I3 P9 R9 p
        {
    . @7 C: f! G  E) ^# _# C        for (int i = 0; i < sz; i += 2 * gap)% w; t! I8 Q+ H) p( K
            {
    ' M; g$ }2 B1 J' Y$ a5 \+ z! K% z            int begin1 = i, end1 = begin1 + gap - 1;
    2 V/ p% U! M0 g  `1 {& b% w" w            int begin2 = end1 + 1, end2 = begin2 + gap - 1;+ u2 G  j& Y$ @! w1 d2 D( D
                int j = begin1;
    % y+ d, ]+ Z& ?: E5 `
    ' X; g1 I, V4 d- j( i            //归并
    + G  }* S- b( U8 _            while (begin1 <= end1 && begin2 <= end2)0 S/ G# d7 E1 P9 V3 t: S
                {
    ' x: ], B8 ]5 c% w' ]. y                if (arr[begin1] < arr[begin2])
    + l" W0 i/ t5 [                    tmp[j++] = arr[begin1++];3 b$ m/ S0 d2 ?5 ~8 `
                    else     + A2 _6 y# G% F
                        tmp[j++] = arr[begin2++];4 g. O/ v7 C6 f: K
                }6 f9 J" y" q% K* S+ d* k2 \- h

      K/ S( g* e( h! w3 |8 J1 ], a/ y4 P            while (begin1 <= end1)
    , G8 U3 P/ C3 E1 Q                tmp[j++] = arr[begin1++];& f8 {# v+ ]% Z* q% P( t( s
                while (begin2 <= end2): l- P. B0 z3 E4 X+ a
                    tmp[j++] = arr[begin2++];
    3 f% q; Y2 n# D  M6 K* C
    " U. T3 q) f( y; r! L) N            //拷贝回原数组——归并哪部分就拷贝哪部分回去2 ]; r2 w3 u7 W+ i! J- }
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));: g% z( [+ n4 c, S" h5 i
            }
    4 h9 K, }% r: h        gap *= 2;+ _2 G; `3 S) {% x
        }
    9 [4 _" C" _5 Y8 @. s
    " F( D( \( W  c6 D- |7 O9 G/ e}
    # C0 o" \0 G  n/ C: A; m6 v: ?
    1 r: H: ]% A4 T, s/ t1
    - S- Z* R. Q9 D% F1 \8 i2
    ; ]# E* V/ V$ z  Z# T0 O* K4 {3) K6 u. T0 }& ?) A4 U& z: O0 ]+ h
    4" {; s. f- R: e7 ?3 c
    5  J& o9 _/ y8 H/ t4 l
    6
    ( K7 \" a/ N. A9 G) u* [" Y2 i9 [74 ]7 w" K& h4 w6 _  L* @" \4 L$ |
    8
    & b: G. q- r$ p. U9: {0 t- d$ x& ^. e1 d7 Y: Z. p9 _
    10
    $ p3 |6 O! J  A% j2 ^) l11
    ; l, g* p  i8 A0 ~, L5 W* u12
    8 d( [1 Y! L' l: r( b( H4 W' J13
    - h* j" h* b: \# `7 d9 r149 D7 }$ A3 s( w9 R) k1 P
    15
    + B# {. Z/ B/ i4 C16, \) [+ x1 N5 n6 \* O/ x/ R
    179 B( ^' i% L; j
    18
    * }) p# T/ u" g: i  g19
    ( R, j" a0 Z3 \: H20
    ' F, L6 P. w( B6 S/ _% P. ~219 \+ K, {& l  Q% q! h: z
    22% n6 g, [2 S. P2 N
    233 x0 o! S# n0 |+ u" }: M
    249 L' R' F/ {# e+ a
    25$ f, Y# E! L; z! X
    26
    " d! b% n9 V. |9 H! p27
    * t" G- I2 T1 d# }% Y; Q289 S# W7 z1 x6 }, [) O
    29
    5 F: Q- i, ^6 r) j  F( ]& e# T& c30. ^; t& E& Z% P; N* Z" w! W8 D3 B
    31+ S- I! B4 y+ o, C. {
    32
    % b& ~: M# s7 Y" h' [# _33
    ; U2 O! {& L  h- I# _% N/ i34
    ; ?* ?0 K* @3 X) G35
    ( A, }: H8 [0 W& g6 n7 S- G36% y+ x7 R' M: i/ T6 p, V9 l
    374 a* j: D/ d- E' c# A+ H: C' i
    38
    & L4 \. j  x# p1 E39# i4 ]# }7 B6 _7 h" I5 G
    40
    . V* ?  }/ J& u8 _6 H41
    3 x5 f2 x  q: }, T边界问题
    4 V( l& r* V& G. E( U​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    9 q  o; z& J6 m) k/ J+ x# {1 D2 z% M( R9 E  Y7 m* G. e9 a
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:1 Q. U. z+ ~; @. \
    9 s* [7 w- a, x5 Y+ S9 L
    4 E6 A8 k% u, v: p& m7 U8 z

    : a# b( r$ ]1 Q& F由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    . V3 D" n6 D5 u, k# r+ j! d# R" s. E1 k7 p. `2 s
    第一组越界(即end1越界)* l) n9 D) D0 E9 L$ v

    6 }5 J5 n! o3 \+ E& c  D1 G应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。. M6 U0 B4 _1 N+ t
    - ^6 \& U  p8 ]' z+ b! z: M/ Q
    第二组全部越界(即begin2和end2越界)6 }" v$ n9 K& G3 y
    + A1 ~& p) G+ U( T
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    ) Y' }$ c" `# c$ b1 F5 t; ^. S! o3 [$ U. v
    第二组部分越界(即end2越界)0 r  O# [% E$ d8 O# y3 V# u

    " P( l! A, |; O% z应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    # }% A  ?3 g' S0 E2 U8 k8 `1 c8 O& l- X
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:) q# ?5 T# o" [5 f& b8 b

    0 q$ A2 G2 s& v1 k+ n​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。: S- d$ N  ?; T* O! s! I

    ! i) U6 l; M4 P7 {6 P- P' N​ 拿两个数组试一下:
    ( S' O1 {% \6 K
    ; b& [9 g. E" P: g( }& v$ f8 z0 o! x2 X5 V+ z" O' w
    7 j- C8 p7 I2 h, @! E+ H

    3 V1 m- h0 `0 V% u8 s
    & W0 r+ l5 c, U# N& Z7 ]代码实现
    - {% j/ D7 E" |
    8 i) C6 v' _7 k+ W* p* rvoid MergeSortNonR(int* arr, int sz), I% Q) t) ^( ^# ?, b0 N
    {
    % K0 d1 G( E5 w7 M' |7 p( `& l    assert(arr);* f$ `* @6 k( V! i- @8 ]- V
    6 a+ ]; d5 u! x0 O
        int* tmp = (int*)malloc(sz * sizeof(int));' v( p2 x) u9 o6 t" Y9 q
        if (tmp == NULL). x0 v! F6 ?- s: B. k! Y) ~
        {4 f! \* h0 N6 y2 l0 Y) \. ]
            perror("malloc fail");
    # W% A) a. G& [" O1 K/ O        return;6 z  g. k  M% t2 `. n
        }
    3 I+ s, j6 y/ e5 F. |9 j' ~, \, }: R
    0 i8 X& E, K: o0 k# ^; g" }) m  E    int gap = 1;
    , M" J2 Q6 @1 \- S" Q    while (gap < sz)" ?. v4 ?; H# P+ `4 t
        {
    ! V& M, b  q/ U/ O6 |        for (int i = 0; i < sz; i += 2 * gap)
    6 m5 Q2 v, |- W: m& i+ m# [        {% Z( j5 J% {6 u2 i  j
                int begin1 = i, end1 = begin1 + gap - 1;. X6 d" l3 o& b$ n9 ?
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    7 E) p- n% S; T7 o$ B# X; L) b/ A( T            int j = begin1;
    1 }# u, i" m" C5 f# y6 W6 l2 K8 e                        //越界检测
    0 }0 S* v6 z# j. k+ D% h            if (begin2 >= sz && end2 >= sz)5 D! k) M: p/ q5 }, j; b- ~9 v
                    break;$ G: H; E) v7 w6 P' v! i
                if (end2 >= sz)
    * Q% ~5 z! n' j  |                end2 = sz - 1;* D. i* o: C% Y7 j) ]
                //归并
    6 S- x% H& Q7 o4 U& q* w3 J9 T            while (begin1 <= end1 && begin2 <= end2)
    - O0 H6 C& Q* s" Y; M- c" E  t2 r8 E            {) L3 {# i4 T, G* o5 n
                    if (arr[begin1] < arr[begin2])
    % C9 D! \7 o' l. l8 b                    tmp[j++] = arr[begin1++];3 z# ~+ E' M5 A
                    else     
    / R4 }6 K9 H  i. t: J4 B9 c                    tmp[j++] = arr[begin2++];0 _+ H) ^$ \- b( {6 N& [
                }
    ! l- k& a+ L$ L- g* C6 j1 [2 z% a, B* D8 K
                while (begin1 <= end1)) ?( ?% G# H) q/ {; x& F
                    tmp[j++] = arr[begin1++];
    ! q: k1 s9 I" L, x. _- A            while (begin2 <= end2)
    & ^  m. b2 k' S1 t9 X                tmp[j++] = arr[begin2++];3 ~3 s3 `0 m( q9 B. a' F! p

    0 h+ ~2 A% Q/ m3 r            //拷贝回原数组——归并哪部分就拷贝哪部分回去" E3 M) v6 n- d2 y
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));/ U  y% P0 I" G6 [
            }
    4 j7 b. Z" @0 h3 K! [; [" }        gap *= 2;- X7 ?! Z* o: u5 A, q
        }) j# D5 p1 C6 U& b/ O! z5 g4 m

      b; Z5 k: j! {& S$ P}
    ) X$ x  ~  W3 l' g- @3 J4 z/ R. o, E
    1
    # r8 ~0 b8 e' A2
      r5 [( B* U2 [- U9 U% L: w, a4 D# H3  a7 H3 r' I* t) ^) R
    43 ~: x9 R) S/ q3 N+ y* C
    50 E- o% i$ Q! m8 p# {0 v
    66 o) V4 V% i8 Q/ D# d! U9 B* n
    79 R0 B9 }0 B: U( B. g
    8
    * g& C; I( P% l" D' y/ j1 e. H9  m0 i! @; x3 i. _4 C& J
    10; q" {( M+ N1 Z/ H$ f% E
    11
    0 _; w3 ]( ?0 z- c  Y, U' L9 b$ g120 _5 u9 i0 e7 ?: \/ ]. P4 m
    13
    : v( S0 Y& B# }6 k, X: i14
    9 [) d: {) p" S. z8 w( y, Z15' R  p" d$ w  J$ P9 Y/ _% k0 H; S
    16; u# J. I. i  c2 j
    17, V& E. F/ P. t" f  Y( e
    18. ]! |; `$ ?3 }% G
    19! X! K* u9 X4 s) d
    20
    . U# B9 `' d8 C) A21( Z5 Y  c" j$ z* `( T5 B! V+ g
    22; ]5 }  g! ~0 d3 p; _
    23
    2 |1 [/ h/ j5 C! r- D& \/ |24! U5 Y# ?6 ^, k8 }) I
    25
    7 L. X0 s* P9 k+ V: y& w4 k26
    , Y6 x$ p$ D7 f27
    8 b) e: Z8 V1 k1 R8 L6 _28- N; `. `% z# w; M/ a5 i) P# O7 G1 j
    29) |  V* J$ Y6 D) P7 W5 s
    30
    + n: j5 y- {0 a4 z+ H313 B* l% j- ]5 w) d1 ?
    32
    ) v6 V; q5 A  ], j6 \2 b33
    " X" w: Z0 M$ G" i  B34
    & y* k. x0 Y5 C/ |1 H$ P, G! D35
    6 E# }" d) ?7 L" ?( x. U5 ^% f36
    ) S7 s, a1 K5 @37' w9 U! U6 o+ E, {" R
    38
    % h( ?3 T1 e* f  R( z39
    0 E7 Z. ]$ \# X, X- M406 ], M0 Y4 N( o" z8 h# y
    41- d. b; P, r' G: q9 V
    42
    4 U- _5 Z8 |6 H0 r; v6 d3 Q43+ k! V4 ^/ F8 l9 e2 `- R# _+ i
    44" A6 j- G& v, N- M
    45. g1 B. x5 e/ s9 f' ^
    归并排序的特性总结:
    ! u: x) E. e4 W; Y9 S( u7 b; B& R( q; E% u+ i7 c5 T: n
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。! o- N  v7 h( I/ U% L' A% L7 q1 U
    时间复杂度:O(N*logN)
    + c4 {5 n2 H2 U8 I% }; \2 }9 a空间复杂度:O(N)
    * J. W! G6 k3 K# H+ h( C' J稳定性:稳定/ S5 i1 Y: M( t- A' p' h" j! X2 t
    ( c& X) V: \& E8 ?# O& o
    ————————————————+ ~. }6 X0 z, M' ?
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    5 h; `; Q" s& ~9 E0 P5 {原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657- ?" v2 C2 s% m, E
      N3 ?& A! X5 |; \( f5 p/ C

    5 p8 n6 q+ w7 b' Q7 w! e. n" T
    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-14 03:43 , Processed in 0.415002 second(s), 51 queries .

    回顶部