QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3390|回复: 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的排序算法】归并排序; l4 Y3 g9 k1 |6 ~) L
    : M- W' q; S1 u" A- I: ^+ J
    前言
    ! [! R" O* L  T9 K  P本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    ; L& u2 N( Q' B/ |* B/ A8 J  z/ g, e3 `: p. z- }+ H1 {% G
    归并排序$ V, a) f) Y% P$ ^+ E2 ~2 ?9 V
    基本思想, e' K1 D. |# ^. f7 a' U; A/ S
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ) U. D) P- X/ Q4 Y* |9 g* t! |) v% C; E3 Y% d9 n/ \+ _- ]% Q

    ) M' D9 c- o! b
    8 P) M5 ~+ ]: g& n& D( [' L​ 合并的思想其实和有道题目的思想如出一辙:
    ' i6 F( P6 n& V3 j" N
    0 S' x2 k2 g1 a9 w  q  W* h5 L
    8 @3 R. i# M4 n/ M
    % K; Y4 I6 B$ [  I" {$ u​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。4 o: s: Z3 ~0 M; A/ q
    . t- |2 }/ G. h
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    ) s3 w7 A4 s# [/ V+ m( e7 y$ o; g5 p& Y2 ~+ m2 a1 s
    int* merge(int* nums1, int m, int* nums2, int n)
    5 c8 u; [, _: I& a2 A* k1 y{
    1 W1 W0 y$ D5 e9 P$ c        int* arr = (int*)malloc((m + n));6 a# X- F/ Y7 ?8 Q. L
        if(arr == NULL)
    8 y0 V' \( b. w- [( a    {( K6 N5 p' P, ~7 D
            perror("malloc fail");* h. Q; \3 V% m! O; j1 l2 _/ B
            return;2 @' v3 I/ w. O1 X
        }
    1 O( t, b8 m6 X9 C; q- F3 m
    7 \2 R4 a# s" w    int p1 = 0;
    & R* P  L$ \- B  Z; b    int p2 = 0;% K! S) P3 t! [7 }7 a
        int cnt = 0;! G7 `; c. d: j8 ?# Q  j
        while(p1 < m && p2 < n)* M& N1 j% |" u) ~( v( k
        {* z$ w; c5 k' _9 G6 B
            if(nums1[p1] < nums2[p2])
    ; o& |* C( E! l8 T* \        {
    & G) H5 x) U! ~& Z0 Q" Y' K8 f: a' d            arr[cnt++] = nums1[p1++];' ?& a- w+ y% j4 E0 z5 E' W/ j
            }/ f" I  n* |$ I% T
            else% q% i; t1 u! P8 d
            {
    . E3 y1 G6 r8 [1 l6 E            arr[cnt++] = nums2[p2++];, C$ h+ `4 z! [
            }3 Y( H/ d" e1 g% @
        }: X& p: L) O9 x8 q. S& Z9 w
        while(p1 < m)
    ) h& q' ^% ?. t        arr[cnt++] = nums1[p1++];
    ! t: _7 f- ?/ o+ R* v
    * e) J) g- V4 o% u# P  B    while(p2 < n)6 X; H# R- j5 H. ]  u
            arr[cnt++] = nums2[p2++];3 e3 Z5 T5 {: l0 w# }

    % Z6 q: v" h5 j7 y( u. I: @    return arr;
    3 J  L5 p5 o/ z- q" T}
    ( _- |! S, B" K: f; K- @
    : I- P9 m/ @+ g5 d( J/ I1 Q1
    0 `( d9 f7 }3 v3 n9 i) [& g7 R21 b& y& e$ Y# C" N; F
    3) R0 F) K% a* f- ?0 G0 ?2 k6 B
    46 P1 |) i3 M% a) n  A: C( ]
    5
    + U6 D( p, z. @- s6 ~6$ X9 v& h" c" B1 N& S. E
    7* i2 Y/ _! d* o0 T3 C! D- u8 K
    87 {' [$ w4 }6 }2 {. P* z
    9( d) D1 ~# u6 L4 v* ?% R3 Q4 \
    10$ }# I9 e+ ?) p: Q4 G
    11/ Z# U) U2 B# T5 Y
    12* a) t2 C1 F) E) N' u
    13
      L5 w3 a9 ~& a( S: F- T; w, i* b14
    . S( z! e4 c# \0 K158 `7 G5 ^6 L# ]3 U8 ~; c' z* O
    16  o9 K1 J% D% R; x% |; R' O
    17  n  W! P( n" s
    189 d6 y/ T$ M! p' _$ d4 E
    19
    * c1 u3 i  v" `( v' g/ }1 {+ @205 x/ `$ h2 ^0 f
    21
    8 V: R% c  Q' G* t5 F22
    % x0 B( R# w# M+ r8 N  _" e! J9 I233 O) Q& n. h: f5 ]2 t5 P( t$ q
    24
    " u; b/ O9 m: U7 Q# U25
    0 ~$ P6 x# L& J0 ^26
    ' B  \) w4 b4 ?9 M- i. v  X27
    , \. L& H3 B: P" `7 N, z: ~28
    . J9 F6 g8 _7 T# V29! y8 z7 F+ [" Y7 Y3 R; @1 a
    30+ K0 n" C/ q0 `" C/ G
    31
    4 B" [, R" m/ j3 I5 i- ~; ~3 @' W​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    $ q- P. G: W) G8 C3 f  U! m6 b- ^' P3 {3 K; s% X- z8 C0 E7 u/ N* K1 k, j2 W
    递归实现" j4 L: ]6 {3 K+ S3 `& c, A* W' ~
    ​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。5 u0 j7 b9 k1 |  [8 S' S; W
    3 h  c) b/ _$ |" r: n. u

    6 d- ~$ w+ I0 i7 s8 n, g2 M1 V. N  h: J+ g" {2 P$ \

    & \  \5 R/ C+ g
    & w9 d  G' V$ P/ rvoid _MergeSort(int* arr, int* tmp, int left, int right)
    # y( ^9 Z, s1 l, ~, e7 A5 I3 O{4 M9 y9 A) z, r/ G5 f
        assert(arr);# y! z/ o9 L! `  F4 f8 |

      t7 p8 }. _1 |+ ~6 A8 ^    if (left >= right)//递归结束条件不要漏了) u+ J# ~; b- \/ @! f- {4 C
            return;( `( z9 |# E8 U, C  D+ P
    4 d+ j% p+ M) h( C9 W
        int mid = (right - left) / 2 + left;5 z9 b) s7 x! A3 w1 F6 \9 J

    8 I0 m& g5 e' K& X5 J3 G( w    //划分左右子区间[left, mid]和[mid + 1, right]
    " P4 T2 ^# v) b( H. V" E9 T    _MergeSort(arr, tmp, left, mid);
    3 N, I0 u% F. S5 W# h: n7 G    _MergeSort(arr, tmp, mid + 1, right);" C: c7 r7 e# _( R# e5 Y0 e1 n
    : ]8 U- o! C$ P) |7 `8 T" I5 @) [) ?
        //归并
      o+ w: G8 B; M( G5 w    int begin1 = left, end1 = mid;# a) V" P; n$ L8 W
        int begin2 = mid + 1, end2 = right;
    - b7 k$ P1 {( s5 Z1 S    int i = left;
    ( p( k2 O+ N0 N+ \( l    while (begin1 <= end1 && begin2 <= end2)" h+ Q, ~, s) ~* E
        {* {: W6 n) w6 c( r, w+ ^& ~) F, G
            if (arr[begin1] < arr[begin2])
    ; F5 q0 Z  u5 d2 s+ a            tmp[i++] = arr[begin1++];3 R0 V# n; y6 R6 \3 j8 S% C" b9 j
            else
    3 h9 [1 u( T2 X9 k1 M& T: B2 \            tmp[i++] = arr[begin2++];
    2 P, U; M9 O9 B/ J    }# x% Y% _( f% c, B& B

    , z: v# a8 J7 |- g* g    while (begin1 <= end1)+ S: M7 S" F4 b9 Q% c5 a, J( |2 r4 b3 i: [; ?
            tmp[i++] = arr[begin1++];
    6 L. M8 Y$ o' \6 m2 H9 z8 _& `5 B1 s    while (begin2 <= end2)
    - e! s* R' @8 d; S& N! E0 N        tmp[i++] = arr[begin2++];1 T, r. c! N  c* q/ R3 B5 D  w; e* H
           
    8 c3 z7 e8 x% t# O1 ?    //拷贝回原数组——归并哪部分就拷贝哪部分回去8 V9 ~! _* k: f
        //而不是拷贝整个数组回去
    4 G4 F, m1 p& d( U% `    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    ( i7 m: ^, \0 S+ ], x6 D+ K}2 E/ f, r: H# @6 u& c
    ; ?# g8 B* x* N0 r2 @
    void MergeSort(int* arr, int left, int right)
    , i/ G& m/ P7 {" i# ~' N{, z2 ^: K' k, M6 p  H" z5 L
        assert(arr);/ @3 h# d# |. s* M7 u
    4 h% l/ w4 b. W8 a6 U' S" j" k
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    7 B; \- k) L' i* A: d% P    if (tmp == NULL)
    ; r  V: v3 ^6 Q    {
    - A* t6 g  w  C  L& _% h        perror("malloc fail");
    $ a: q7 R9 Z. @        return;8 k9 {! ~5 y; F" y( Q3 w+ v
        }9 M' a- N- F8 X

    " h1 ]" _% @& q( g    _MergeSort(arr, tmp, left, right);
    3 E8 a3 A! J$ p5 ^0 U  O1 J9 F/ P+ b" w2 z& L4 {% V% X
        free(tmp);* s9 @3 I1 Y9 X$ B% E
        tmp = NULL;
    ! P0 V' L* ^) W1 v7 @}% A+ H: m% Q' Q6 @" C3 e" w, q+ G
    1 z' A0 F: C; A6 W! d; u; {5 A1 g) g
    16 l" t6 D1 k5 o+ I! P6 T8 c
    2$ E3 h8 D  @4 q
    3( S4 `0 t3 q  N2 Y4 v
    4
    : ?! b' s; C" j5. d" \2 ?2 u3 j9 ]0 `
    6
    ( m" v/ V# L$ H: s3 ~/ K" [7; k+ l# K. J$ L6 {9 U. p( R
    8
    ; X( s& h$ f, O, P* V4 o9: u2 l( l: G0 o  ]3 B" V
    10( j6 |) i! X8 K  q" W# l5 Z1 B
    11
      O$ P$ B! \2 U' g( p, J126 L9 V. |8 u7 Y5 N/ N  P0 k, M
    13
    : ~4 f1 c6 M4 ]" W# c14
    ; A% n; K; {+ h1 i15* T; G% C7 ?! t1 D/ {8 l
    16* e2 b+ j& `* v9 V. n0 a
    17
    4 M3 d, J2 B$ \, U2 U0 t1 p18) o+ C0 @0 X6 N* W
    19- c' l$ h( j$ y& t) H
    20
    . E  `3 C& j! ]* u; _: O21+ J- W3 h  l3 f, f$ Y3 u0 J' g" j4 r
    22/ S, G) V6 d& e0 t" O9 j
    23
    7 p# U# l& E4 \0 U& H8 L) d24
    . p; U% z. c0 t4 X9 ~255 U- E6 a# h! |( x* P
    26
    # Y" Y) R+ B' L* E27
    ; Y# y/ [, N. t( [, f28& [  d+ R; r- v  S: v
    29
    7 I/ y) [- N# S6 b& a6 ]30* X% h$ k) F. @) A4 o# K
    317 Z8 Z) K  b- o& e* l( ~
    327 k$ R$ y9 L1 A0 y
    334 U/ }" n8 v" R- \3 u* Z
    34, ]' C' O* A8 j( K) n
    35
    9 @5 Q3 w% @+ M1 u; ?  r36
    ! N$ @2 w7 W/ I37
    1 ?0 U% _/ D3 ]+ I38
    ! y, T9 j& I+ P. r3 Z7 O39
    ) B( b( \  L; `* F2 |+ i" |' S40) @' }4 N6 v( Y8 T# `4 I
    411 B* h% r2 Q3 v' O* I$ z) P
    421 J1 O. Q. }, ^3 H0 o5 A
    43
    & x8 l: V1 w/ p- o4 F44. t3 }4 B* x4 O) v
    458 U7 S1 V/ j/ }+ L+ h
    46' T& g. m/ e# E5 w0 M1 e
    47% T& a8 E. }" C
    48
    3 r' d9 f5 H! N0 ^" k) B49
    0 ?/ B+ [! S! x& L1 K8 T+ g* N/ j: b50* w+ s" u. R% q- d4 K1 [
    51
    - D. |0 c$ _6 U7 s! c' x非递归实现
    : G( U* P1 r7 r( B' v​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。: T( Z- Z% n# j4 B2 @, A4 ]* G% Q+ D
    6 }; x- `; o) j

    ( P1 {) g- g' v& I. N$ T
    : S& u, O/ l$ \. f: q3 X0 n​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。( P; C/ h4 i2 m) c+ b) ^

    * g2 h6 B; G4 Z3 G3 m( v, |0 N​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。  `) w7 n3 E1 s
    + w& C( _) J& Z$ W6 |2 m
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
      m( o4 l! j( p: L8 V6 _2 ?
    - G0 t1 S. k7 u0 \4 [' E) G代码实现# F, A6 m2 y: ~9 q9 n% `% S, j( h0 ^* g
    8 K, k) F  ?$ m# {" j( q
    void MergeSortNonR(int* arr, int sz)+ a9 B$ g. f+ h! G, d
    {3 k* g' P; Y7 M4 |$ g
        assert(arr);9 H$ b1 X) k& p- ^& H0 j
    + W; X$ \" V8 q, A6 y
        int* tmp = (int*)malloc(sz * sizeof(int));6 ]7 a# n" N+ H: d, p, [. Q" ~' ~
        if (tmp == NULL)
    & e- z4 U, K+ u% j" E5 t" u    {
    - z) J8 P% u" y4 ^+ R2 X        perror("malloc fail");
    0 D  {8 n" G" [1 \4 g        return;7 f6 `8 A$ A. e
        }
    4 R3 ~/ w% r  ]0 f- f1 T3 h
    , \$ O6 m: p/ E% @' g3 N% H3 C    int gap = 1;
    ' x6 c: t% z0 w# J    while (gap < sz)
    2 h3 o/ T- Q- e- {7 ^2 q    {
    " f3 g" c+ s  z0 C, P        for (int i = 0; i < sz; i += 2 * gap)
      {8 u0 B, F6 e0 t        {# F. R7 |$ X/ m, D
                int begin1 = i, end1 = begin1 + gap - 1;' d& d: ~0 W0 x6 P
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;5 @2 J1 ?1 g+ l8 S
                int j = begin1;
    7 n0 d" G/ c' U: i* F6 _6 d
      ?7 e9 t  l. A/ a            //归并& i3 j5 O" B9 `3 B( Y
                while (begin1 <= end1 && begin2 <= end2). X4 F3 g1 A& m" B
                {
    : d# ~2 x. K) F. S" T& t6 Y8 t+ e                if (arr[begin1] < arr[begin2])
    " |2 Y# v4 G% ?: G4 x. y                    tmp[j++] = arr[begin1++];
    $ q; {/ Z& f3 N3 F  D                else     ; r# [- m; U% V1 X9 G! S; i1 A
                        tmp[j++] = arr[begin2++];! x" X, a9 G" \* g. m. @( P2 e
                }% u" T6 b( b9 v5 |" m3 Z: ]5 s

    4 Y: Q: k+ c+ j* o            while (begin1 <= end1)3 S: I3 _0 O5 L5 ?# B( X
                    tmp[j++] = arr[begin1++];; L$ `& ?- \+ A8 Z$ e
                while (begin2 <= end2)% D" \9 ]  M/ ~. `3 U0 h
                    tmp[j++] = arr[begin2++];2 G. h7 ^' Z% K; j$ N2 e

    : {! X4 m  H: n  z            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    + u* a( l$ X. K0 ]* G; U: `            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    7 y3 z6 G  U& v6 N, A        }
    ! ?* u$ p7 e) Z' M9 x4 A7 O7 e        gap *= 2;) e+ ^7 f  r5 u, U# R4 e) D; s
        }- k7 g$ n) ~/ Q  I" d% n
    1 P8 `% o' b0 j) S1 U( l8 R' _: o- S* `
    }0 A& D! b# i, l/ Q8 I4 |
    3 Q, M) ?/ C' b- d  M% _5 t
    1) T8 i2 h* `% r; J
    2
    $ e4 |6 [7 L" M$ G/ F, r3
    ; D5 Q7 |: |9 _4 {4
    2 G/ h5 @2 m" _: D$ @& D5, Y& s; @" d/ C/ T- g
    6/ E  m* E! h. A
    79 q1 R7 |. M" W% u0 q
    8# E% L# \( [- A
    9
    8 j. X6 h: W  I109 D4 Y! n4 l6 J2 k; y, n# `% ?
    11  Y1 o: w6 W1 l
    128 f) `% b6 H8 N8 ^; R2 y
    13
    ( U+ J. Y3 H& n6 x14; U( L2 t8 V5 Y
    159 s0 _$ ?" E' T6 P9 E8 z
    16
    6 Z% o. t- U( M17
    6 d: J" C3 M2 x' z% M2 C7 ~18
    6 b& z  J0 C0 X* N, J; Z  l1 O19
    ( f4 R- K3 R& H9 |20
    1 p+ ]( r* t3 m7 D9 d7 V: U; _21
    , t' @5 y3 i2 M! O# d22
    6 }3 X2 X  L  g6 N23
    ! ?5 `% A! @' q; ~24
    $ P4 x. ?. c5 ~" B) p/ j25
    # P4 X% N1 X; y% T8 r26
    1 E% |4 i" {2 [) u27
    1 u5 e/ |1 q( A4 {* J28
    " x" b# O4 R$ V& e* {* N29" V; H4 U% p+ x5 s0 |$ X
    30) [6 e% k7 [% a- g
    31! Q& w$ Y4 N4 O
    32
    4 A4 e  X* e/ f33
    # s6 X  m6 w' B' z) V34. {" u5 [5 ~8 m: _8 B
    358 c; O/ y: o. P  ]
    36' T# T" e% T' d; X2 Y
    37
    9 k6 v. l" M: d& a2 _& l$ Z3 U38
    . k0 Y/ q4 l( M  ?- w7 e$ N393 k: v, r, g& Q& a; }
    40
    1 Y1 [9 S2 C: i41- }) F* O: T, M) k+ k7 o
    边界问题& n3 h4 O9 C9 R! H: r* }* U( C
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。% i/ s( n- X( C% b* s  D7 |, {! M
    , x+ @( H2 U; B- U/ P' ]5 F& Y
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:5 Q- {( b' e: n
    7 p) r3 E5 I2 g5 [8 o

    * Q' G1 d2 a6 B+ }0 u! T" N' F
    ) a  s9 f! _9 y1 X8 w9 w由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)! u9 r  Z; m$ c

    2 Q4 j+ k8 M. ^9 N第一组越界(即end1越界): B! K0 v0 j" e/ U
    3 n  K( J( k$ z1 n7 o; [
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。" f6 o7 X5 ?; y  Q6 w
    + _# P( C8 h  T& h) o& U6 m# D# [5 u
    第二组全部越界(即begin2和end2越界)1 x! w' b* j  d  t3 U1 t0 [, C. o

    : D# A+ c/ h( K8 _应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    6 P  v3 m7 S' C3 b! S
    ! _- P) X5 N* i9 x5 j第二组部分越界(即end2越界). J; d1 s% A6 E) N+ g; M" O8 T

    " Y+ A- j' K* r" o9 |0 N  |4 m; C: t应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。4 U9 A( E/ o4 Q, u; Z5 G2 ~+ k, X: \' a

    ; M7 R9 x* Z9 c7 I7 D9 K( E$ `( ?​ 其实第一种情况和第二种情况可以合并为一种情况,原因:4 D0 k1 e! H9 e6 F
    : r9 t# g/ e% x1 x0 A
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。4 |& J% d1 S: u! h4 u" `

    9 [0 n) `  D% I% A​ 拿两个数组试一下:- ~; z: a4 W- k& [" _

    , ?% e# j/ S8 H1 C1 F& n' a' s6 _. h* k! Z
    + m/ b9 B& S+ Y/ e- z; C! S2 y' _
    / I! B; N  D( H) w; }- I+ H
    3 U" \/ k- Z# J+ V+ T- i" H' H3 _
    代码实现) i7 z! k6 H) {0 ?
    ! e( n! g  d7 e  n8 D
    void MergeSortNonR(int* arr, int sz)+ C, h: P1 D7 u
    {
    6 {- c& W+ v9 o0 u; k4 o    assert(arr);
    5 N& D, C" p- i8 L( t% U& V( v; Z7 p) [' i2 _( o
        int* tmp = (int*)malloc(sz * sizeof(int));
    # t# w4 l7 o) N$ G1 q* Q! z" E7 ?    if (tmp == NULL)
    ) l6 u% x1 R+ U9 ]0 }    {! L) h4 g! N7 [* t* Y% P) L( J
            perror("malloc fail");; ~: x( u" S) ]9 d! I8 D
            return;
    - |4 z; H7 \1 z( l    }
    ( O/ |( d7 t- e0 A
    9 T# n) h# `6 t  g& t    int gap = 1;
    1 D, b( k" ~; W( U    while (gap < sz)
    % M( R' _" \4 e6 F, h# l    {
    - h$ h& R* x* d! I; K        for (int i = 0; i < sz; i += 2 * gap)  q( J0 p) L+ P8 Z% |
            {6 j, x2 Z9 o; B  c1 F
                int begin1 = i, end1 = begin1 + gap - 1;9 s' V# X0 ?1 L# A% t$ {/ c/ q
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;  w+ s& t% }$ t# L" H
                int j = begin1;
    * c0 |" J  V6 ?4 H$ V& v9 Z                        //越界检测' M' v# G% F0 l/ `/ d! a8 f; L7 X
                if (begin2 >= sz && end2 >= sz)
    5 a% H9 _* d: s) o                break;
    $ f; B, r% m0 l7 b; |            if (end2 >= sz); `4 T0 ], g8 x9 k6 `% f0 K
                    end2 = sz - 1;
    $ a- b0 x& W! I2 C5 i8 S+ }- H5 q& S            //归并8 r$ v* l" o2 h9 L. ^  T
                while (begin1 <= end1 && begin2 <= end2); ~6 s1 T" a9 m$ x8 r" `( L
                {
    8 _9 E9 b- T( m3 l                if (arr[begin1] < arr[begin2])
    ( P  U3 |( ^5 a: b" T6 w                    tmp[j++] = arr[begin1++];
    8 O0 a; O, [; e                else     
    / p* b' u, [" h1 ]  b                    tmp[j++] = arr[begin2++];
    ) {6 H3 [3 Z! `' l9 t            }: ^# G" c& y+ t

    9 l+ ]; ~  @# R' ^* F  W. }            while (begin1 <= end1)8 g& G! Z5 N  ~" w! T
                    tmp[j++] = arr[begin1++];9 l1 m% _+ q- X% I& k4 ^% s& l5 o4 T
                while (begin2 <= end2)
    6 X  r+ @% i: t4 ]3 h3 _7 s  K2 ?8 u, q                tmp[j++] = arr[begin2++];
    + E/ B4 S: Z: a1 K% @% G5 c4 h/ ]$ ?! f$ E) w" G- }
                //拷贝回原数组——归并哪部分就拷贝哪部分回去: p* z; V# c* W) s
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));1 v5 G0 ?* l& U8 i/ ?$ n8 z9 a
            }
    & a1 I2 R& K2 r        gap *= 2;
    1 v% D7 s9 V* F- T, h; E' A; a    }, T5 C: f: m3 U( L# j8 |4 T

    + S. f6 e& a% h- S8 e8 Q}% {9 ~. c8 s9 [6 h. h

    ' e; }" m, |4 C7 L# ^% O( K1" B) o; ], F( a% z1 j
    2& b  F" X5 D5 i6 a% V; p$ ?
    3
    6 K' Q' f/ w$ C5 D2 I) q2 ~4( P9 z6 w! Q7 X0 q8 l/ Z% e0 U4 \
    5. t8 h! H% d! y2 @, c
    6
    0 c2 ]0 n; t' r7 D  l2 a' l4 Y7
    9 u4 ]4 f' C' m3 e, ^8
    , {# D0 _! M& ^4 S; n; O/ F90 c. F2 X5 y  X: r
    10
    * d# R) Y0 e% y7 ^: C118 p* l0 W8 C$ J  M% h, @+ J6 L* _
    125 G& K, B8 T% k* \# X
    133 q3 F1 D9 g; t4 i$ J: P) \1 f3 b, H6 n
    14
    4 I, \2 K( |7 z, U- R: M1 Y. g154 h; k  m0 W% G
    16
    2 y7 e0 Q# P/ |* q/ s9 v17; K7 E& Y, _( H# |
    183 Q& D3 R" i! {& A0 `
    19
    2 m" }7 b  v/ Q6 }1 H( S20
    * y; K0 m5 m- v6 f& [21
    ; b( A0 A9 b" d. {! z0 \22! L8 F9 ~0 |0 G1 ^$ @# |
    23
    # W! y4 f) Z& {24
    0 `  i+ ~+ p1 h2 K, g25
    # B$ \) b& i3 r* T( X262 e% t" ]. V2 |+ c: S- x* C
    27
    1 g1 m5 y: [5 K) Y! k. A( {28
    4 p0 i5 I. P& J( N& E+ o2 \29( L, T! o6 |2 }/ g7 l8 @
    30
    ' R& @/ Q' m. L$ S' h4 @! J$ \31, n, S' U& e5 Q* _
    32
    % F3 ?+ C3 k& e7 e2 J7 n. i1 U33/ _: B. o  E1 }4 C
    34* s& Q) \! R* l/ a+ n9 [: @
    35
    - ?. z* K( S' d& P; b- o# \36
    + }! _3 ]1 K7 L+ j% }: T8 C37
    6 c/ S1 F/ D! j+ a' f38
    , ^5 ^# S* A! P, q' P* f& h$ X39
    + W! Q0 y6 E' m! p% ?40
    6 l3 W+ V6 [) V41% h# O" L& f2 y( y- ~
    42
    0 C4 b6 S3 V" T, x% p) w& V9 Z8 U8 r43
    # s; i0 M" V- c9 p) z/ J' z44
    , A" u* n8 ~: O. f7 `45
    6 I3 z$ O/ Y: V1 I( {6 l3 f; r归并排序的特性总结:
    ( y/ N$ ^( F" C  I" w8 q: q  ]0 }6 }* Y5 F+ u8 ^" ^3 c
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
      }5 y$ v' K. v1 g0 f8 Z时间复杂度:O(N*logN)
    4 b1 J+ `- u( S0 W- N4 K9 Y- A空间复杂度:O(N)$ E" H1 `/ L5 m6 f
    稳定性:稳定8 Q6 e' ?' h. Z9 K

    6 d# y3 d; D0 X————————————————, I9 B( N+ S  W, p3 E, |* V, v
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。: M4 O  y4 W! k
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657, |4 K8 H# N& Y. _
    ( b3 J3 v. K0 B1 }* j8 P% b8 V

    9 X: Z( \& a  ?& ?
    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-10-8 10:32 , Processed in 1.199273 second(s), 51 queries .

    回顶部