QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3279|回复: 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的排序算法】归并排序! h/ ~6 T& r8 }  h; T
    9 _; o# j$ x/ O- M
    前言
    ; n2 h4 @4 S/ U. K0 m' Y本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。7 Y8 S2 s& D+ w

    - {* ~0 k+ k* W  z) Y归并排序
    ! N' }' [, C9 `5 z基本思想2 y! ~) n* d/ y5 m$ c5 u
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。) u* {5 h. h- M- P" ?

    + |6 |$ F' S: ~) R7 f. W, S- G' c% X' P, G+ p
    ' O3 Q: T. b/ ?3 G0 K% V/ |4 Q9 @
    ​ 合并的思想其实和有道题目的思想如出一辙:) ?3 H# q7 F5 f  |# s: X2 w  x9 \

    - A% @# k/ w& X, e5 ^
    / Q" y3 e: x; p& C* c7 i% y, F# t
    6 Y. R6 B7 [1 N' e  m3 I​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。: Y" }' w1 k+ I
    ( O1 I) K; c; t( v% o! ]; q
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    9 Z* w/ g! p( \' F" g
    3 r! Y' \; b9 G1 `; Zint* merge(int* nums1, int m, int* nums2, int n)0 V/ H3 k( _2 @* D: h  d
    {$ f* Y4 |- }% ^# K0 m
            int* arr = (int*)malloc((m + n));. s! n0 m& }4 p) |& g
        if(arr == NULL)9 O+ c' D  V3 g* B  Z7 `8 N
        {
    6 F" |8 F# A  y3 k; ]$ |! f' u        perror("malloc fail");/ \) G) F+ i8 ^. l
            return;
    9 w4 i2 r. Y& k) z9 e3 e- N    }
    % E5 M4 j5 W% ]. v; d" w% ?& _: {1 W- ~2 S- O% [0 p6 ^: N/ H7 B4 h' H2 T& s
        int p1 = 0;
    6 o( ?" c* M7 J8 I    int p2 = 0;
    * J' z2 ?* B& I5 f/ F: V: g- N6 W    int cnt = 0;
    , @' ~6 u- [& ]& [- O    while(p1 < m && p2 < n)
    + V/ Z$ \( J( C7 H3 D1 ]9 d& _0 J    {: p$ U$ \  k# W; V6 n/ e8 |
            if(nums1[p1] < nums2[p2]): ?% V0 W9 n2 _3 y8 O
            {
    * [8 w- N% v* v$ `0 U2 v9 _            arr[cnt++] = nums1[p1++];: E; q) O) |* T& N  X% |
            }
      Q" ^* a1 f1 S' k! D4 W# \        else
    + ?+ _; H3 f% Z1 K% |6 m: b+ [        {
    - S5 p: ^* L& X+ [$ Y- o7 s; E            arr[cnt++] = nums2[p2++];
    5 X' N. l% Y6 q$ h        }
    5 p. q6 @: R9 `$ `* P    }
    3 o3 N/ n0 y/ d% b, ?' O    while(p1 < m)
    / g. t* l$ I/ `. P        arr[cnt++] = nums1[p1++];, l0 q: U( `& w& u& z' v

    + B$ t9 W) U" _+ F8 u, O$ H, I    while(p2 < n)' F+ d8 k5 B' b8 {
            arr[cnt++] = nums2[p2++];
    - w6 e2 N& p+ n, D# K# {2 d. q0 C
        return arr;& x2 a* Z( I; X9 S
    }
    , h! g3 s, c1 M, G) n
    6 `# F! ]) o) {, F4 i8 ]0 h1
    6 Z, {  S9 g  m( Z' H2
      N7 L2 u& W# ]5 M% R/ _. J3
    : a+ X3 K9 V* t, R* k" R4
    0 s% S; L( F+ E  Z5
    ; [  x* d5 ?( _# @# x- I! }6
    # n) v* m; b& C7% W' v9 G. C$ E  G  ~7 m& q
    8
    9 v; y6 i+ p( `  \0 @* [9
    4 e5 Z7 v5 {( c6 I* G+ q10
    2 h- x6 S) ]4 n3 H3 o% R7 B11
    5 `' G- R# Z% H* Y12
    5 _0 p* h+ U1 ]" I9 J# e, J3 d6 n136 j. [  l1 }* A
    14; d  {# g6 I2 s* V& z  M9 |9 S" c1 C
    15
      ^3 B' }- h4 o- e1 s1 L$ F9 o9 P! J16
    ! {, ~* y" `, X' N17) ]4 |  ]/ n) S8 t3 z- Y
    18
    - l. q" p0 S# c191 c; J9 I% Z* t: G2 O- s( }
    20
    ' i: V8 z2 N7 b- r# p6 J2 ~' p21% f$ L) Z# c3 |0 P, }
    22
    ) W$ y0 }5 A$ l; ^; \! K  b23
    9 p& d( z2 ^( ^9 S24
    ; o. b8 [7 ?$ }; N, A25
    $ _, i6 @7 g5 c5 W- w+ K- x26
    8 _" k" w0 [8 t  t27  W5 P7 D6 X6 l6 W7 j
    28/ d3 h4 \* o. d4 L+ W  F' Z) y
    294 J& ]6 {0 ?$ Q! N: S5 C
    30
    + O$ K/ @3 {3 x7 P% n8 w: [. L31  I9 A. W! A- }: ], }
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    2 _7 b2 Y# `7 Q- A2 P" V9 k, f2 Z) ?& A- j. f2 t/ n2 j- ]' r. Z0 Z
    递归实现
    " w7 Z- T& d9 i/ \​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。# j$ N0 q& \. H/ q

    ) v( E" v* R4 ]. o' i4 R0 x. h6 K; ^( t5 N0 f( z
    - ?& k5 j9 M' `8 P) G2 x* t7 {
    9 b5 i; i1 m4 M8 f2 \4 e

    3 o6 H6 m' z2 P! [  I& \: ^# ?void _MergeSort(int* arr, int* tmp, int left, int right)
    6 c4 b- N8 u2 P2 P{
    & J. e# X0 X$ E9 l    assert(arr);
    5 _; ~2 n, I9 O7 d. j! a0 w2 Y
    / x: M# r4 W  t4 O% g5 S    if (left >= right)//递归结束条件不要漏了
    . y- E5 B3 {0 H        return;
    * B& y! i9 i6 {4 d0 m" J" p3 F" I* l( r. j1 y/ b
        int mid = (right - left) / 2 + left;
    . E6 H) Q4 i/ p3 @  H( r) p# l  |7 D. S4 E& u! A5 p
        //划分左右子区间[left, mid]和[mid + 1, right]
    & p  U, Y4 H: p6 U8 n    _MergeSort(arr, tmp, left, mid);; a' V9 p  L* L* \6 A
        _MergeSort(arr, tmp, mid + 1, right);/ A0 W4 w2 ~9 \; ~! Y7 S

    8 a9 i) U. O5 G    //归并$ I6 \. ?8 |0 e
        int begin1 = left, end1 = mid;. i- J* L( G) ?8 h! z6 i  ]2 M
        int begin2 = mid + 1, end2 = right;
    % B- i6 L- f1 Z: |# g& N: x3 v    int i = left;
    9 Y) F6 N; d' C% H* M/ q6 ~    while (begin1 <= end1 && begin2 <= end2)
    : n: K5 y( w0 \+ V; P/ D5 D    {, g8 [3 Z6 |  x% l% T; D/ e
            if (arr[begin1] < arr[begin2]); k) `& n, a  }5 T
                tmp[i++] = arr[begin1++];
    5 n; \3 }7 O* x0 [3 d0 w        else
    / G/ t$ ~. v" u# k! X+ h$ U            tmp[i++] = arr[begin2++];2 U2 n6 a8 ~1 ]) I. ?
        }
    % C2 L& H; Y9 w4 \9 T8 D4 \
    ' C/ z% U3 k! l  R$ n    while (begin1 <= end1)
    , C# H; \# b: v0 @1 J        tmp[i++] = arr[begin1++];
    0 `* P# y1 w& t! Y. r. G    while (begin2 <= end2)
    . E+ L* U; x( L$ o* X, h; ?        tmp[i++] = arr[begin2++];  z: J3 m2 [5 M; m# y
           
    & Z  n" p; O' h0 y) r" P& F, a( N; \3 k    //拷贝回原数组——归并哪部分就拷贝哪部分回去1 p1 L; c' `' k( I* m
        //而不是拷贝整个数组回去) V& j; z( o: `
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    - K) C% y' n, w3 o: f& P}8 w# t" d  h0 n: Z) g

    ' b# O  [2 q  X. B: \; r8 Avoid MergeSort(int* arr, int left, int right)
    9 H' f% m2 A- Y; a{# \, B2 g1 I( B6 [
        assert(arr);7 w/ m0 R$ E* y# e7 K

    : S' K& j4 V$ s; {    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));4 L& Y* f/ ]* I: E# N) ]* A% y4 r6 L
        if (tmp == NULL)8 o4 E  f( J: j0 B% K- ]! x+ \
        {* H9 a6 R3 X, G5 F* H, S
            perror("malloc fail");  V9 `6 @9 B1 E5 u9 C1 u3 n
            return;
    4 o. A+ h; K4 u- x6 E    }8 R" L- M$ }) d4 i, l
    , F' d/ l7 v* U
        _MergeSort(arr, tmp, left, right);! M. P/ C/ e7 w$ o2 @
    6 L6 Y; q  ?- g* N$ \9 F
        free(tmp);
      L  n0 E+ ]" k" m5 J    tmp = NULL;7 D4 n. w% U4 D/ I$ }" C
    }
    , N! j9 K. f- z9 `  X& B, z) Y5 Q, X0 O
    1
    . R) ~6 p6 O9 S2/ S5 k& d9 V' {
    30 o6 @8 @" U* G$ X; I' y7 t
    4" L  \, O2 m9 }7 H# W4 t
    5- [1 a; m2 s6 B2 N  s$ g
    6
    6 M) E: J4 x- F* P  g7 H7
    8 m6 S% K) _+ x' V8 G1 |& H, f8
    1 h# Y- e5 A. e. {; O9
    4 W3 x$ I; z; h4 W. A10" W, B4 R- ?4 W/ R" A
    11+ u8 q$ e* S1 X4 e  D- X
    12
    7 O3 u/ E% C* e! K, C130 S+ B2 e% o2 @* _) r8 y0 [( j
    14
    4 M$ F! D* {) T4 I2 [15
    9 L5 o, h8 b9 k3 R. O9 v% ^" _# N16, c) q* |6 y0 E+ n9 @
    17
    & J  d0 x0 O  n9 }7 v/ [1 n' R4 m18
    ! Q) A4 ]# y8 J* ~2 z; k19
    & G# d/ x. F. \4 o" K20, r' j% y% M* D8 V/ k
    21. E- E! P7 G2 a0 ~' @& W9 ~
    22
    - ?! M/ K. k- ^3 [/ C& j; z23* z3 b1 Z6 R  Z! M. }
    24+ m% f& s9 x' D1 H3 r7 [
    25% M8 O( C3 g3 v
    26
    8 G( P0 H" ?9 V- d6 k* d( a279 O5 \7 y6 |- x; m5 F0 K; J
    285 I8 B/ P1 Z2 p' Z  p
    29
    # g' B( R+ ^! S1 c30
    ' N; b( Z, z3 Z; L31' T, s, ?# V# V6 q$ H. I  }
    32
    ) g- E8 I1 r. K; p4 O33. U1 f: T0 O% r1 g0 n
    349 O4 H# ?1 Z0 A$ |: K
    35& I- |1 e- {- I
    36
    - G' u3 X! G$ V" R& r37
    9 V! q: r! ^: P+ A6 f9 Q3 _* u38
    # Q9 F8 H$ T5 T9 z1 F1 ^39
    0 k; C4 T( x' R402 b$ D% s3 j2 h  U6 W0 I
    41! F! P; n4 u0 H4 Q5 {
    42* ^: h/ c! b( f4 t4 G2 Q
    43( c7 [5 C* e6 A2 V/ I
    44- S; e  V3 |/ \( b7 i% ?# d
    450 ~' B8 p& w8 k5 m2 D
    46
    . i( \3 h( K, y2 F8 N; W; \7 \47
    / P! F* i/ \# |' ^48
    1 r. m8 y/ ^2 e49
    + `5 k/ ~( @3 u% f$ f# e3 m50
    ! z. z# m+ s5 T514 M& O4 {7 Z$ j; U. b
    非递归实现1 ~0 `  V6 P" H' X, }/ z( ]5 \/ ~+ X
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    1 \' M, a- F" c* H5 f, d' d7 Q4 E# f! W) [9 i' R3 j

    : A1 z, y, u0 c6 j8 c1 c
    2 c( K: L# e: S7 [; J3 u$ P: N# c​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。0 b  z$ N( r7 D- g% V$ X1 A2 W
    / T  [" r+ n  u) G/ D5 o& N
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    6 N' y; w0 Z9 i
    ' P0 ^5 t7 Y$ U​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    4 A% r* {# X/ j2 V$ O* G' F, d; d  Y2 k, u# v9 u) R3 J, R
    代码实现+ G% k, g  k  p, l/ Z# W2 w3 k
    , \7 D" R; z% k
    void MergeSortNonR(int* arr, int sz)
    5 Y7 Q# b: j; H5 h2 p0 P9 `- j{
    % j" X, }, U" w, Z) K    assert(arr);& @$ _0 ^. c% u2 l! N
    . y, J6 b# `% ^2 |8 R# @% D5 w
        int* tmp = (int*)malloc(sz * sizeof(int));
    1 s, p0 i2 N) Q& e' U    if (tmp == NULL)
    % Q4 _$ R8 W" C- @: w( \    {
    ) @# D/ [: c  [1 s0 s        perror("malloc fail");+ W3 i( l& z7 F  k
            return;. M# F! H  W8 \- V: {6 _
        }! G6 e$ h  ^. ?
    ( j, w. a, k' m) f# V( N4 R. b  f
        int gap = 1;6 r8 O) V- }9 Y2 ?9 S
        while (gap < sz)) f0 @+ H7 N) ^9 L! l! K+ \
        {- g9 u# q- j2 X/ d
            for (int i = 0; i < sz; i += 2 * gap)* y7 Y" S! E0 m  o3 j
            {
    / v( b! H: Y6 k/ z            int begin1 = i, end1 = begin1 + gap - 1;! z6 Q5 t0 d* M3 E9 H
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    ' h% k' h6 o6 v. P/ |            int j = begin1;
    2 X0 f/ X8 H9 W: c8 N
    4 r  t7 v  [, e! `            //归并
    ; ^1 e  p4 w; v+ m( [+ z- J            while (begin1 <= end1 && begin2 <= end2)' n1 ]% `7 s5 A; f6 J" J2 p$ n
                {
    $ b8 v% Y+ ^7 c" }% Q- F) J                if (arr[begin1] < arr[begin2])3 |/ E  j# z& g+ X
                        tmp[j++] = arr[begin1++];
    ) c. u! D+ Y8 Y; Q1 j                else     
    - H. D* r# q) O4 F& B- z$ p/ ]0 ^. n, R                    tmp[j++] = arr[begin2++];
    $ `8 n' x$ ^# e( d: T8 C+ v            }5 b; w: `. s% f
    ' `0 T" F5 d8 }5 s, T/ B. C( ?
                while (begin1 <= end1)3 g6 N9 k' G7 a2 N2 C
                    tmp[j++] = arr[begin1++];5 E, J: O; b8 E8 n3 C7 m& A* d+ k
                while (begin2 <= end2)
    4 a' f, u) z3 Z6 g2 |                tmp[j++] = arr[begin2++];
    ) S5 J( ~: t4 A9 L
    ( O" k* W% w8 i- e            //拷贝回原数组——归并哪部分就拷贝哪部分回去3 K/ \& G, ]% |3 L; z1 ^( M
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));& S$ A6 T1 Q2 Z# V  M6 t$ y# c
            }  T) c: i; L: _1 R' L0 V
            gap *= 2;! i9 Q% C0 ?2 \0 q6 T4 ^3 v
        }
    9 k5 W6 P' G9 |  ]+ N' a6 S1 Q. e2 o  q: ^5 p3 f
    }
    ! c0 H4 N4 p! A) D. ]( ~# V/ U( w' K" [3 e
    1
      z2 t' W6 n3 F+ |& N" w8 ~2
    # S$ n5 {/ n- I3. O9 i: ^" _0 m8 L. T  m; h
    4
    . X7 F3 p* X- e! R+ ?8 ?3 {$ p5$ Q" q% ^8 J# H' O- _
    6
    7 d( b' _: {2 X2 S0 s! y7+ N/ R9 ^5 c8 M1 i4 }) G
    8
    , k7 `/ P7 N- n4 F1 \( U1 |9
    " U" Y3 G1 A; j! m10% ~9 w+ Q3 d, x+ [4 C6 g5 c
    11* M) K+ _3 j& l
    12
    % G& J1 }8 c/ Y- u13
    , ~3 D  y* G% I$ s6 Y14  f( y" C/ w2 u2 D5 I5 w
    15
    ) o7 M; C  k# z- i2 c; _" x1 j4 k( l16
    9 [6 K1 A' T# {9 S" p17
    $ X' i5 `7 N, P8 V18' n& u. @+ A8 B4 B+ r/ @+ }
    19+ V  G8 o. [' a& F5 m' i, e- |
    20
      H* ]7 }! o6 y* Q21( R' [9 y/ C8 o/ o) ?# i- |8 i
    221 z" |+ o, U$ g& |' J" @% I1 p$ E
    23$ b( _+ ]" Z( P$ H2 Y4 G
    24
    . c6 g  `' ~, F9 P25
    ( o* ^9 ]# `: I/ |# V26
    9 J6 g! g0 S6 h: i' _* J1 q+ C27( d+ d' D6 {% L* w: |' _8 h
    28
    9 k* M2 x0 f: Q4 _8 S! m4 m& Z1 u2 {5 b29
    5 E) f) D- v  k+ i30
    ' h" U3 x, M5 p31
    ( k; t( {7 M- q$ K( w* f. o322 L, y* E0 V7 Y- u; X0 n+ p
    33
    5 D: P! x" e& S, P, X; Y34
    . N7 W7 K  b9 q35* I$ m6 N2 g1 R
    36
    " o% y4 M) q  c/ B6 `; z1 }' S37# H5 ?9 L4 a  N: p
    38  p$ ?) X5 S  |. d# L. J
    39% N) @  c. m# S' a7 t- V
    40
    : j7 o) v6 G7 O' n& H41
    / o* h4 W0 u  T9 u边界问题
    1 L% B7 E( B9 Z8 @0 I  ]9 f. P​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。7 L0 E, c  h5 G, `

    4 f1 v: _1 ?7 {: o- ~: H- A; A举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    ' j5 ?; L6 g5 v& e' `2 L9 @( `6 o% l/ m! ?# ~. r# d
    2 n3 \( R4 Z7 u1 b9 {; Z2 a& S
    1 I) H7 m: J: {+ e8 x' S) N
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)8 s4 x: i; y1 c& G' G. s

    % u" m& F* Y& J: O" ]/ a  [1 ?5 t第一组越界(即end1越界)
    ( ~& r$ s2 Y; I, r0 \0 U& f- S  O: H5 l8 T5 V) k; Y, ]
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。$ H" m6 {9 c9 V' T
    ' \" q/ a/ E, [1 n% @. Q# a
    第二组全部越界(即begin2和end2越界)( y  \: m# `' Y. v( B
    ! a2 l+ h- w, }5 z
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    # J) b: a6 n5 v& T/ W. x" Q8 }& c1 R: L
    第二组部分越界(即end2越界)3 E2 M8 N, ^0 ?1 m- t3 D. A, t
    ' _4 \6 G+ _; X# g: i8 L
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    # o- i: f+ C+ M# q0 L- m$ Q$ B: X8 s# e" ~
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    ' E; m' m( I( S2 \/ Y; @; j6 ]5 t) W. ~) F6 w* B4 D
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    2 B7 X" X/ _: I2 R- f" t- Q0 [5 u0 j+ i  j. M) I' \: Y" V; A0 M. C
    ​ 拿两个数组试一下:9 y( R" @" o$ c( Z! L' p, _
    3 J8 M! y( r. Y/ v

    ( n" k% i7 ]/ }4 z2 u
    ( X/ ?" ]- P" ^
    # N' r# J. Q2 ?; o9 i3 p9 p  p0 d: K( b, Y5 D; ]8 V6 u  D
    代码实现
    6 o) [# i( z' M1 L6 n& Q+ ?  |' U% `4 P. o: f' s
    void MergeSortNonR(int* arr, int sz)
    ) [' O/ V# o# J8 Z: ?4 L1 n{
    " [7 l/ ^7 r& E) ?6 l8 M. C" w. W    assert(arr);
    . `& H3 Q( i8 c" ~; J* P
    + K" W' Z6 _- a# C! e& }" L    int* tmp = (int*)malloc(sz * sizeof(int));  D+ W- z" E3 H- j" n" }; u/ c
        if (tmp == NULL)
    & H0 V  K- m2 b  H    {; h% [% V. I. ?) m) P8 T
            perror("malloc fail");
    8 @' K4 a: X2 p5 r. u5 ]7 y. j        return;
      C3 A$ N  q! z$ A  F# c1 n' S    }- _; o) u; H$ ]" \3 I& P

    7 d" A' n9 A. `* R9 e    int gap = 1;0 }5 p/ x: m* O
        while (gap < sz)
    + e+ H! ?( U1 a8 U) f+ s    {
    / ?  O8 X4 ?  _        for (int i = 0; i < sz; i += 2 * gap)& z7 }8 p3 G5 y& M
            {, H1 U, H8 w& E) {0 y
                int begin1 = i, end1 = begin1 + gap - 1;
    + D9 G8 l4 ~1 q            int begin2 = end1 + 1, end2 = begin2 + gap - 1;! c5 d' I" b1 |+ d# i
                int j = begin1;2 z2 i; \8 d: w: b
                            //越界检测$ U( u/ U7 Y: H8 l. @: y& \
                if (begin2 >= sz && end2 >= sz)2 p& z7 w: N7 p' h/ _
                    break;0 [' X" D! p6 a
                if (end2 >= sz); m; L- Y9 |9 V  w4 [0 D! X9 |
                    end2 = sz - 1;& ^! h5 e8 |) K+ Z5 @/ C3 X" V
                //归并
    1 H9 ^3 t+ e: d            while (begin1 <= end1 && begin2 <= end2)
    : R5 @! |4 {6 J6 [  X            {
    3 \# x2 d+ B% s9 b* J                if (arr[begin1] < arr[begin2])' S& j/ E$ l, b. p6 {! h' e' o
                        tmp[j++] = arr[begin1++];/ b' Z+ @6 Y( X' `  ~. _
                    else     
    + f/ T* z  k! X" C: W6 t) ]                    tmp[j++] = arr[begin2++];
    4 s6 G2 W" E) m6 c7 J* H; g            }
    ! {0 l! ?  z* h, g$ G8 B4 |9 v7 S. ?: U* M/ t3 K$ {
                while (begin1 <= end1)/ p5 @- F: H' g
                    tmp[j++] = arr[begin1++];( i0 j9 e2 K! ?( A, w$ f
                while (begin2 <= end2)
    & ?2 Z, G9 ?: G0 {) v+ O                tmp[j++] = arr[begin2++];
    / d) c* a: e8 b5 `8 E( g
    6 Q, Y4 g& T! ]& d' Q' e7 L            //拷贝回原数组——归并哪部分就拷贝哪部分回去. g! c) d& d& P9 n- O6 \) r
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    # f1 _- Q; M" {* M1 Y        }& C$ K$ B: G- E6 V% ^
            gap *= 2;/ z# X- r& z+ {1 O# ~
        }
    " t: w" E" j7 o; s9 @/ B  u: |( h  {, z/ W% j" ~1 L
    }
    - ~. U( q3 H0 d% }! j/ {0 K9 s/ O
    1. `- k  s. n, B+ k: o# N3 ?& l* B
    2% `& h- A/ @+ x3 X% O2 m
    3
    4 g5 E! c' ^1 ?4 X+ \* l' E9 A4
    - A5 O; v$ z' n. g0 w5
    ) ^7 b( S) |: F* c1 R' M9 {6
    , }( B3 t8 H  W3 s& J4 a7
    , ^& U; R) s9 A8
    , ?, Q$ k3 a" G. |' O# P. \9& E% O! \  N- W2 l# U0 P
    10: ]& J$ L+ M" t/ ]! L' Y
    11
    ; Z. v2 V# `+ @! X6 ]12
    ; Q4 H% l6 M! D. [13, B* i) W3 n& e. O* I. f
    14/ X1 w+ W0 _" ~4 m) j
    15
    3 r5 b' \  _- L3 u16$ n0 Y, C' B5 g! M2 s
    178 C% _* z7 A! \1 Y+ L- W0 {  I
    186 g$ L" ]9 a6 n% C" @4 b
    19
    ; w7 O! S5 J: A20- a5 L% p& J, o' s: u
    21
    - U" B1 q2 _) U226 e; n. s0 p6 U7 a3 ^/ s
    237 W$ x$ c' i( z% ]2 D
    24
    ( @) W' e" ^8 |# F2 J8 s25
    1 E1 c5 P3 c3 I0 H26
    ( E' g3 E* E9 z( _# u2 D" \+ i. ~" i27
    % C! D3 T& v* o( z0 O280 Q& ]" G. V- O+ d
    29+ g3 D* k) \- S1 R7 g
    30
    ; L$ a. b7 }! E31# f; \* |- k% [9 m! A
    32
    ! o* F; G# H/ d) _6 o# G4 l33
    % Y: H$ P9 t1 P( Y: M. D. s34
    9 V1 v8 r1 a; w) `- W35
    5 O8 {$ K+ ~3 R; K* j! c, ?- g6 N36
    - _4 U  u' H* U, ?7 |2 S  W37, ~. b2 N8 C! {' z5 }
    38
    7 h! X; m3 |' }4 O+ T: Y39
    4 f2 B5 `" u& {; f40# c- m2 O8 r4 s; a2 V
    41# L* ~  g1 n: o; b
    421 I9 E8 I  R6 L. f/ n
    43
    % D5 q2 S" {/ E9 P+ P; k; ^, A8 I44
    - Q$ c2 Y6 Z* T" s& O45
    0 e  ?6 Q7 k- k5 z# h# {! r& _, ~) X归并排序的特性总结:% d" k5 g1 \' L$ N: @0 b% m$ n

    - a4 \) `' V! ~2 Q归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。: O' D$ Q! r! T. p: u8 v
    时间复杂度:O(N*logN): F6 k. i; q9 E/ e. y1 G$ W
    空间复杂度:O(N)# i$ J5 m3 a* O  Z
    稳定性:稳定8 D4 ~8 F& d  Q8 H0 w/ i
    " Z2 Q4 @3 E9 A0 j
    ————————————————6 i5 E# L7 Y6 d5 g* D7 a4 k$ o8 L* ^1 |
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。7 V3 m+ u" R/ W) N& {
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657- o7 e. s1 y* I
    9 |8 M1 K2 d2 d8 s. }2 e$ H% c4 [

    0 R( d. c* ~7 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-4-23 00:03 , Processed in 1.040182 second(s), 51 queries .

    回顶部