QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3392|回复: 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的排序算法】归并排序7 U; {4 i( q! E5 a8 E, Q
    2 @" X2 E" B; e5 C7 S% N  A7 u
    前言" V0 v# y1 ]7 W, b9 ~0 w% k$ L
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。  Y& P! y+ [) f4 }3 [

    6 C9 P2 o+ I7 z$ M& M& ]+ H归并排序4 X( x7 q& s/ }7 J% ]9 Y
    基本思想: u9 R/ K. z$ V7 x1 p9 B& T
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。* y3 P# S* V& `5 {

    1 x( z. A) I- A  v; k2 V4 H7 F- z; h2 O7 a) @' C
    ) N$ ]5 ~3 ~7 @. c: z" ?6 ~
    ​ 合并的思想其实和有道题目的思想如出一辙:' a7 T( }0 b6 l; C6 Y0 r

    & f$ B, d0 n5 j8 z/ s; O: x% ~) X+ W; X* f4 n- P( V

    6 l7 l3 X- D' u7 N! N& {​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。1 P! }1 T- D( ]% R3 m- R

    " X. C/ x  I: u" P: s& J, F[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    ' o# P+ s: @+ z: M5 e9 |4 K" V$ _3 O- \+ t7 Y$ r* K6 {
    int* merge(int* nums1, int m, int* nums2, int n)  ^5 B" h! e4 b& R6 u( n# e
    {3 \$ q: C7 c" B
            int* arr = (int*)malloc((m + n));- r, k1 A* |" z8 P) ?6 O4 s' A& ]3 m
        if(arr == NULL)
    9 P) Y4 D2 t% K) Z3 P  d( T, {0 Y    {
    $ U5 p# P% O. ]0 F& O' y        perror("malloc fail");
    & a, B" N! D9 h% j. a7 h5 G        return;* Q4 h$ s1 U* B# K2 A$ U8 B
        }. F: ]& U- r1 x% k3 p$ R
    7 z0 J4 h, k4 e
        int p1 = 0;  x6 e  s6 O; `  V: R% C% V
        int p2 = 0;6 n6 Q* x+ v" d) U! O
        int cnt = 0;7 [/ D, P* q7 S/ k- `, o& G, c
        while(p1 < m && p2 < n)
    ! W5 G( s$ a5 f    {
    5 W0 z& w: i7 I; X; w        if(nums1[p1] < nums2[p2])
    ) n0 D: O' E1 I# K8 Q& j; L        {
    6 \1 B# y6 J" c7 [            arr[cnt++] = nums1[p1++];
      N1 Z$ u! a- x1 Z5 m# e& f        }
    2 q9 @+ C) ^+ k3 ]; d3 d" o        else
    2 j. q2 Y+ _9 a" ~        {
    9 f5 _# ?+ L6 H2 ~" l; b( A            arr[cnt++] = nums2[p2++];. N& t. _  o8 |7 z  U
            }
    5 X1 B, G: M5 Q7 }5 u) N6 {2 }$ l    }* f  s/ I" P- {- L2 z' Y4 O7 ~, h
        while(p1 < m)
    - s8 l* n/ ]% c( L+ L- q4 [: C& I        arr[cnt++] = nums1[p1++];
    0 e  b- _: C$ T8 s/ B6 B; ]2 c' ?2 P$ P
        while(p2 < n)" K3 Z, R- l8 a! P+ s1 Z
            arr[cnt++] = nums2[p2++];+ `) @9 G4 z; S4 Q& x7 f1 L- ^# D
    5 t, F- c$ B$ n, t
        return arr;$ n$ Q8 A- c  D, Q9 U
    }
    * {; F2 k( ?0 a4 h. q0 p0 y3 X( o' N' [0 n: U! ~/ a
    1
    7 o0 G8 b; }9 X2
    : F: U# G3 ^6 P! J3% d7 H9 f& Y3 A5 h/ b& C6 m
    4! P4 ]- s! M# T2 _+ D
    5
    . B1 Q  k7 @8 T# K8 i. M6 p. |# M63 n3 ?. P& g3 V% Y
    7
    2 f& |9 V1 g8 g8, L2 ~5 F9 I, M
    9/ Q9 B# J3 W1 T0 A; B+ O2 v: ^
    10
    2 y! w% k4 o, V( e* y4 m% e- B11( H1 U% w0 m, M, ?" E
    124 N+ q0 e/ g- D) ?7 @
    13) L  t2 _# h) h' ^- H$ i
    143 _# J6 C4 j1 n+ O% c$ s
    15: p: J$ \! g) Z; k& M3 |
    16. i! S) C9 J  _: B- c5 b& i
    17
    ( [6 N) x* f5 w/ Q/ i( T187 Z/ a) [( M( K
    19. d" n2 F: ~3 `) A0 _+ K
    202 L) O: e8 Q7 J( ]& _
    212 W1 Q+ X. \# c9 d/ V; ?0 l7 f; V
    22
    7 f/ ]  e1 ~' X, |/ Q. D23
    8 Y5 l9 i) {- h2 v$ R# W248 E! `) Q' J4 N: ?9 u
    25
    2 e. j9 F' u+ @" G8 y# i" K) u26% E5 _$ P  J" g
    279 l( G, s0 K* m: q* h( a
    281 @4 x/ D9 k* `
    292 l3 P; w$ P8 C# w; j
    30
      q  {/ ^; X* H. X  r, E2 I' U31% G# Q2 V; i7 W3 g+ j0 N
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    5 S. m" n" F! i7 W, g' c  z/ J9 M$ c
    递归实现
    + g  P) Z+ `- g& [- a# T$ D​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。: q2 P  w; s& v; o: G1 o$ b# x
    # m4 ~- z" E! A+ O( e% l1 ~

    , _2 C; I+ _! P0 e+ m# A  K* G. z& Q+ @$ _4 N* W# U& D6 L

    # l8 n# K3 w; b% D' Z  O
    $ ]* m4 K9 X  x8 J( b# U1 n" {0 Fvoid _MergeSort(int* arr, int* tmp, int left, int right)
    7 e  h/ X) \6 K! X$ a% @{; r- x6 v/ ~$ f: ~$ O3 s
        assert(arr);
    % Q' G* O% i& X: s& J1 Q/ u* Q* ~
    ( y! n3 A. }% F8 u: K# j/ E    if (left >= right)//递归结束条件不要漏了
    $ h4 Z3 C+ ]* U: i3 T; Z        return;9 C+ v. U6 U2 A2 E; ^- W

    4 S+ h5 P( Y! W$ ^; X    int mid = (right - left) / 2 + left;
    8 C# p* c2 G  a9 ^2 S2 z5 E1 x$ D- Q1 c+ U2 A
        //划分左右子区间[left, mid]和[mid + 1, right]% k0 V4 f; w% F  D; a* ^" D' q
        _MergeSort(arr, tmp, left, mid);
    9 r: \! n( U) y    _MergeSort(arr, tmp, mid + 1, right);
    2 L( K# m( I' Y) ?& Y  ~' p8 W" q- W8 g
        //归并
      m( v8 {- X. K7 m    int begin1 = left, end1 = mid;
    * a3 f2 Z/ `7 ~6 {2 ^    int begin2 = mid + 1, end2 = right;4 Y4 C6 ~+ I, n) E
        int i = left;# c; C2 o6 c8 m, ?4 z, x
        while (begin1 <= end1 && begin2 <= end2)
    % Y. o2 r3 c% ?& k* e    {
    1 A7 P7 A6 x, r        if (arr[begin1] < arr[begin2])
    & R, _$ N" X8 [, G! t            tmp[i++] = arr[begin1++];
    $ K$ z; s. g  v9 P+ X) v. R- L        else
    9 J* B! a! [6 {% O8 {            tmp[i++] = arr[begin2++];0 L+ b; P# E$ P! V8 j4 P
        }3 A! M, P  m& |
    2 I5 y- J( w) E1 y. P2 L
        while (begin1 <= end1)4 s( C  W8 t4 G
            tmp[i++] = arr[begin1++];
    3 k  a$ n, C6 w  V) O) l/ _2 e    while (begin2 <= end2), q) n# S9 t7 A* y& H
            tmp[i++] = arr[begin2++];
    ; g1 W3 x! F% d3 r5 C* K# k       
    2 I$ w; Q1 P4 w5 {    //拷贝回原数组——归并哪部分就拷贝哪部分回去
      f9 C+ y9 v$ ?: ^    //而不是拷贝整个数组回去
    : t& F  d, _6 a) j9 d    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));% f: v5 I: N- W3 L
    }
    ; T8 ~$ {# E6 V5 M, q! q$ v5 C0 T
    : T3 k8 a2 J) ~void MergeSort(int* arr, int left, int right)
    1 Q9 L; P1 ]& [{* M! c! ]0 I/ y) x+ l5 I: T4 O
        assert(arr);
    7 d9 g; ~% Y) P6 i+ `& ~) @" ?3 x' f7 R$ f) G5 {) H
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));- \  L, @+ g3 n) H
        if (tmp == NULL)
    " z+ U- L$ A, A' F& d    {
    : l5 C7 F6 g' e# X        perror("malloc fail");9 v/ a9 _% X' l/ h& [( m$ d) v9 ~, Z
            return;
    ) W7 }) E. ]4 M& b    }6 J8 [' s: x' A2 X& o% S% |
    6 u/ |+ J2 ]1 \9 t
        _MergeSort(arr, tmp, left, right);# B. j2 I  F; v3 }# m7 N* M1 a

    3 \; r2 K  W; _; W/ b" W" {0 ~. D    free(tmp);
    7 x& G1 W# @2 j5 }* I$ a5 A) Q/ e    tmp = NULL;
    # j0 f7 p9 K( V4 [}! l8 @4 y/ m: r4 t& G" P6 a

    ) o3 C* @: n8 j) x. m$ }  b7 w1* D' h" x3 q; X" Y4 M" Z' T  t
    2$ s( Y9 s  k6 X- n  }
    3: e/ @! k% C$ @$ [' s
    4" U" G6 k$ W/ {+ r$ l
    57 H, e& W$ f; z2 G, I( Z
    6
    % Q" a! V9 S0 N  l7
    4 I% @* ?) i" r6 X" Z. I) ]8
    ! h3 [5 h/ I+ k) ~: Z9+ e. n3 B' k* p; m
    10
    % i" R  R4 W  B; C/ w! E11
    ' ^# \0 u/ ^2 I; t12
    , }4 U. y- s1 c* Z# a13
    ' W0 |6 a7 a$ [# X6 L# n14
      y/ p7 H& {. }# B* G15" O3 D! p$ q! {, F0 k# }7 F
    16
    * ~% Y: M! ?7 ]8 u" k/ c; U& ?' [( g17
    ! D* E" U4 q5 t! J0 z18
    / H6 A- E0 \, F19
    ( H* Y  l4 T  }7 C( _" r0 H/ j20" a& q0 U$ o& R: U" f4 j
    21
    6 c- m6 c3 o( W, }; M) x& W221 `. _/ M* x/ D% W; B
    23
    3 n7 m# T# i: [# Q" g24
    / t/ A6 k- {5 h5 ?) w6 N25
    # @* V, {5 O' z; E26; F+ \! F5 A) h: H6 G
    27( f! W9 L8 ~+ W
    28# m, |$ E5 m0 k
    29, N  B6 O0 h" C+ a* y6 ]# n; G
    30! I- {7 Q" {+ l0 b& x$ H
    31- o2 C0 M) b" M; y. N$ d/ R& U# I
    32: I% u+ u, S' C: J. Y( H
    33, D& O. |4 g: u2 H+ i: Z4 ^$ k' X  }
    345 J) p6 k. e8 k4 P. M3 X
    353 C5 O2 Q' q2 @$ r9 S1 B
    36
    $ t" _" @. u9 b. q37; q% p. j1 X: f5 c4 r
    38( @2 U, ?; i8 f3 F1 I
    39
    # k) c4 O2 ]2 v: ^2 W40! H* q. k; R: p7 u$ p. F& \* o3 c
    41* S0 C* N" g5 _; \- m. s4 q6 @2 n1 @
    426 z: }1 S9 Q5 G: y* Q1 |' ]
    437 }6 d) A" Y7 J9 Z
    44/ j, I6 v, @8 U
    45
    7 [( Q. V9 K+ k) Q( W. G7 V46
    # U- t  m( i$ g2 Y/ _( k0 q/ o474 T  a2 O; ?9 M" l7 f1 ~8 B
    48+ l6 ?9 c; a5 F- E% b
    49
    : u) u( f& [/ p7 P50
    , c1 Y( a, Y2 H6 |4 H51
    5 S& m% K. }  U非递归实现$ S- q% p! f+ F/ j+ p
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    4 s% [- |' @0 y8 x5 r$ V& k+ I, P$ J( v6 H
    / R. x3 X8 R! A3 ^3 Z6 A
    9 Z+ i! O& g4 C# h
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。: s) D. q3 ~1 W: h  n7 _& R: T

    ) |) \1 O: C& S4 f* t​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    9 v! B% Q0 [2 N( K2 \
    ! }3 y- F! @" {8 ^: N​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。% i$ [  n+ F( {- k4 O$ n

    % g& \/ Q7 k; Z. G1 U. g% U代码实现  \3 T; }2 `6 j: R% s! J! K- Q: [

    $ l" D. p5 Z- I4 f+ v. d/ Rvoid MergeSortNonR(int* arr, int sz)
    . t- h& G$ b9 \' {- F) x# `{
    " o5 [; m9 K2 j    assert(arr);. s+ [  }7 a. b8 D6 f' A( F, I

    ; e$ L. }" ~$ I! b2 d8 ?! e    int* tmp = (int*)malloc(sz * sizeof(int));0 Y% A5 N+ ]; t- h) N
        if (tmp == NULL)
    7 M0 T6 t: _' }- _8 E! R( u2 @6 a- J    {3 N/ J; K: f0 `( H5 [6 {
            perror("malloc fail");
    1 F* I# q9 B' K& j( U2 j" s1 g        return;% Q% B# u# N4 Z# \+ p0 c+ }
        }
    7 k" ?5 q4 w( h* B/ B/ i  O/ q- n& x+ \, W/ W
        int gap = 1;0 H. [* w/ a9 f$ _: H. Z6 ?
        while (gap < sz)
    9 u' @! {  e; `( B- z' z    {
    % o2 v0 J4 y$ s9 u* a        for (int i = 0; i < sz; i += 2 * gap)9 M5 N* i- Y+ u3 D5 K# e- n7 T! x& r) b
            {
    / C( E+ y- Y+ c. Z$ ?2 k9 j            int begin1 = i, end1 = begin1 + gap - 1;
    . Q; T% j: R) r5 I. j: r            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    7 Q- n' a4 W' G- ?0 H$ g            int j = begin1;
    " d) W# ^- s+ w' f7 P  p
    * C! s7 [8 Z: h7 I" ?            //归并
    9 i2 |+ d/ _% i, c- t( d8 J* C' c5 `            while (begin1 <= end1 && begin2 <= end2)
    3 B( }$ J9 w6 R2 M            {* q0 l0 C, A$ }  z& g
                    if (arr[begin1] < arr[begin2])
    - ^& G4 Y, f0 j  |0 V                    tmp[j++] = arr[begin1++];
    # q% D. L/ w7 f6 w3 X: j3 Z+ p' S1 h) t' |                else     ( \& W+ x/ D# z: e7 ~* o, n1 x
                        tmp[j++] = arr[begin2++];# H8 m3 n8 B( D1 z. l% \
                }
    2 t3 D( h' p9 Z8 ~  f
    5 j% r/ y, P2 k* Z2 [4 x% ]            while (begin1 <= end1)
    # h! t8 ?# w1 |) X                tmp[j++] = arr[begin1++];7 E( [2 p3 v$ m$ C) y& e- L6 o
                while (begin2 <= end2)
    8 Z. E! i* [, n% J$ _                tmp[j++] = arr[begin2++];. B6 l% d6 B! b

    / U/ R. H# b* T4 }, _& O) e            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    8 F9 M+ z; r+ E. f) W            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    # W8 w; l2 P3 L$ @- r$ \! \1 r        }3 C% j5 n( ?# P$ M& Z
            gap *= 2;$ n: K' Y; V; c% f7 D
        }- G7 q; B4 y  g" c4 c

    8 I4 Q- j( o/ h6 U  R}" Q& ~3 \+ O3 q6 V, K- S
    . \" O  M# P  x+ Y
    1- E& o7 s; a9 |" V! Z
    21 Q: ]7 k% q7 @$ y
    3# |1 M( D9 c% }+ c3 v, v
    4
    9 z$ ~5 G: a1 S52 e& M5 l; I+ `: s
    6
    : R9 v1 T. k4 W" [: K+ M7  A& v! M+ }) K: A' K( _1 T
    88 K5 [( Y) Z4 @$ w
    9
    ( q( v( ^& J0 ]' Y. w. R: q10
    $ @0 `. u) w7 a/ `- ^; y, O11  h  G  w8 @* F6 X/ y
    12
    , U- r2 p* E4 K+ u134 p8 q: ~/ T2 O1 |) K
    14
    3 o3 {+ d. T# e, f15" [& U, O! p: F2 P7 O4 I4 B
    16
    7 C' L0 j2 |4 S1 d4 o% N17, i' ~, G: P+ ^
    18
    # q8 A+ |: t' v  a( Y- a198 h/ D- L. O+ x1 J0 N
    20
    , G# y, E& M$ I! Z214 G" U3 ~) Q9 x" J+ ?
    22- }2 J$ |$ ]) }" c" E  _( |' g- T" M
    23' }+ Y/ E$ V3 H/ s, d
    24
    6 H, A3 ]" f6 L2 a25
    # c% Q! }8 y( M+ @26
    ' Q: w# T( N5 z( H1 {$ E; a7 x27
    1 B9 m. `+ G# c- E& B28
    / }: \  w6 M0 X) k' N; O$ z' A29
    3 a* s) d; r2 @( Q30( }) k: j7 x4 t
    31
    8 A7 J  T" F, S1 M! J. n& E32% r) B- s8 L) f" U* S$ S" @7 p; i
    338 r7 {( E, ]% n6 E- f+ \
    34  Y2 l: g9 s: a* L
    35* `% J; b  D- o# D
    36
    ' J; g7 @) `- N. o37$ r1 ^; i- C6 \! I5 I8 n
    38
    1 L7 U# V. G: _399 h' O; i% k; }
    40
    ) A6 d- B1 |( V; @3 P2 D0 |/ D6 E1 S+ u41$ U% ~: L+ Z! ?* V- U
    边界问题
    * H& ?+ U- Z3 G8 M/ }0 s​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。0 b; w4 O8 L* \( R% j8 I1 J9 H

    % c" c2 [, x& d# r/ W+ q举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    ( ]7 U+ |! j+ T/ V3 z* o5 @  e. Y5 j: }+ f- k( P5 X+ ?$ g

    4 R( {0 \! o$ \3 {1 o# G3 a
    $ F6 r. n: Z' ~8 f% y7 ~由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)% a( h3 W' T# E  W7 u
    3 _5 H3 |! Q8 h
    第一组越界(即end1越界)+ v3 c! J9 l+ v% l" N+ C& y3 T5 Q
    & m& y3 i" _; P$ ^; G0 e
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。9 V$ m, x5 x% k+ e4 g  @( Z: a

    : p, \4 W3 U/ i0 h7 _第二组全部越界(即begin2和end2越界)
    ( {" Y+ q0 G6 i1 _
    5 N% v# P  J7 @! g/ A& k应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。+ c/ \  ]( ~" g& _

    2 o- U+ Z( ]: o& O4 N# V第二组部分越界(即end2越界)
    - n1 ^" f" Y' S( o
    + J- A7 |% Y) F( V% \8 i应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    0 a/ J3 K, n% d' K9 C! e" J0 s+ |$ r5 A6 j4 _1 [
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:2 B" j& [3 ^' c
    " a& I* l0 V: z; u, J  _
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。7 {- U2 l  E: y
    - v8 a6 U  E* `+ {! s  c
    ​ 拿两个数组试一下:
    0 [& Z  M8 }8 @6 m0 p2 |( m! q# [
    8 v1 s# x4 J) d7 P+ c& q0 W4 p# {+ U9 z8 E
    ! _  A& x# m+ N- A, B
    6 M- z1 r9 F5 ]  u- w. z* R) f
    . |7 y! i& E4 f3 \; A6 I
    代码实现& u! q& G1 K) ^4 x$ O! F
    ) y/ D/ z! Q8 `* E( f
    void MergeSortNonR(int* arr, int sz)
    5 p9 S4 W( A% l{
    - U: e; u; E- F! j    assert(arr);
    0 O( w! M: [7 w& |3 f4 _2 {/ x2 m# g. \  \0 r
        int* tmp = (int*)malloc(sz * sizeof(int));
    3 H& H1 |. X& o7 B) |    if (tmp == NULL)  a' i* j4 f, _. z# g
        {
    : e. Y4 r% h% T. O9 a+ l6 p        perror("malloc fail");
    ; ~1 |0 S6 }" O, r5 }8 X- X6 C        return;
    $ h! P1 F& Z; _# W; n) `    }
    ' ]$ W8 b- V1 D' ~# p* Y1 F# `9 \, L8 h' a6 x9 T5 s: d  E! F
        int gap = 1;( ?  X2 A: u" r& V+ H0 E4 C
        while (gap < sz)
    2 Z  Y& W1 }) e    {9 G. j+ w, i) W3 o& @5 B
            for (int i = 0; i < sz; i += 2 * gap)
    2 i, [3 N) T* E4 _- B        {* p% Q# z- H) `
                int begin1 = i, end1 = begin1 + gap - 1;
    # q5 s' n5 P- \0 X& ~$ `            int begin2 = end1 + 1, end2 = begin2 + gap - 1;; c. }) p/ _/ G( |' l
                int j = begin1;
    2 M$ Q! O5 C2 J1 ?1 W2 B                        //越界检测0 [2 x! B" j/ U# A
                if (begin2 >= sz && end2 >= sz)$ k" e; G& ~  L' T- d
                    break;
    ) d3 ?; Z1 E; j5 B$ d  l9 j* Y) `8 c            if (end2 >= sz)
    % C6 _3 X& ~( l, J: J# X+ B                end2 = sz - 1;8 p3 h  F/ r% J3 A2 F4 X: A
                //归并
    6 g1 l) t. q# u2 Y+ Q            while (begin1 <= end1 && begin2 <= end2)/ V2 z* K0 E$ q4 g8 P
                {
    8 d, d0 t  J+ X: w9 j                if (arr[begin1] < arr[begin2])4 q; N# v! L& L
                        tmp[j++] = arr[begin1++];
    ) G5 g! q0 G) q) k$ V, L                else     
    : d) I# _3 C3 U2 |( m$ z$ d. R                    tmp[j++] = arr[begin2++];& k7 g/ s! e2 {1 X
                }
    4 n2 q+ \) F$ O9 X7 c3 N- _# \( k$ E4 `
                while (begin1 <= end1)
    / U* n2 \! F- J" [* o                tmp[j++] = arr[begin1++];
    ' a! x1 j9 B) A$ p* a- z            while (begin2 <= end2)
    8 h# I7 Q9 B7 X! b5 a) x                tmp[j++] = arr[begin2++];5 K  v+ b! m" Y- \2 d7 I

    ( ^  s  L$ l1 n            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    . W) C& s6 @* L1 j, I' ?# [" ?& r% j            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    6 }; C) b; e$ T- X        }0 r; K* \  A  C2 I
            gap *= 2;
      B0 W  x) f: x5 f; N0 w- a; f    }) K7 s; Y- s, }1 @" c1 Q
    : A1 o! ~1 |  ]; t
    }) ]2 E0 w/ v) k9 ~( [! S

    / m+ o2 D2 v6 m2 k8 X1
    . b! p/ z+ ?8 F% _, N, l2/ z  \3 |5 n  b2 ^. X  q' W
    37 Q" n" o+ {2 G! X9 U8 O( b
    4% p# L( h8 }: R# R
    5
    0 K+ k8 U, M5 ]4 w2 R% w6
    / b* i$ [4 J6 o8 n. ~7
    4 N6 z( Z) V4 o6 g# J8) V% H2 B( |+ j
    99 u: Q# y) X- y0 D+ P) `0 m+ B, J
    100 ~1 m; R1 `% {$ G# j
    11
    6 d! y4 Z3 f/ ^12
    / _7 K) m& @) e5 p* t' j5 r13
    # d# G- ~: k$ t. m# {1 u2 t14
    ( W: i! l) K* h% c15" e3 ]7 b( ~& a( F/ v
    168 Z" e4 n1 f! l9 ]" ]& f
    179 p0 V9 G$ T6 u# f4 W+ z+ _
    18
    : {/ i' x- n; o( X197 m4 G; O- y! d9 @, ?  s, u
    20, ~: |" X) [. R7 F0 g2 G. k
    21
    4 w& `6 ^) f+ f+ m8 r4 p22' U3 G3 }, [5 N5 M  l6 B5 Q, H
    23
    7 A# D& c  P6 S& P( E24, m! j! k+ ~3 n; b3 M  N3 b* u
    25+ Y7 f( w8 m4 R! S! a1 f  p
    26
    , `0 ]1 m7 C6 J9 m27
    ' }2 _3 a$ U: E5 s0 |28( P! n4 Q2 [) y) c  W
    29
    : s: t) a# e5 X* _5 E" L6 H5 r30
    . w# \2 L, i5 f9 p# B# D" }1 V31
    - n' o$ j9 Y5 }32
    1 {0 j- @7 d/ k! {* w- L4 u3 S: @33
    6 d1 Y7 Q! _9 b( ^34
    : K' b* e7 I3 \0 z: o8 k+ B35  h1 I# ^9 ~( T, P
    36
    0 w) `" H% }+ ]9 n' o. o3 x37& Z1 g, \$ F9 t
    381 @! G1 T& j8 |" A
    399 Y2 N! u5 V4 K6 ^
    405 }" J6 q( S% r$ V- ?: v* Q
    41+ N' q* }7 }; t
    42
    8 h# d. ]- T( o" [# `% S43
    2 o$ F- h  h" |. l0 G44+ n( R' C' m4 c# M0 |* g
    45% b  T8 y, }* l3 c# G9 T
    归并排序的特性总结:
    % S  @) O& a! O( s* o/ ~, `3 s) i
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。* [+ g; h6 O6 K8 u  E/ c
    时间复杂度:O(N*logN)- g2 C* I" D4 s5 O3 b  K" Z
    空间复杂度:O(N)2 {  G( c4 ], D$ A1 Q
    稳定性:稳定$ f' h$ F: U+ b6 d

    ! G& x2 I3 C1 W& t( p* ]8 p————————————————; k& k; m1 y( J6 m* m) z7 {
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。2 v7 J& V/ R/ N6 \2 I- h, l1 X1 Q
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657% p3 A$ V! C% t
    : K+ Z' Z! ]8 }
    9 r% \' r$ z' i/ m2 a" y* L* e) n; t& J
    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-9 03:42 , Processed in 0.431920 second(s), 50 queries .

    回顶部