QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3326|回复: 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的排序算法】归并排序3 k* p( D0 ^  M
    , I  g9 D- g0 T9 k
    前言
    " \5 ~" i7 q  h: u- O本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。
    ! X: F" }8 F0 L+ B: N3 D
    . g1 l, U# L6 T6 H归并排序9 L9 J$ w- K! ~1 n* j% h  ?
    基本思想$ q8 C. i1 |! i; q
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    ) d, \; G* K1 d" G: X* |% \
    $ l8 Y, v1 [; w
    $ P- S& h  q6 W
    : o% V/ o: p1 u$ T/ x# E​ 合并的思想其实和有道题目的思想如出一辙:
    & Y0 u. j+ m* m" v
    3 a4 P" p9 o/ g5 S" u( t
    9 I( g" C5 a2 a3 R9 G) y. y/ F: Q
    # t& h4 {+ D& @; a; g5 e0 _% O​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    0 s3 P) |0 ]  w7 H/ H9 S$ w# i& `2 S9 n; ^
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    ( a, K' p9 ~# w: C( }+ q* J4 \* x, w/ P
    int* merge(int* nums1, int m, int* nums2, int n)
    7 N8 d. c& j. b# w6 f4 `- }{5 Y% f3 K! P' W
            int* arr = (int*)malloc((m + n));$ R" i' h' x3 b( u/ q' A+ i1 c
        if(arr == NULL)7 H5 ~9 s/ M; d. I5 {) _
        {$ g# N2 \4 R# d( I
            perror("malloc fail");
    ( b/ `9 B( o; B6 @8 t9 r        return;
    7 n/ A: o. L' V5 p' `    }
    # _* |! x, L) j; ~; b
    ; s4 ?; b) c) F, |    int p1 = 0;. ?$ t! z( w" E: K% l
        int p2 = 0;6 z9 e! E, ^" y, w  X/ P
        int cnt = 0;
    : D. i$ u# @0 W( g5 ~    while(p1 < m && p2 < n)
    + S9 x+ k% E; I/ M7 P1 U% T    {9 Z* w/ f% g5 G/ y
            if(nums1[p1] < nums2[p2])# ]2 {# n$ O7 V7 x# d; n
            {9 d. c! a2 W  [2 G8 l) e
                arr[cnt++] = nums1[p1++];! Y4 ?/ ]; U5 H3 g, F
            }
    . @( Q3 K6 g5 n5 J1 M: \, [        else
    / G- f9 X# e, |! {8 J* a        {
    # j$ V) \: p) O/ }            arr[cnt++] = nums2[p2++];% S5 e% _  J4 F) k+ o
            }, p+ |' e. ]: G6 {) ]
        }
    0 M' |8 H7 D+ R7 U: |    while(p1 < m)
    # H$ H* j0 T2 X! L* P# C        arr[cnt++] = nums1[p1++];
    : ^, ^2 c2 g& R5 X5 ]1 M4 Q5 Q
    3 ^7 u& H* p: ?4 e    while(p2 < n)& N% W, Y9 r  B+ P0 O" f
            arr[cnt++] = nums2[p2++];2 B- c: ^" u: J: ]
    3 |0 X: T& a& X4 U9 \# O; G
        return arr;
    7 H2 k# Q( A9 A0 J}
    " p& V# @* t: Q/ l1 Z8 I6 e" G# J0 Y7 \- Q4 I: W  }
    1$ X' k! W& `7 {- t0 a0 Y4 i
    2. o* m( y5 D3 B* D$ E
    3  m& b* ?% D& D* X  y* l
    4+ t" l2 E" y8 v! a$ ?9 k
    5, w" W1 k! |" q
    6
    . _0 v9 Y5 Q6 T( Q1 H) l" R! p" G- T7% v+ ^! w" P3 J% h6 ]- b4 s7 y
    8
    ! o# `& C9 G# x. C" ?! ]9 z9
    ( H* @) ?* y1 l. m# ?& T6 P" u' X10
    ; G& h9 S7 W6 w7 m1 D& j4 B11
    ( f2 J% o3 x$ _  F12
    % O* e& d& m5 }5 M* ^5 L13
    ) N1 i0 O, i9 {( o7 f' e0 m14
    # l8 ^2 H# H. ^0 ^15: l5 l: l. z3 s. g  x# u
    16( v( T5 v2 a( ~  y$ }
    17
    8 Q% `6 S3 S- c1 @" N6 [189 o& O6 _% g0 a0 `% K
    19
    # U' k- X+ k, f& s8 H20
    # b, a' v* x1 }) v7 b; B2 r4 t0 p1 J210 T2 i6 j- i7 s
    22
    9 t/ J9 p( x; H: F: ]8 m: l- l7 k23
    ! I! p7 A  ~2 I3 y; I" I; |24
    & L( O' ^, _: ]5 b4 q25
    " W6 V4 M8 `  A, `- G; Y262 r4 S! h% E: W+ S4 b. H% n2 A
    274 ]. @2 a3 q: B7 C* a! K  s9 r
    28' [' M" A7 g, c# h2 S
    29
    ( y- u# a- ]+ ^0 ~30. {% g5 N( o+ B6 Q* F; n
    31
    6 B# j# a* I  ~, f: c​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。
    * O7 [1 S( Q" j7 i- M2 q1 w2 u6 ~, x; K
    递归实现
    ! x" g; [; w) I  t​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    7 E8 @; z5 f$ \' {
    & Q9 P2 G1 r* U  h8 q6 T
    ; ^8 Q- V; k1 h
    0 t& _7 v% q& G) W
    5 a+ _$ f  u7 P. k" }+ Z, }9 V. }/ \# I0 j( ~( f, H
    void _MergeSort(int* arr, int* tmp, int left, int right), Z" x6 F$ X- S5 H, R  G3 {) L7 }& q
    {
    9 }( j  o0 }4 ^) D    assert(arr);
    4 j, n( {8 i$ w. \9 U1 w& a7 `) b+ f, O3 i) K# Q
        if (left >= right)//递归结束条件不要漏了& c+ W* a1 D& s4 K) B9 f  T
            return;7 \; H0 P/ x8 A3 N: Q- g
    & {5 \) W* |5 j* G
        int mid = (right - left) / 2 + left;
    6 e% r" z1 [% U+ c( a1 {0 N, S5 p
    " G9 b4 D9 V  c4 ]" r% Y( N& D7 [4 L4 R    //划分左右子区间[left, mid]和[mid + 1, right]9 X# J* b: N* P5 F& i# K
        _MergeSort(arr, tmp, left, mid);$ v3 M1 o* n" r5 \& T
        _MergeSort(arr, tmp, mid + 1, right);! Y5 J7 B- d( t6 Y6 n  d9 ~3 S5 b
    ' U. i6 y9 T  q( a
        //归并& [* r8 N  {/ N/ z
        int begin1 = left, end1 = mid;
    ; P( u' Z+ E* T$ ^    int begin2 = mid + 1, end2 = right;) D% c# J1 N7 E- J) `
        int i = left;4 }8 C+ @" F2 L3 k0 l
        while (begin1 <= end1 && begin2 <= end2)# h  d6 m( |6 L7 e( _% B" O
        {
    / j! `- T8 J3 |/ f  z$ V        if (arr[begin1] < arr[begin2])+ V! N6 G# D! j  i
                tmp[i++] = arr[begin1++];
    ) g2 o4 D/ ^- u1 F        else
    $ `1 s6 p6 d% h( T4 T            tmp[i++] = arr[begin2++];
    ; w) {6 y# s4 w& W6 p" {    }9 f0 m# Z" l# r( V
    , q1 D4 N6 g* W# a. ^
        while (begin1 <= end1)
    % N: ^$ B" d3 ]1 ^9 C! E        tmp[i++] = arr[begin1++];7 N! h+ d$ j$ U! ?/ `
        while (begin2 <= end2)$ S- f7 C; a* z; E
            tmp[i++] = arr[begin2++];
    & `5 a4 j6 S  d. s% ?( X- |       
    7 y# x6 B) x' {$ u  v0 ^    //拷贝回原数组——归并哪部分就拷贝哪部分回去3 y. @$ f& O% z2 U5 Z
        //而不是拷贝整个数组回去; x1 [/ y( s, \2 n5 m
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    - h4 Q. z# y0 s}
    ! y" K- ^2 Q5 r  {
    $ E7 r3 ?; w5 Avoid MergeSort(int* arr, int left, int right)+ \% `5 j; K! b. z! A9 I
    {2 L2 ?  U3 z. T9 \0 p' X. |
        assert(arr);7 r( U9 R& H& }$ S* t- U# _

    % J/ }; C& ]0 X. p! [: [    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    ' Y! C5 u8 @: U. W: o, j5 k    if (tmp == NULL)
    # ]! s# w  B1 {    {9 F* h2 S/ i  E
            perror("malloc fail");: i3 C; Z5 k) J; [
            return;% I( l; |& m' L
        }' q1 y& F; @3 m1 j

    ( z8 l% i9 n# j- B$ v5 ^    _MergeSort(arr, tmp, left, right);$ \! }" [$ F+ }, p% ^
    5 B# n( \4 Z% m1 f
        free(tmp);8 Q3 ?) B$ _# L% l1 A# E
        tmp = NULL;
    0 e, q& m! m+ }, m7 b# I}
    ! b/ k  f1 {% G2 q: S( `# M/ p/ V
      B$ c9 `# ?8 U7 S8 a7 @$ j" S1
    ' b2 a( s& V* D' x  }2
    " q. S; P9 e! o! {3
    6 }+ x6 \* P5 J$ Z8 y0 ]* i( Y! ^6 M5 C4
    * W. o' C- r  ?# i  {5
    3 o9 \. L/ C( h2 Q60 A3 B: ^9 [  G% [* V& ^
    7
    7 k' F* w7 p" y; X  y8
    5 \5 a6 M# X0 B: i  R; F6 a9
    # s! n4 Z7 a7 R' O- V! s6 g10" ?( Q$ h/ f' R( E
    11
    5 R3 ~7 G1 J( n: }. \12
    + t3 t6 Z: C; `- S1 p/ V13
    % G$ T5 |; E1 G8 Z: D0 _# H5 q14
    + r( z3 I! f. m  @15( ?/ |* @0 Y6 t+ p, f
    16( J, D3 c, R# T$ x5 U
    17
    # U9 u6 @, i5 {" P) O: G# {184 n; a, _  g0 S! {! ?2 g
    19
      p& L$ S6 r- \! H: v20$ b+ a- o; {6 K" U; a& x
    213 m& t1 _% P( p/ r- F' B2 C
    220 U& I( D) x: s' p
    23
    7 z3 ^  ]; |$ @: o6 l  M& Z24
    ( G; R. e. t& i6 x8 R25+ d) H! Q2 T7 B" [/ F9 X
    26" M1 l" y; y. T" ?. b& `$ s
    27; q( t" g2 y3 m: |! i+ v
    28
    " W. n+ X9 X( H  `9 p293 f0 J  f& j9 @, G0 C
    30
    3 E& c9 }& _& J5 Z5 k" f; ?6 I31
    5 F. Q4 O. u" I' {323 Y1 b4 E  S" T2 e  W+ J0 C8 @
    33
    4 M/ l0 v/ u! [. b; |8 d" x  H2 y342 |1 f. m& l+ _/ F. b
    35
    # G$ g( L9 ~: ~+ z" Q, n36
      S9 L+ X, g+ R2 \, I) D37  g6 {1 E9 t, @  k8 |0 L( b  ^
    38* h4 V4 {% T- {% J4 R# ~
    39: u. J% j# w, K( v1 G
    40
    2 A4 ?! p; n1 g0 \! N41- O; r2 T. c- p# O2 b2 _5 Y( a, o9 g
    421 \/ d8 t, q7 A) B7 h( U
    43
    5 S" g2 F- K+ x7 X' o: ?8 A44
    # v: ~# F% p5 X0 O; P" |% v452 ~* E# L, p  Y5 E9 ?
    468 P6 h$ ?3 U+ d* ~
    47  ?: a3 n) E/ y" O# b5 T* n" b! c
    48* g3 V) b! t! x; t) L- Z
    49
    6 @$ c# F  \( r% _509 ?' t! l0 m  z7 z8 h
    51$ \; h3 c2 R9 a
    非递归实现  b( K9 V- g3 x* d5 g* h
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。
    % P0 g. }5 E; f  g4 p. ?+ Q
    # _. R# y" A' W$ o9 ?9 A6 ^. y: |1 Z0 Q- I$ o

    3 G! H3 V( S9 A: Y( ]" x​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。0 A4 @1 {. l7 O+ a) q
    % _- T- l9 ?) i* U: G9 X
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。4 _  b. s1 ^+ ~4 c; k

    $ z; |/ N) E! o* R​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。3 R; A3 U- d6 \) Q: B

    9 G! j* L( t, ~& R. T& q代码实现
    % y2 L7 h# i* \0 C  C' y5 N5 H
    ( x4 K! j" k+ N% D2 o% n! Z: Gvoid MergeSortNonR(int* arr, int sz)
    ! y( p2 Z( T  h{9 ]" }$ ?6 y+ m  V( n3 Q5 l3 g: E
        assert(arr);
    2 h2 |4 L- S6 [3 K5 t  ?2 \* ?' j
        int* tmp = (int*)malloc(sz * sizeof(int));
    , r2 A" Z. L  A4 o1 J2 P+ U+ c    if (tmp == NULL): o1 p: U& ]( h3 [4 L) ^
        {9 Q/ p( m3 e7 `8 M, B4 p  F
            perror("malloc fail");- p: p! ~0 |1 e3 L
            return;
    ; g" l1 e" O" ^0 I( g7 l" [. u8 x    }) l* z* t; D3 b5 R

    4 [4 t7 Y& m4 c    int gap = 1;
    8 f7 B/ l# v# r' f: m  c" i    while (gap < sz)) k8 J# Q, O. Y: E4 p/ p
        {
    " [( P7 d% d* o# ?* M        for (int i = 0; i < sz; i += 2 * gap)
    ) U. ?, e$ M3 h: h1 O$ V+ r        {( Z4 E' n, N* ^+ R$ {
                int begin1 = i, end1 = begin1 + gap - 1;
    / Z4 N0 d3 H# C! j/ r8 R7 v# L            int begin2 = end1 + 1, end2 = begin2 + gap - 1;* f4 M+ R6 f" Y, g
                int j = begin1;
    : o5 _1 l! n4 A2 i% I3 K
    ; Q/ ?5 I$ [9 X$ d3 _6 \) e            //归并
    . R) R# w- S5 A* T" T( S  V            while (begin1 <= end1 && begin2 <= end2)0 L' P5 h9 x* h3 f% l% i" j
                {
    9 z7 O3 f' D* j# j                if (arr[begin1] < arr[begin2])
    5 p) ~, I0 S! U- c* {                    tmp[j++] = arr[begin1++];
    1 z5 A0 z8 r% q: A) @+ p+ R                else     
    1 W1 q4 d+ a/ f) G                    tmp[j++] = arr[begin2++];" H- L: m7 b- J2 U4 j; Z
                }
    ( _" m4 g& T7 k# i# x6 z) l8 |$ W8 d
                while (begin1 <= end1)
    . F8 p7 E( I, e                tmp[j++] = arr[begin1++];
    , h* d- }7 x; _. F2 ?2 m            while (begin2 <= end2)
    5 o. C8 e* L2 V  g. }0 v                tmp[j++] = arr[begin2++];- ^0 C+ ?: h- q& f. U4 A1 h
    : \9 E9 h! M6 t# J$ J+ B1 G
                //拷贝回原数组——归并哪部分就拷贝哪部分回去/ [5 b: q! m4 W8 K2 o# g# _
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    , J6 @5 s& w  X        }
    / K7 V( I, j/ d        gap *= 2;
    % w; ?% Q0 y! \* s    }8 o! d- C; C, L

    6 n' i3 e! T8 H}% N2 n+ L5 d% X& s
    3 J6 X: e6 c& f' t6 p% v
    1+ n3 x1 k  A9 J
    2
    : j4 ?7 l) U/ p' ^' I6 u. I3
    : K: T6 H  ^7 S! Y& P' Y4
    6 W, k. W9 d/ z3 S# S5! c7 A$ Q+ o# q$ z$ `8 H
    6. r" A/ R- d: q4 e. F8 X
    7
    , l" o0 s% I% B5 q8& e; [. U) ?2 ?* |! [" C
    9
    : O+ b- R! x* g3 D$ w10
    2 @2 D7 C5 i. P11
    ( a; K5 e+ t1 j9 w% {12! `3 V' C$ A7 g6 l5 [0 R# s
    13* G. W! a/ ^# h- e( ?
    142 h' A0 ?1 I$ x& q. b; V6 @5 @; `
    15
    1 P7 b9 \# k* l2 T4 V16
    6 @- ?! @$ T% ?+ y; I; h0 U3 M17
    . {( r2 {: l& s" l18
    1 m3 _# {; j, D' A- }/ ]8 Y( n; K19
    ) H. {! K- ?4 i20( j# j% m- D  l0 x8 j) N1 G7 T, B
    21
    ; Y9 D" K$ i* a" n$ U# o2 {) h9 C. A22! g) F  ~4 O, u2 O
    23
    7 d" f4 M! H& T2 O. x+ a249 K9 m* z% H, @* P3 r
    25: e- w( D3 l6 w
    262 ~6 ^/ e7 ~: u5 V" S! I9 v
    27
    2 H8 P- \& _0 v7 e. c/ ^28
    * c( h4 E0 o- n  L! V9 x5 G" S29
    # p0 n4 d1 T' r# {0 U. q30
    , z, Y+ c* J2 c* [# D6 X( [, o  p314 `& z" s6 W  E/ k& c/ y! F; {
    32
    , }) V) g) N! Q/ q33. b' y: w' w. |+ V% R; b& k! z
    341 [4 S" {  l" e# F1 _( O7 \
    35
    0 F! r  E' {' q$ _369 Q! p7 _& \7 n8 V7 Z" q
    37- S3 @9 f2 Z: ~* M, Y8 }4 T
    380 r' P, j4 I1 ], e, t5 z" o
    39
    8 Y3 X2 f( ~9 g2 b8 v- j( A40, s3 {4 l: L4 E& z0 _1 p0 V
    41+ I/ |4 I2 X& M, a: y
    边界问题/ I6 w0 M& ?9 v. I' G& D7 N
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    5 e4 b6 |  `0 |$ c$ `4 }/ C/ F  I
    + P* v1 w1 A# b5 ^" n4 \: V% V! v举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:! O& g- l, I4 N- P) D* P1 F7 ]

    6 q: Y  _: q; X- u* m  q; Z! s8 H  o8 Y, U3 k+ D

    + q5 M& L& u2 Y3 H) K* ?9 b% v: k由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)( @. l4 Z+ C, h* }( ?. y

    9 X9 h% z) F& ~第一组越界(即end1越界)
    # X) c' T8 r; z! y% [, H, L6 U8 u+ ~! w3 c
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。5 o! u5 c# q6 l; U% R+ u5 q) z7 D
    6 Q% g% P& l9 r0 O' f
    第二组全部越界(即begin2和end2越界)
    ' v/ t, T! g) l: ~% s3 w- Y- |3 X5 q5 X" K% ?! u+ m
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。$ G2 o& ?; [, C& K& Z
    4 s2 Y7 N! X. z9 Y, {
    第二组部分越界(即end2越界)* v" Y! D; h, A7 s, h/ H, f; w8 }, F

    2 Y" @! i0 A- [3 Z3 r; j0 \应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    * G) w2 w& k' o1 C: n: `& Z
    4 a- d( f. ]" _, D! L​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    7 ^0 u9 Y1 U& A, b# U2 P- Q. [' |# U  f: s$ N* G# K8 p  u
    ​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。' f1 H% A0 p$ {- a2 V3 \! G

    % @, k& J& x' [  A4 P) ?​ 拿两个数组试一下:
    3 @4 s& i' c) [8 q) }0 M# n/ X- c
    2 J$ v% `3 z7 I9 S- L3 x
    6 b; A6 I; J) V4 L/ F
    2 B, t, w6 p- D2 F
    1 m9 j9 ]* m+ V5 A% n4 v, ?8 a7 u7 \& p
    代码实现+ s& {2 V0 ~7 e1 ^2 l$ D1 `

    5 }& T  w. a) l5 f  P6 Y, ?4 Yvoid MergeSortNonR(int* arr, int sz)
    0 W3 ^/ d% q/ t{$ k! x1 c- y( a* n% z7 l1 x
        assert(arr);1 f9 z/ J/ r0 O( D

    5 R8 J9 E/ {8 s    int* tmp = (int*)malloc(sz * sizeof(int));5 p3 i# U/ G$ H+ j/ q+ i& y$ @) I
        if (tmp == NULL)
    ! @; {& ?) o* ~    {( ~1 G8 }9 c' `5 J2 e
            perror("malloc fail");' z; x3 A, p$ {6 j& @/ J
            return;( b- `9 t' t; O, J; r" {& f& T
        }
    4 z# d( I4 K% _  {
    . f7 H% w! l/ M4 |( a: `  T6 @1 v) W    int gap = 1;/ |) s7 J. }; c2 w7 ~& e2 @1 I4 V
        while (gap < sz)
    - z& I; ?8 c$ F2 G* K    {3 c# i% Z- P' j0 l
            for (int i = 0; i < sz; i += 2 * gap)7 o/ M$ d& H) @
            {8 h0 y8 F$ P- j; d/ B! M' _
                int begin1 = i, end1 = begin1 + gap - 1;, I3 D; j& a! L) S1 ]0 T! A
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;( W3 e: w0 h6 P+ K4 ]
                int j = begin1;
    $ u- C# C9 w. K; `" b                        //越界检测
    & |- _" Q, M$ Y2 d            if (begin2 >= sz && end2 >= sz)$ {5 o& a% T; }; h  A+ e+ a# H8 x
                    break;8 D! l3 m4 A0 }+ ^: }- I2 ]
                if (end2 >= sz)
    ) t1 B/ v3 q8 E: Y$ x, _. k( x2 b                end2 = sz - 1;' `0 A. c3 k/ ?3 H
                //归并5 J" n9 P) |: @# c. n3 D; O$ X' C
                while (begin1 <= end1 && begin2 <= end2)
    7 ]" ]: [9 ^8 n- U+ W            {, i& k# r* i) `7 ?
                    if (arr[begin1] < arr[begin2])
    9 i, M" C% [* X: s' u! r                    tmp[j++] = arr[begin1++];0 E7 ~2 n8 {) W* M
                    else     
    4 ^5 N. j0 n4 z, P3 d                    tmp[j++] = arr[begin2++];7 ^* r7 Z4 l6 I8 |+ z- M
                }
    1 z( r; w  v5 G4 H+ f! ^: l: W, `4 z+ T$ [+ V' ^" ?( {
                while (begin1 <= end1)
    / n3 p, {. T# p                tmp[j++] = arr[begin1++];
    8 `4 i$ c5 S9 g. V) X' u1 b            while (begin2 <= end2)
    7 w& o& G! n5 ]                tmp[j++] = arr[begin2++];- t: @: m" E7 v" I

    ( F4 s+ v# L" W            //拷贝回原数组——归并哪部分就拷贝哪部分回去, o: D  i* d6 B) B
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    3 n9 |8 m" b, a: {        }9 \) `- b: J0 E+ ]; X: }
            gap *= 2;8 c6 z* f0 G0 L
        }
    0 d' i3 l. ^7 ~0 Z5 Q+ N3 T1 C
    ) E* h( h" C1 L* h) N/ J}& m" ?  {1 G8 r, J5 q) S
    1 C+ |" t1 i& e- ?
    1
    - w( H& L7 n5 c5 }% _: s2  ^. }" h8 K( v' c& q
    34 `% G* |/ x1 N
    4
    4 v( o% Y6 M% F. A3 |5
    / g3 p2 b  R7 f$ `" G6
    7 z. l% m, t# a4 K4 ?2 E7
    ; @5 Y: G# C& e$ {& g8
    " M, g( }& m7 ~1 k5 O6 c9; @$ C  M0 m5 |: w+ ?$ d& e
    10
    + d" u/ `% K3 A3 x- A( ]' [! r11
    ( o* E0 a" [# E12
    $ P/ q; I) p; l6 Y) i13* [" p( b% A7 `& @
    14
    1 u- |, D) N) {; l  U15
    9 K5 S  U. {, N. [! Y. a16
    . g$ ^) q! D$ @* N0 M$ R177 ~  Z. v/ x7 q  [& @/ y
    187 S/ c( ^9 O' M4 r( f5 w
    19
    & y% i; ]7 f1 X* b! D6 V, v20
    # m4 m: j  _! l' S" S21
    " x" `; ?4 o; R/ @1 w, J221 d) O: p1 s. _3 E7 J6 K
    23# D) }  q1 b" d
    248 J+ w. _  L7 x; X
    253 j, u: ?+ |% f% n* J" c
    26  @9 l* G: g+ R/ ~# }8 S  u
    27
    : Q2 P* C1 N9 Z  C4 `6 g; ~9 l28/ Y- W' @; C9 P7 N
    29$ @5 ]1 t( @8 V5 q: j
    302 _; w: {% H2 {. _2 ?. q
    31" o9 Y$ u, j, r  d8 c8 q' w0 @6 k
    32
    3 B! [5 _; r% ?5 X& s4 O33: W$ f. p9 K# H0 D
    34+ `) o3 L+ R7 i2 p
    35
      u" R) u& G. l0 S" y36
    8 V6 |0 z3 ?+ z$ f( u% m* [  d37
    . w2 d8 l) `! w: j  k+ G# k2 ]5 R38
    2 F& D0 S8 h* _39
    " {2 |& S! b( ], j407 D* F( d0 k! b
    41
    ! C6 @; T5 i7 i7 \+ Q5 H8 F42: _$ g5 |+ r* p% Y3 ?0 A- w0 b7 I$ {
    43
      @& n: d! T" Y0 z2 Q44; Y! Q& A- p4 @# d3 q  U
    45) r  x4 q0 `% d  g- u0 p8 K
    归并排序的特性总结:
    1 g5 @& G" |1 r/ m
    8 }/ E6 f8 S% |& O$ o1 h5 k归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    8 @3 y8 ]9 m0 P8 [时间复杂度:O(N*logN)
    . C" Z0 I# v/ |" ^7 F/ @1 M空间复杂度:O(N)
    8 d0 |$ g' J8 z7 Q  n6 T稳定性:稳定
    + \  [- P5 C  t0 B; E: G7 x4 \* L; x3 r  _
    ————————————————; P' t* g6 _- c' L) Y
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    $ g7 f* |) s; B  ~0 k6 c) y原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    # {" G9 |- L" L+ y1 D8 p" {  K- @; |! A  X+ O% ?) v

    # S* {# I0 n4 f
    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-8-5 11:05 , Processed in 0.385134 second(s), 51 queries .

    回顶部