QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3319|回复: 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的排序算法】归并排序0 v6 i# p; ^7 F$ ^' S! @3 n2 f
    9 ?1 c  q" P4 k) {* Z3 {- t9 A
    前言
      B6 J5 _7 `0 b9 ?* r, }% j本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。% R7 _# W8 ]/ Q" Z% U

    5 r- U+ C# U7 u2 Q6 K9 g( C3 m' }归并排序6 `* H5 |/ S* |1 Q. m& l3 c. o
    基本思想* a" Y, H% `; P
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。; T& X% _( w; |! |
    , Q, Z. q; {4 b! w$ {& n- u2 e
    : [2 V0 V' `/ t

    $ R7 \. m8 B$ E​ 合并的思想其实和有道题目的思想如出一辙:
    6 L( s2 \" b$ R  Y# v/ T2 \7 W8 j' w& B. ]! w1 N

    ' i: Y  q5 V( R6 H8 t( y* s, q1 u  Q; [# l2 [) A
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    * V7 L1 g. J! @) _/ P$ g+ x' Q/ l( g' ^
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]1 q& P' H/ U# O; k
    + N1 K: X  ?3 S- m
    int* merge(int* nums1, int m, int* nums2, int n)/ f' N$ |4 Y0 z! Y0 b6 A- P# T
    {
    3 g5 z9 N! j2 `% o        int* arr = (int*)malloc((m + n));
      y9 s. K+ ?5 ~    if(arr == NULL)
    % Z0 G, n1 S7 C& `9 K    {/ T$ Q3 [% F; j, c3 v: x  D
            perror("malloc fail");
    9 D: j, ?* F$ T, d        return;
    / o7 h4 U& R, N+ g    }# T' w6 i& m) y5 I( O. k) U1 Y

    , q! y- o) ~) C( Z, e    int p1 = 0;8 E- t" Q: E0 D4 H# \+ u& B
        int p2 = 0;
    # w  j1 M- |0 u  u$ Z3 r) C! i    int cnt = 0;
    . }! x4 [; R: u: i9 n8 e$ g    while(p1 < m && p2 < n)% N+ v: ^( r' P. ~7 \
        {. R) K# C0 }1 t9 u. a: P( L( o! c7 G
            if(nums1[p1] < nums2[p2])
    6 F+ ^3 V7 [2 c$ W0 D/ G9 `  B        {1 t& B+ v! Z' I4 t
                arr[cnt++] = nums1[p1++];
    1 D7 Q# N$ D  [        }
    : q2 j3 E! D- V0 U        else
    6 d$ D: w6 S3 C0 K        {8 _, F3 |% e1 N+ E
                arr[cnt++] = nums2[p2++];. n* r, q/ V/ g5 Q
            }( P/ q7 F; L+ X  {5 U, I1 B, @
        }2 T+ T* z2 w0 l5 Q
        while(p1 < m)* I% C, q; {7 S6 M( }
            arr[cnt++] = nums1[p1++];; v) n0 p1 ~8 h0 o4 f# m# F7 a
    0 v! E* W: _- a, z& `$ U& \
        while(p2 < n)
    " m$ X3 q  L$ z' \, U9 f. g* [        arr[cnt++] = nums2[p2++];
    6 O0 s1 a3 G$ J4 m4 h! e1 O3 u8 d0 T* P8 b4 A7 a/ c4 s  }0 a
        return arr;
    & [7 \) w4 Y) E- q}- n0 U+ b$ z  a1 U/ K! y

    1 |9 R$ `5 i8 A; n" f+ x1
    2 D* R  V; a5 d/ f! F4 b2
    4 w$ }3 Q: u* R3
    9 e5 a% Y  C1 Q5 F7 D4
    4 d6 u. J/ K5 `- E; G/ _# H' O5/ ^+ H$ J% H4 G
    63 _, s4 V$ m4 k8 m
    7
    , z% ^% Z4 {8 j! v! u" s" Z9 S8
    7 c6 m* q  g& t0 T1 z5 {94 D4 N2 R! B9 g( C8 |: i
    10! J; j1 b! p. H) o% L. x" i- ?
    11
    - _! D" Q, x) f126 K0 F: Y; ]5 r3 M7 g& F+ S/ @2 l
    13
    & ]* {) h. J3 k- b$ S. H14
    0 Q1 g4 Z* a/ }& A  c* w154 u4 A/ m3 r0 I; A" X' _$ j# u2 n
    16
    . M1 w9 }( x7 T7 M( E  h17* ~2 D. d) V, Q# n( s8 U
    18
    # F: E$ |& M9 p, a0 b) f8 j198 M% r# Y  W# U  q" ~
    202 Y2 l8 _9 Q/ [0 |, ]& m
    21' e$ B8 {1 O+ G& C
    229 @+ ^$ V9 Y' y: D
    23
    ! w5 i# I8 R; z2 Z" q# e$ s: @6 U" C24# I5 K- A& Z3 r9 q
    25- Y. r$ p5 s, X3 {
    26. {& @; V& B/ |
    275 w  g$ C- c% f  T
    289 x0 s9 x! ]; E, L" m3 E
    29
    - C: [2 e2 D8 _7 f$ ]30* N0 X2 L" T: ~8 Z4 N- C) X
    31
    - y9 d) y' \- [! E. S' |* ^9 n​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。* [; V) s5 l( U" J, p8 l
    ! x# T  Q! o( g3 c& ~
    递归实现
    ) K) `7 a% b$ x$ e1 {​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。: D8 T6 Z! f; L( V; n

    & Z, y* f, K" H: b9 U0 F1 c, i$ V6 m) D9 E
    ; b  u9 q9 y; M9 t; e

    1 S# ]; ?% \* K6 N: w$ a; i; [8 y9 P1 ]+ R3 u! P% m2 {+ |
    void _MergeSort(int* arr, int* tmp, int left, int right)
    + L/ c; N# t: ]: P/ H6 G! f$ F2 M{
    # i# S6 o: P. B$ ]9 |) q- [/ ^    assert(arr);4 E" \9 Y) ^" Q& d

    . j, W5 a0 L' P2 V. I! Q    if (left >= right)//递归结束条件不要漏了9 a5 l" L* K1 ~' z+ ^9 t
            return;
    - q% p% [, m/ n2 m+ y5 W% G! j
    . g% s* N# V, [! F( V4 m    int mid = (right - left) / 2 + left;, j& r4 ~3 L4 S1 T

    + i% \9 n/ \. l+ f! m" {) [    //划分左右子区间[left, mid]和[mid + 1, right]
    6 M; w$ S1 M" F& _7 }6 t; B    _MergeSort(arr, tmp, left, mid);
    ' Q; @  Z! c3 e+ E2 j7 r, f    _MergeSort(arr, tmp, mid + 1, right);, z) B) b4 w: ]- ^
    0 ^6 t) |" m1 a# M
        //归并" E" {! R+ N' ~6 O1 C+ A+ N" i3 l/ T
        int begin1 = left, end1 = mid;
    1 g1 c  _1 J, j/ Y, h9 S2 o    int begin2 = mid + 1, end2 = right;! k, S/ h; a& @7 k5 [; {4 s3 S
        int i = left;6 Z- q3 _' ]  b4 C
        while (begin1 <= end1 && begin2 <= end2)4 E! e4 V& }. N- x$ Y7 w; X
        {
    9 v1 C- B1 R; b, T: I        if (arr[begin1] < arr[begin2])$ s* A; B5 @) z' b
                tmp[i++] = arr[begin1++];
    ; |- X4 o' T5 v7 {0 A9 g, v- Y        else" d/ }) I" T: a+ q$ C
                tmp[i++] = arr[begin2++];( r4 S+ J! Y9 o/ ~
        }& Q1 l. T3 S0 A9 Q
      |8 Y& M  Y$ b" v
        while (begin1 <= end1)
    - Z+ [; g$ ^3 Z  K( M        tmp[i++] = arr[begin1++];+ o, }1 K) a' m
        while (begin2 <= end2)
    ; R7 _1 x8 M6 ^  W1 }        tmp[i++] = arr[begin2++];
    7 S& _: S( g7 t' I6 {* T) |7 U9 x       
      u! P, t  Q! w6 ?. A    //拷贝回原数组——归并哪部分就拷贝哪部分回去
    3 j5 `6 M6 X  k    //而不是拷贝整个数组回去
    , q2 @( ~, A8 N. g4 A9 A    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));3 g+ [8 Q1 U7 t; h( {
    }5 K# k1 ~9 ^8 Y1 m
    ' c; @1 `; A6 U/ ]6 s
    void MergeSort(int* arr, int left, int right)
    + c( H$ U; i+ S: @8 O9 ]% T" H/ ]5 `{
    6 _( p1 G: w2 |+ p: B( m- \    assert(arr);0 ?3 ?# t  [# i$ J

    & ]9 ~- q& ~" D0 n! p    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    - P  J1 P* y$ J: E    if (tmp == NULL)! U# ]# e! K4 E/ o# _5 A
        {
    % P9 ^' a5 L- Y3 t! A2 E        perror("malloc fail");
    7 M# t  S! w( d3 s2 V9 ]        return;
    / h. m5 U0 }- x9 K9 v- q- j6 K    }
    / S2 H& I$ v  |4 U$ R0 G$ L$ K/ I  u/ ?
        _MergeSort(arr, tmp, left, right);
    1 V4 M* ?  U( T: d
    : \+ P7 [7 A+ ]. U    free(tmp);: N% X5 D: {. Z
        tmp = NULL;  O  `1 u. D* O
    }" N6 J: Z' ~  e5 U. M! M

    - z# K! m. C* w5 l1! Q6 I( U* b- Q% L
    20 w. W! q& K* c+ m  l
    3
    ) b2 L6 ^% n7 u$ o) I1 d4
    ; E; y# e( ^; B& p5
    + G2 R! @) E( o3 J1 I/ t6! t- b7 j, v5 l+ O, f8 ]
    7
      a* K# _9 }; `$ U- ]8) y) s: N) N4 P' f. j3 ]
    9- o0 f6 ?% j% [. H2 ?
    103 }/ @$ h2 x# o/ h% o& v* ?
    11) y" k0 [5 W% R8 Z6 G' N8 e$ d8 ~
    121 J3 x. @: s0 }5 l& m7 h: w
    13
    % {! O% A/ S, r5 |142 H& l% _# F5 U& q3 s: M* R+ @
    15
    ' i2 a' y+ `) u; {* z16
    ' k6 w1 ^: Y* o$ i; f* i  o9 c17, Q' |. l! \3 s, _
    18
    : b- D. ]. z6 p9 z19; E5 T4 A9 ^, {7 a; Q
    20( @, l; a0 c3 T' X" j. i
    21; ^4 T, m4 p' n  z( Q1 k7 d
    22
    " R" Y  m5 b: L23
    $ k: M! B, T& K24
    # P: b1 M3 \( S& b9 g25
    ; f0 c& ?( q5 {2 P  \- i; I, u  N26  ?) A1 @) x( J7 d8 s/ x% z8 r" I
    27! o2 N9 I. z  H! A' n
    288 @  T1 A* v  L- B1 j, d
    290 g( e5 I. x- ?+ I
    309 l  k1 E# |. U0 n
    31! L$ X! J. j5 M2 s
    32% C' o/ S3 [6 ?; S7 g
    33) s% W  F) f! x  ^0 W
    34
    3 U! ]3 c. _7 I. P* O5 H$ w351 U. n- L% t/ k+ P. r8 r+ ?5 w2 D7 o
    36
    + Q, c  b% E6 S0 d- D# n* j37
      m$ P9 M  ?, M4 i38
    0 d" {7 V, e5 P6 A  R39/ N: P* Q! f) c: R
    40
    8 o* w7 B  E+ K6 k: Z* T$ U41
    3 }" ^" s) g! ^/ f42
    % J6 Z: p1 L; ?  V5 O- [43& P# B& ]( `" B1 Q" P- {
    44$ F) Q+ A6 M* \+ K% x0 j2 q( v
    450 ?* x- S1 x- b0 n+ s% F; K
    46/ p3 N7 H3 Z2 m/ ^* J( q  ~! m- S
    477 h' N# Z+ b7 x8 a3 c$ {$ |3 l
    48
    : X6 }9 W% D+ ^9 j7 [49
    . w) h* {% J; m0 m8 W50- e$ h+ n% }. \, C9 h
    51$ j, T3 {) v( R! v& X
    非递归实现3 }; K! }' M( I  x2 c, f6 l
    ​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。; B( g: P- u4 {" p, D5 s

    9 z$ T9 l) |( b' |$ M/ ^1 @( L3 k' m4 r( @) l5 j. b

      w4 a! v4 W2 M$ Y$ D​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    2 R  A! c. I. Q
    * h! d, T5 T4 C8 v+ {# O​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。, r) B- D1 f3 j9 p5 F6 C1 t/ B4 P$ N; t

    ) z- ~4 C" P2 w! q5 t​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
      w$ ~, `7 d0 M) a7 R- h7 L9 J# B* p) H4 F
    代码实现
    ' U! C4 j5 C/ G5 K! E# T, W: S2 f0 C' {$ f
    void MergeSortNonR(int* arr, int sz)+ R* k) }1 x  Y1 W0 T& D) y/ S
    {9 }  a0 g& L9 ^7 X/ `( m
        assert(arr);3 w* G" Q7 A% B: _: O, {6 }1 o

    0 C7 {/ O+ _7 Z; Q2 K0 Z    int* tmp = (int*)malloc(sz * sizeof(int));1 i0 D4 ^* v8 E: t- D
        if (tmp == NULL)7 [  ?, W' p! o/ j# }, m7 c
        {
    0 O, j0 C" f( U1 q% J6 c        perror("malloc fail");
    + r6 w* i& |' [. k0 {% Z        return;( y6 ^2 |7 b' B- E' B# c% E/ L
        }
    ; {" v! z$ i4 c* {
    & U( G. v2 t# I/ g0 |    int gap = 1;2 D( r* N3 T% h* C2 S( B9 y
        while (gap < sz)2 Y( o3 G) Q" W- N
        {
    $ T, }* x# b( ?: @3 S+ F        for (int i = 0; i < sz; i += 2 * gap): w$ Y% i; M0 F7 C4 X/ g, D- L
            {- [' c$ f* i$ J/ b7 U
                int begin1 = i, end1 = begin1 + gap - 1;+ j) z; x2 A1 o; d! j" p3 \9 |
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;9 ~7 N7 A+ ]8 K2 }! y
                int j = begin1;
    $ S! v" k1 V) ^  f% {. ^; t+ L! W( D6 }6 A7 \- W
                //归并+ b- Z3 r: m! Z. x) i
                while (begin1 <= end1 && begin2 <= end2)
    8 T2 S  p/ E' P$ d6 ]$ n2 v6 Z! L            {
    : P: N' E- Z( y+ y                if (arr[begin1] < arr[begin2])
    & Q( ^. a6 C. h3 D: Q! u" l                    tmp[j++] = arr[begin1++];
    ) {6 u- M3 V* l4 M* E" `$ `* b                else     - {3 F2 e. c. ^0 d# `
                        tmp[j++] = arr[begin2++];, S: S( j) l3 ]
                }& E) [1 u) J( j2 d

    8 z6 I1 S" a/ T/ {% C            while (begin1 <= end1)& a- w7 L9 [3 i
                    tmp[j++] = arr[begin1++];
    5 N3 ]5 S% E2 u$ O1 \            while (begin2 <= end2)8 D( ]  E" N8 L5 X$ ~, L
                    tmp[j++] = arr[begin2++];
    - j' y+ Y. X. C9 ]0 z# G! r; j$ _5 V. b' h. S" H* Q! r/ H; p4 `) n
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    , M6 u/ z1 x- k: r            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));. o7 k$ v3 |& d/ |( `
            }5 i, p1 e% P0 V" I9 K
            gap *= 2;
    5 P9 M" m: {# c& [; q    }2 u2 u) w* T" ]; [. e: g' k6 {

    4 y3 ^  \4 u0 `9 `8 G( j}
    ! W7 |* C2 U; y$ X& k$ G5 [4 u; z8 z% _' b
    10 L5 E: c+ C5 S( q  I; I
    2, {7 f/ P: u1 f% q$ ]' w
    3, G3 f" S, q& E& H! x
    45 A0 |* c" I1 v9 ?" e" x
    56 Y- |8 Z/ P; m4 K- p
    6
    0 j( z  {/ j$ f# U0 E) D7+ T! m. G* @8 |9 u( t* a& O
    8
    0 W8 f0 r. R' m9$ y6 Z: I2 R+ a" d/ v
    10: T! h2 ^- T7 F8 ?, r9 Y: \/ U
    11
    - N" D$ ~) u4 u5 l8 _6 E  x12
    ' _5 Z) t3 C: N; @13
    5 f3 ?% t9 y' s3 t6 X8 ]- T14, `$ Z9 K' X, Y0 l8 A& _
    15
    / O3 i4 W0 P/ T* ?2 h7 K16
    - b* a) Y" \% l3 T/ _& R! w2 l% B17
    3 Q( |  y" [; k+ T) a* _& h7 P18% |$ c4 A* B6 i/ ]+ S. Z
    19: P  @. V" D! j2 G2 d
    20
    5 ~8 ^5 L7 z5 z3 E/ V3 X21% a) ?9 y1 I- Q+ u' Q
    22  R3 s; X" M' D: c" L6 g! a
    23, V: I- ^6 x3 n0 |( X0 e
    24
    # d; S  I0 D: x5 e5 R25
    2 c7 ?/ z+ {, F! \: Y$ A7 W26
    2 z( S9 D; k* E; K( r8 L# I27% f# c2 X" L# J- U! [, g0 ]. H3 U
    28
    6 x1 R# z+ F9 x) e/ j+ N29
    ( d5 L1 }9 a* W( \! M7 [+ @305 E& i0 O; U! p- u
    31
    ) q1 l. K# H4 l0 N32  m' {5 D2 A5 N  t6 j* q! c
    33" v2 v3 g0 H, M8 S8 t
    34* h* x: j; r$ M8 q
    35
    ) M! q, e: K8 E$ t2 p! U' }36
    # E. \4 `/ k  d2 Y. o' {: W0 i% {376 w5 \. Z9 ~0 e# v: L" G" g
    381 a. t% S9 u- y; n! {
    39
    $ ?5 q- Q5 f, }% f7 R6 ~40* ~5 P$ `" M2 f3 ]* T, T
    41& d) c+ T' C) W0 e$ H; ?8 f$ ]& y
    边界问题8 Q: W) o( v: H- u) Z
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    ( M! o" h& q$ F  O5 h; q! g7 Y3 B* ~, N2 N- ?2 K. J" T2 b! u' z
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:0 Q1 X9 G8 b+ B( P& x5 Z4 R

    : z% I0 G: L: o* C# N" Y$ ^9 z7 t8 }- I8 G
    ) M$ ?# _" t7 i
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    5 t. O+ o  s1 j7 K0 n3 G
    : L* J+ d% {7 o/ w第一组越界(即end1越界)  k/ k# z1 a( G' U  f

    3 B" u( v3 Z+ ?+ J; C* k$ p* L( j应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。4 e  m9 t0 o( F9 K

      g; G2 L! _- _6 ^4 s; n! e第二组全部越界(即begin2和end2越界)
    ; k8 E  Q" m: W5 k9 I- W; m/ I" `( _8 e4 `
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。* F% x1 H, h4 h+ q

    " i. d% X+ P! n1 N  ?# k5 O# P第二组部分越界(即end2越界)" w4 n  V1 ]; P) j

    ! X8 B$ P; C9 d% w应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。; o& E0 A0 K& |' |2 B+ x
    / U4 z6 [  Z8 G2 A" W- Y2 f5 G6 C
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:
    7 X/ d$ \9 J) x1 |1 E3 z! J1 ~
    & V+ Y$ g3 i9 N% ~' M0 ?​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    ' u, Z, \% i4 O' a
    ( ^7 t( Y2 O2 U/ q' m# o9 V+ i3 w- k​ 拿两个数组试一下:
    - T) d- c& v+ X2 Y  Z; F( n0 }) H5 ?) |( I/ v

    : u) T$ [3 J  Y5 y0 v
    0 F  ?. \% h8 s* U( [; e/ ^: R  W8 _, u) d/ T8 ^
    + X6 k1 P! c7 J7 W: ~' }) }
    代码实现8 l% q- D- m8 h6 h. `

    2 @& \' D. h* f! i% Yvoid MergeSortNonR(int* arr, int sz)
    " s$ u' E* B* Y" m{5 i6 y3 N) `+ A
        assert(arr);" N; {3 f# S. j

    2 d& d" \% h3 G    int* tmp = (int*)malloc(sz * sizeof(int));8 ~0 b6 Q% X( P7 c9 V
        if (tmp == NULL); g( i( Y3 G" z& H
        {
    1 V" _, K( }5 Y, P. w. p        perror("malloc fail");* h! r7 S# P9 q# j/ Y- p- `
            return;
    % m3 ]0 m: k' f% Y0 y  e* e* v    }3 Z3 T& s! G5 N  T+ }

    7 O& G9 I4 [6 v1 }    int gap = 1;# |4 o* D/ t' ~4 Z0 q8 J
        while (gap < sz): K9 ~5 T/ s2 E7 u3 e; e6 b& M1 T
        {
    * }' _4 \& H$ N! ]3 q& M        for (int i = 0; i < sz; i += 2 * gap)
    4 f) ^* h! G( M9 y2 p$ @        {
    7 i( W# l: T/ |4 c0 e4 v! }* h' x' S7 i            int begin1 = i, end1 = begin1 + gap - 1;
    ! Z% ~) d# b4 q+ z: q8 S. ]) t$ ]            int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    # V7 i: P  F( m8 Y  A. W3 C            int j = begin1;7 D7 F- L( H: o$ E$ e
                            //越界检测- p6 J6 [0 b2 j8 N7 J, f$ A
                if (begin2 >= sz && end2 >= sz)3 F/ D9 E5 c/ w7 i
                    break;
      z3 l* v) P8 ~" _& Y, D" G0 F: Q5 C            if (end2 >= sz)# [6 F$ k8 L) o6 ?& S" K
                    end2 = sz - 1;+ z0 `' B+ ]7 J$ ^* @6 ~
                //归并
    * ~( ]# B2 E1 t4 O            while (begin1 <= end1 && begin2 <= end2)
    ) k. F# C; G% m            {
    # N( {+ T1 F+ ]3 `                if (arr[begin1] < arr[begin2])
    & J& u( I$ n# c! P6 z                    tmp[j++] = arr[begin1++];
    7 f) l% _5 x' S                else     
    ; O$ t( a. Y2 o: a, O0 o, }0 ?                    tmp[j++] = arr[begin2++];' x8 }. N5 \. p4 u/ }; j0 Q+ b
                }
    8 [. N9 l/ ?  q/ X% s3 ^: ~+ z1 P3 I1 d/ K- I5 u% t8 A
                while (begin1 <= end1)+ k9 ?6 F3 h( K1 m
                    tmp[j++] = arr[begin1++];( D- g& m% R" S$ |/ @
                while (begin2 <= end2)
    / p7 M( b" k1 F- M4 b1 B" l                tmp[j++] = arr[begin2++];  E/ N1 \# h* m. x6 K/ `" A( b

    ( \% _# ~# c( ~- A) Y1 j            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    1 }7 v3 U3 w; U2 p            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    5 S1 N+ q. g+ _5 g* [        }% {1 J$ S4 f3 `4 L/ ^6 S% o
            gap *= 2;8 j2 p/ u5 B- z
        }9 z' W; x& s; c$ X. n; t

    0 I. k. B+ j$ A}2 I4 I( G. S  |: f4 Q0 l1 \

      b, t. j( L! C$ G' n1 y1
    2 x/ {; Q; d- O+ x, J2
    . a" V# E) G6 P, |! ~2 c3
    . D) e! n. l" |! y9 u+ E- W4% r0 d3 o! T, p4 }
    5" p  ?* K) R8 b0 c. d
    6
    8 O- w$ `/ E" a* M1 ]7 \7
    5 a. S5 ?# w1 `8 O) D! [8
    " l# a/ R! i: E6 T$ Z9
    ! d3 Z' @" ^! e! B/ F10; U) S+ g, ~- ^( J4 v0 n" o# F4 k
    11
    1 T3 D2 m/ g  x2 X/ {# u% W/ Z& G7 c12/ I! d2 h* T: Z8 L
    13
    " ~& D+ Q* M: w$ o8 w3 d9 G14
    * X2 Z& v. @5 G; ^0 _; e2 G15, F2 B6 t6 X; |4 z* H3 U5 \0 I0 P
    16
    5 e8 O/ O  M2 R9 C( Z. S" o17
      V8 E$ ?, D8 L" ]! s- e1 _" }18" A2 V- p) _$ P) U" g# L  t
    19
    $ j& u% [+ d" J' [2 k202 q# E9 G( j! G4 A1 H
    21. ^3 `: x( e! a% a, T3 r* H4 j
    22/ S! T8 z7 B2 A
    23) _$ j" F# c5 T+ I& ]7 u2 l' O
    24
    0 W# t; R. }2 h+ Y" o25: y: n+ M0 M, Z
    26
    ' t# c/ I. A( T! N! W3 i274 C! X$ B% j+ z+ R2 ?- a- m$ t) H
    28' }, f" X0 g, R3 {7 C  M
    29
    - A! \& ~+ ]5 `$ d4 Y; b4 f) ^30
    ) Y- V( O# {! @: d1 U% v: \31
    " v; ~3 ~: `# ]+ z- r325 g# w  ]( }; J* G% {" y
    33
    , h. S( _8 ^% ^4 ^# t# Z2 C346 N' U7 C4 E0 g. A% u! _' [- c
    35; m( i$ p; L% ^7 T' Q% o' @# v% d
    36; q% @7 A$ ~1 T4 O8 u# ]
    37
    * N  ?! v, u+ \38; U/ b7 S" f; k7 p8 N2 P2 J, z' n
    39) Y5 ?* G) V" \, Q
    40$ Y! q3 v0 P/ g) p" e
    41
    % s7 J2 E) @/ B2 H8 U42
    - M# O- S7 W; _2 x& d& K; S3 `, T/ b433 ?% s9 D; B! E0 s) U
    44
    5 G- R  z/ u/ r4 r- q( U45! D3 S) K4 j: ^  {( }
    归并排序的特性总结:) S5 F9 q' d8 T; u" ?# |

    5 m) x+ R9 R8 G: V6 ^* ^0 G' r归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    - p4 y/ w& Z3 f: P时间复杂度:O(N*logN)4 T7 N: I; r" W
    空间复杂度:O(N), u# o" o7 ^* ?# Z7 i
    稳定性:稳定! `1 d  O1 Z' [9 g$ u
    ) a; `6 E2 x) V' G
    ————————————————
    4 |) l  w4 w! i' G+ F# a. z5 M版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& r3 D( B# X& `3 [( N# O- [" Z$ Q
    原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657, f' c2 \9 S0 q8 ]
    9 |, k  }/ t' {) o$ i& h7 p
    8 U8 q9 D; j0 F. x( y" B
    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-7-9 13:31 , Processed in 0.705578 second(s), 51 queries .

    回顶部