QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2214|回复: 0
打印 上一主题 下一主题

[其他资源] 【基于C的排序算法】归并排序

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

81

听众

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的排序算法】归并排序
    . j* ^& Y, n+ H! W1 b3 v* @7 z* y# i  F; C/ J0 p
    前言
    . J- _0 W1 d! j5 r9 K* m- ]本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。! n2 m, F: ]( o) D- `( u& I6 T  P& P
    8 ^9 h9 m8 ~- N! H/ l; R
    归并排序5 ]4 V5 h: [& A5 o
    基本思想5 x% ?$ |; i9 v& o; b
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    : ~: X# S. f2 h1 B) z+ q  h: M$ _. u
      ]3 U6 X$ S2 q6 Y9 k9 K0 k

      N  B& `% N! u7 m: x​ 合并的思想其实和有道题目的思想如出一辙:) A' @. J  a, r! f; w

    8 W" O( t3 e* A! u& |9 i* @* h/ `) |. I

    ( P+ Y6 s  k# i5 [6 g​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。
    5 j: {0 R- N2 ^: V2 @
    2 q  I2 E# W; J: T- X[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    8 G( T! O- @1 o$ O. T8 Y7 W8 F0 s$ c+ N+ B3 K' v+ c! S+ {
    int* merge(int* nums1, int m, int* nums2, int n)! S; w* j; p0 i& ?9 G
    {3 v; p8 t8 v: F& D1 D
            int* arr = (int*)malloc((m + n));/ d3 c' i$ h! q7 I3 S! T
        if(arr == NULL)
    # S6 a& u, V- q" u$ [! W    {
    4 Q0 X. D4 _0 Q3 g6 S3 n, P        perror("malloc fail");
    2 t' n: i+ D7 I1 _        return;
    8 e4 T+ E' R$ r, }$ ?& \5 y    }
    " w4 Z" g* P$ D( o
    0 c6 e! L4 q, i. F7 C6 X: B. Q1 ?8 `    int p1 = 0;
    , x: H% C3 T2 ~8 r2 |    int p2 = 0;
    ( k4 ?; {; ?& E- M' w5 d    int cnt = 0;
    ! R; r. u) W; b" u4 Q! i    while(p1 < m && p2 < n)/ \1 p( R, ]) ~/ O" M
        {. F( R( H2 P' p% k; K( `
            if(nums1[p1] < nums2[p2])
    4 b0 E1 r) w  J' i# t        {
    , L9 ~$ H8 |2 c& E# n( W6 v. q            arr[cnt++] = nums1[p1++];* g' H, |- P. B+ `* Q& z
            }
    ! W8 S+ z7 U; m" z7 C7 N        else  [2 L6 z1 }7 N9 Z, ]4 Y
            {2 n+ \* |6 V+ ^
                arr[cnt++] = nums2[p2++];' v) B( x- w6 k) N
            }. \; p, |8 L8 H
        }
    2 S+ ?' A% ^; V$ G    while(p1 < m)
    2 [& v! f/ j; K& f" k; u$ F1 `: S        arr[cnt++] = nums1[p1++];4 l, Q5 _% F7 n& V) E4 k- [, p

    1 R7 ?( e! l# P" y8 Y* k5 x1 |1 D    while(p2 < n)
    1 R6 o0 [& k0 u  k- Y        arr[cnt++] = nums2[p2++];
    6 s  P/ u5 `) x' _( v0 a* o$ a' C; \4 G
        return arr;: I' r+ y8 J% G! r, Q
    }3 j; T- X% n& B" {
    + }$ l* P7 L! R* L2 X% L6 x: q' F
    1
    3 f4 i; k6 ?/ b2
    3 ^4 q1 {8 e. C3" I  T2 K$ m) P, s5 e9 }1 d" s3 }
    4- w2 ]6 b4 Y$ f' _6 N! b, k  h8 q
    5
    0 K# z4 ^% H. B* B# x8 m& y6- D3 S+ H8 A# v6 ?
    71 H0 u, M3 u, ^
    8, P( s" z* O! r0 }: K5 e9 j, e
    96 q) a2 E1 d. p' g) ^6 C2 z. A7 w
    103 s; A4 E" {1 |' I" }( H# L
    11- T- x# K8 Q9 ^
    12
    ' D* c' f5 u4 y* R131 H7 H; s$ H1 U; i+ t* Y/ ?
    14
    % p) Y. k' _, l15
    + e8 h) E0 M+ w3 s2 Y; i* u1 K& ?" Z- u+ i16
    6 R  e* s9 K7 _4 T0 ^6 p17
    ) [4 \) L5 f- V7 ^9 w( o18
    ! e9 ?2 n7 g0 J% K$ ]- U  E19
    5 X* @# _+ V3 a20
    ' p) r; J8 ~6 `3 d1 R- e1 k4 b# Y21$ C5 B$ |/ ?3 D% y& b3 @" u; M
    22
    % W/ ^2 t1 u5 \  f- ]- h: O$ c8 Y23. C6 [; @/ f( U5 Z1 M: N
    24; N( U( p# S+ e( q) Q1 A, J
    251 t% N: {3 {2 T+ T: F5 S2 m& }
    261 u* M/ X0 r  t- x
    27
    ( T* V+ N, ]0 K" t; }8 K1 f28
    + `& n. {$ f9 D, ~1 N. R29
    ( u/ I* H2 ?& ^5 ?$ M30
    1 h9 O/ r, L6 M: y31; Y; `8 S2 K; I6 Z, w( m3 g& U& S
    ​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。) C- }; w8 k1 ?. `: a
    4 j; t( T  Y- A
    递归实现
    * f6 a3 v( @9 Z8 `; s$ J. I​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    1 x* H( x# U/ V1 f5 M! a! H' [( I3 Y' @) t' R# U
    7 j/ R) `7 u  j* ~/ y3 U6 Z* B( e) j

    % l, I3 A0 j, f$ O' x9 P' J3 a3 g$ |5 b2 A6 O
    8 Z8 E9 H6 r' ^
    void _MergeSort(int* arr, int* tmp, int left, int right)8 N5 `& Q# ^7 Z! @8 y. ~
    {
    " R7 c! v/ A3 M2 w    assert(arr);: ?( F# x0 s/ ~  g$ H1 t

    / ^; k$ f+ _: z3 c! g, i  u    if (left >= right)//递归结束条件不要漏了
    ( b, q, K2 O/ s. V2 D        return;5 f3 l( i+ W9 Q, _5 S/ o) X

    6 x- H, B8 Y; X5 w2 o; F    int mid = (right - left) / 2 + left;- A; t  U4 q, E$ r$ S

    * X6 A% N/ D  P$ E3 {: n    //划分左右子区间[left, mid]和[mid + 1, right]2 M+ S, g& I) P- B3 Y+ x
        _MergeSort(arr, tmp, left, mid);
    9 z  u+ [6 v$ y( w, i    _MergeSort(arr, tmp, mid + 1, right);
    / A5 ~4 Z7 J+ _9 r1 e) i% V! X  L, x% m0 w) v
        //归并
    , }* ]) f. I% U5 t/ y    int begin1 = left, end1 = mid;
    ; Y0 m  ~9 w+ g& ~# E, i/ d" n* G    int begin2 = mid + 1, end2 = right;1 `3 {/ |7 t* D: L* }1 Q$ B6 A
        int i = left;
    4 I  P: Y( m6 \" |. R% P    while (begin1 <= end1 && begin2 <= end2)4 r$ B) J+ b& q5 ?* C  t/ g
        {
    7 u  r9 K8 a2 J5 i! j7 d: k        if (arr[begin1] < arr[begin2])2 v5 `5 E9 S; P+ `
                tmp[i++] = arr[begin1++];7 b! W! L) G& V; d  R6 Z
            else# j" c, q+ b8 E# \5 _3 n3 [
                tmp[i++] = arr[begin2++];
    % I5 {! f! ^$ J) l' C. o    }9 J; C7 Y6 H$ i+ D

    . P2 l3 t8 [9 T1 ~( i    while (begin1 <= end1)
    * M  D8 Q: y& _1 R, h+ y$ F        tmp[i++] = arr[begin1++];
    7 G7 @. ^4 A9 `. H    while (begin2 <= end2)
    1 ?: k5 l$ F1 C) s6 E        tmp[i++] = arr[begin2++];
    0 `9 @$ |$ g& j4 i, v        * e5 r3 [$ z) s& j
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    # b$ S  e$ I1 A2 g8 `% [) O5 z    //而不是拷贝整个数组回去
    / T. S) Z' J; n    memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));9 y( y$ G- D& j
    }3 g& N) I3 P8 W5 e

    1 i' ?$ }4 K' N3 k+ Tvoid MergeSort(int* arr, int left, int right)) g2 g. k1 X+ \$ l% E8 V
    {* |7 X5 v4 F0 H
        assert(arr);
    0 |; [: J+ r% t7 s$ ]; F8 T
    9 S- B+ U! q9 o; @: T+ ^    int* tmp = (int*)malloc((right - left + 1) * sizeof(int));! L) y% [/ q, ^) V8 G. c  ~: S
        if (tmp == NULL)# w9 {- E0 {# N# ^9 U; |3 n
        {
    # y+ D9 h! H7 g  _4 S  p        perror("malloc fail");
    0 l3 T& O! `& m" d% j# X$ q        return;
    2 g, O& i0 T: o4 f  M4 U1 z5 g    }" l/ p* q: E( \- y

    & Q& t6 l* A5 O3 D: t6 Y5 U    _MergeSort(arr, tmp, left, right);
    4 w" P0 A) Y1 y. _
      f. y8 o5 X4 }8 Z( b/ \* e0 R    free(tmp);
    % D1 f. f: l* S! \4 J# S8 S2 u    tmp = NULL;
    ! x5 I: f; J# a1 B) q}
    ; I) m4 w/ N; h4 X
    * |" o; Y/ ^  h( p/ S- k1$ l6 o* x2 x0 L7 X& H7 d
    2
    % Q; D1 @) z: J% N3
    , f# P. @% I9 f, b4
      h4 J* O0 y& d6 x5
    # N# Q& F0 [6 Z* C' n66 Z5 S' o* q$ [$ W
    7& }6 s6 b8 i9 y' \, t$ H( X
    8
    # C9 _  h1 E4 S9
    , z* u: m7 V; s( n10
    # n! p) M+ b1 I: e) O11
    ' i- w" X0 i$ e& ]0 O" f12
    8 z* f9 G, u+ p/ H13
    " C/ \  L) b0 G" Z* ~14
    % G8 E3 d. P9 m1 G9 z152 L# O: [* r& Q6 S0 Q2 A
    16) ^' Z3 }8 o2 f4 C# o  l& v9 T
    17$ L; r) l& X; o  q. i
    18
    5 G. G* K6 y8 s5 C  g8 \19; F' v9 L/ W7 c7 b5 _4 E8 q& Q/ z# P
    20- ~8 w1 ?8 N% P4 i5 v- D
    21& W/ N( D7 k# G- j1 r1 @
    22
    ) o! s$ Y' \  M/ e23
    * h, c8 m" n/ ]/ d! G( d24
    ' g* r/ C5 J0 R. @2 w251 f8 ?+ w  M& F* Y% J* z
    26" P/ n# J) a# Y  R: E2 H; U% F3 V
    27/ a: M2 n# X7 j
    28
    " T# V: P) R$ ^; S- S9 q. r6 K29# y0 ]4 q; U- t( D/ V$ {2 W: I+ ?2 l
    308 y5 `2 V& L! f. p* ?5 L1 ~
    31* P, _5 a% p3 C, {
    32
    1 G8 j# m' V1 j) k1 u. w33% t3 k' Z  ]3 D  l
    34
    & B) c- E* R$ e* Q% V350 Q/ v( e/ `6 i* `, F; t; r- i
    36
    # {; i0 r: N) i; D( v6 o7 m# H, w37  q/ `) Y/ S8 C" @- Z5 V0 N
    389 ?) G! F3 h% K( C1 N7 q* [9 n
    39
    1 c0 j! P( R5 }& \: Q: ]40
    9 Z& N3 Q! [* p  K) ^* F7 g6 O410 A8 j4 @; U5 b" z; V7 {9 h# Z1 i
    42
    . l# J( P3 C% ?2 Y7 z43
      ]' N0 y; g2 v& Q44/ P9 S  q+ t: a6 h" D0 O+ D. H
    45
    & k- ~( }9 Z( P1 l46, T" l! B+ t& n
    47) g# G* H8 B8 v. w! [7 f4 F
    48+ y8 F# C  Q6 T: U$ j
    49  v1 h0 a. y& A
    50
    0 I! V* j1 a: o3 x514 B- K; F; h6 s
    非递归实现
    ; c8 Z! v8 A! H4 L0 \​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。0 S( D$ E/ h/ C, d- s7 c

    ! G5 W# o8 _  \. E5 E* w3 l1 Y
    % U+ r7 l+ {# u1 z/ w
    7 }2 W- s6 [, L( X# ~5 t​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    1 P" Q/ C4 d+ j! D1 M# o* q$ W% }& X+ n* _# \) G$ b$ p
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。. F2 ^9 B( [' J$ r( l
    2 Z# T2 f1 \! i8 C& p# F5 h
    ​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。4 l1 l3 W! f( k# C; b4 Z; e
    * X8 U8 J% o0 L, D+ z& K
    代码实现. H# q9 l: b4 w
    * M# F5 C8 C* K: n) x9 Q
    void MergeSortNonR(int* arr, int sz)
    # @0 F8 z( l4 L/ }; B, U  ^{
    $ p8 _  `, j" u8 G' C2 q8 N    assert(arr);8 ?: j9 h8 D2 c

    3 p, y' g" i3 X% {* f. F( A& l    int* tmp = (int*)malloc(sz * sizeof(int));
    $ ~5 q% P9 D. w1 M9 V    if (tmp == NULL)
    : g1 Z/ Q6 v$ c- V; \    {/ C/ U; U4 b1 Y5 n7 S5 J" J
            perror("malloc fail");
    * ?$ x+ M3 y' t; T1 u4 i) }/ C" |        return;: _( t3 b5 K/ w* E3 I
        }  d1 S$ R+ v6 T( {7 W
    + R4 h7 k. o6 f1 x9 I
        int gap = 1;- \( f% \$ o& ^! s4 M& b0 Z
        while (gap < sz)
    $ }& |/ J# P: t5 O. q. k1 v( J+ S1 @0 |6 M    {: E( @- A% `' a- S/ Y& q
            for (int i = 0; i < sz; i += 2 * gap)( U8 P5 ]9 v5 X: F, f8 ?: _
            {
    : G6 \* r  Y, f            int begin1 = i, end1 = begin1 + gap - 1;. I" V5 L( D1 P
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;9 i0 I2 Y6 i" Z1 i5 j% l
                int j = begin1;
      H* G. n# B" D  h4 y) V, b2 ?% N) ~# |. U
                //归并" v- V, @" d, v" I  v- n
                while (begin1 <= end1 && begin2 <= end2)$ k  @: j$ Z" m) X& T1 j
                {; r3 l: p3 m& b( ?" N8 N7 Q
                    if (arr[begin1] < arr[begin2])3 V2 A' Y* D% V# j- Q6 L, O7 L
                        tmp[j++] = arr[begin1++];
      R' W8 p' N( E2 M3 n, [; g" A                else     
    & x+ z% m7 J5 A9 ]. {9 W                    tmp[j++] = arr[begin2++];
    ) n$ l9 F0 B  Z4 M  p* O. _            }/ b! K: Z8 f' H& D+ ]* i$ y
    1 g4 Q1 j% t; h- T
                while (begin1 <= end1)1 J% I. n0 h9 i- z
                    tmp[j++] = arr[begin1++];
    : d: _* y9 C1 u" O# K( S7 o            while (begin2 <= end2)7 J7 R5 g: Z' Y* L- C
                    tmp[j++] = arr[begin2++];
    : \, G# U9 _$ ^" r4 E# S! G
    ' A" f( c" F" N: f            //拷贝回原数组——归并哪部分就拷贝哪部分回去
    6 s0 M9 M9 o6 D' j, O. d            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    3 h8 m: D) Q% w" H6 }* p3 i        }% s9 f4 t; {! Q
            gap *= 2;
    ; d" I& x, f4 i5 c, y) u    }
      S0 x  g* G3 r& h$ {+ ?* f3 @0 o, m6 @( Y: d+ Q3 _
    }
    6 V3 i1 Z7 v# ~' a$ M9 s% p) h
    " n* i( b/ U2 [% S$ s8 G& @1# M' m) R! s) y9 C$ t# A
    2
    ( t: p4 i8 c4 g: ?# l3
    % _" A; \. d9 N0 _$ m* h4
    " r/ U+ t( J# J5 A54 Q$ n" Y, F6 C/ J: p
    6* L, R2 H8 e- ]5 c8 p
    7
    ( i9 @: a$ d1 o2 Y- ?8
    6 m* z5 c& Q) s$ {9% K. M  J* X2 B4 }, g9 I* w
    10
    % w" J" {. Q- k% x$ Y1 o5 `2 C11/ J' l: V5 {+ S' k; g4 c4 `
    128 o. Y) U) R/ l" J, c4 X3 T! ?
    13
    * K0 S9 [" @* O" V14
    8 d4 j% R5 Z2 s, I8 O' b& A15
    9 M# T1 q1 z: o) D  t166 I  A) x0 [7 i! O+ x: r, u
    179 x3 H( g+ D% q) Z
    180 ]$ e% c7 v, E* t, x. i3 r
    19: L0 W$ y, C( P7 K5 l
    20
    ( G$ C" u, U# h3 `21
    . o/ S/ A2 k( ]22
    ) s2 `/ J$ T& ~: j239 j2 k$ V: x4 _# p! B# b
    245 ^( O. ^# k/ A7 n7 d4 M
    25/ w) M, X+ F) [5 E4 w- ?0 Y
    26& T# g3 [/ X6 s4 `0 z
    279 n8 O) F' J8 Q. a. E
    28
    5 L' _7 g. {# F3 y9 F9 X7 m3 ]29
    % S$ _0 F4 U! k" }# V% m30
    % g! n: W* r7 Z& \& v2 Q- Z31* q) @) R8 z8 V  Z
    32. C) \( M# U; Z& Y9 {
    337 U, I' e! P7 U/ |. L- I9 s
    34: O; E3 [$ I* R9 j( ^. H( l
    35
    $ D8 L8 v" ?  L( q, j" W3 `+ E365 Z; n9 Z) Q0 T# o/ r6 E9 p
    37
    6 p$ E" `4 B: X  P$ i/ d2 P38" Q) l) H  a" x6 ^! H$ `2 H. j# I
    39" L8 n4 S. _6 ~+ h) _" J
    40' C+ H- x  z5 _  W# w4 W! s$ _
    41. T  N" D* U2 w4 @- h' L
    边界问题
    / _; p& P. O/ w3 ]. @​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。  g# a, j9 s% h% U- Y% \$ b) l8 r$ G

    " h, g/ t* N7 S8 ^/ A0 W. q0 \. d) L举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:3 D; r& c- H# P; f* e7 B

    ) s5 {% u- `! V, s  G8 E0 \
    " B0 X/ ]5 |: g; n. G! w8 U& y1 Y" ^9 K+ S/ Q
    由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    * N; I9 W" R" e* O( J( |7 H! ~' P  ^8 b% W0 X/ \2 D  _7 e: d
    第一组越界(即end1越界)4 V; @/ Q3 \; n2 j! O$ B8 [
    - A- x3 a( Z0 F) y5 E5 j% s6 `
    应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    9 _) f$ u3 v- u. u+ y6 n# r
    - _- A9 C( N/ g" _9 \第二组全部越界(即begin2和end2越界)
    # ~6 \6 K, j2 s! D& _
    * k6 f: c9 w( h3 H3 D应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。. D7 z0 _5 l. L+ l9 j0 |8 v8 p

    ' m/ S3 z0 U( C& m第二组部分越界(即end2越界)  }5 ~8 m3 h# F- ^
    * C5 i0 G! c: w8 o  X7 {
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。1 T/ ~( o2 V$ s* u4 x
    4 c" C( x) Y; H3 m' a# ], L
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:3 ~: i! A" b: U8 q

    % P7 ^5 S4 Y9 z9 ^/ O​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    - x, O5 t" r% g" _6 h9 R, h! _8 e& g/ F# @
    ​ 拿两个数组试一下:
    ( k% Q9 \* Y& K; K3 g/ ?' h$ W
    1 ]: a" j" {8 |) m2 O/ K; `3 ]8 J, q3 t: f: x2 ]% T

    9 V9 Q! r4 I! \" E: \- K: \$ X+ t* |

    ' K1 q+ \7 G/ J  B代码实现; E5 F+ L: G- Q3 y

    ( r4 G3 }7 S; u+ fvoid MergeSortNonR(int* arr, int sz)
    ( o4 M, q; D: \. V% m{
    1 \2 C8 O( d" P3 S    assert(arr);- R3 n' _9 E6 L) E/ g
    ) e3 K4 K" i& Q: K
        int* tmp = (int*)malloc(sz * sizeof(int));
    + G- x0 A# o) o/ K    if (tmp == NULL)
    ' r+ ~( D% \, K& z    {" W7 W# ]* v! A# o
            perror("malloc fail");* h0 \7 L0 r7 `
            return;
    8 F4 [/ V* f2 B  D& F+ L1 v    }
    $ k, Z  o2 N4 s# @
    1 L& B/ u; E, t$ J  J8 B$ f    int gap = 1;
    3 _  i9 q4 E0 j    while (gap < sz); v2 a+ l1 R- z0 w2 b5 z+ C7 m
        {
    0 j2 [0 R# G. t  m        for (int i = 0; i < sz; i += 2 * gap)5 h! A, |! c* k6 k+ @8 y
            {( x3 h* l) D2 o9 C& T
                int begin1 = i, end1 = begin1 + gap - 1;
    " ~# {' @6 [% E            int begin2 = end1 + 1, end2 = begin2 + gap - 1;% X) k9 p( C$ n! f8 _( r( b4 w) o
                int j = begin1;: t! G/ r# |. B* A2 X* |0 N- W
                            //越界检测' {# b# w9 Y( U% ~
                if (begin2 >= sz && end2 >= sz)+ D& h$ o  E9 M
                    break;0 M: [9 t; |% f' _8 C. E% `- R
                if (end2 >= sz)
    * Q% Y3 H$ ~1 P* Z- c7 g  P7 M                end2 = sz - 1;
    $ W# E1 w: a6 {. M4 C            //归并! r; o& }* @2 ^/ |% M
                while (begin1 <= end1 && begin2 <= end2)
    3 B& T' b) M( x- E            {; \& x  E5 s) a2 J: ^
                    if (arr[begin1] < arr[begin2])
    7 ?$ C5 A+ s' K+ U* T4 X9 x0 C                    tmp[j++] = arr[begin1++];- |  t5 P( L) s% K
                    else     
    + Y: ^8 i7 [: X' J                    tmp[j++] = arr[begin2++];
    " \3 S+ @, Z9 {- K6 r1 E( N% p; l            }: z0 |/ c- r% V2 g5 j1 d+ t

    , f/ o- }7 y' R            while (begin1 <= end1)5 V/ E! H4 J5 ?* n
                    tmp[j++] = arr[begin1++];
    8 d9 m' m5 U& F& u) X            while (begin2 <= end2)
    ! L$ i, l0 S% I' P& E; E. n$ `% e                tmp[j++] = arr[begin2++];
    # z- L; f. _$ p9 M. X5 ]
    . A* y2 l. Y: q7 b6 L0 Z! x            //拷贝回原数组——归并哪部分就拷贝哪部分回去" v; [$ Q& A) f# Y" t7 ~4 H
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));# |7 b* u% L, w+ T6 n: j. P* J! y
            }
    2 J6 x# c- Q* y        gap *= 2;
    5 G+ c# A9 I5 Y; M* z  k: U    }
    2 P! S# o2 Z  H
    ) b1 \* s! i0 r- E" I/ P3 g}5 Z% a5 U- N8 P- h8 P$ N

    ; l+ ~4 Y' z0 G0 L1
    ( {# ?1 U0 j4 ?; w6 d2
    ! c2 k4 }5 g' t2 A3+ ]  [. }3 V" K
    4
    + m8 s9 {2 Z0 }+ s1 Y2 H+ ^5; X. c/ |1 o) a$ r$ B- I: u# x" n/ ~
    6) E, x& ?/ g* L: X& i& P6 C7 ~8 q
    7) g$ w. U- T/ o3 Y: p
    82 F' H) Y6 Y! F% Z
    9
    3 x' r" X9 c8 v! Z10
    ' j) ~7 K9 U  H& Y( f" B( H11
    4 F( j* j2 t: m1 F12- b( W3 F! |* q, R: R
    138 e  b6 _. G0 J! r0 q0 J
    140 M4 `) e$ s8 H, ]- j3 N
    15' f& z8 s# v3 M' A' b
    164 C! S# D% P4 i! ]1 G: b
    17
    . |5 V, ~- A4 H9 |% k180 e+ p9 g  i+ X  w3 Q( s2 e
    19. S7 U* z' Y! I& z* f& w. c5 s$ F. m
    20
    0 j0 w# O3 [0 F21; L$ w, |% z& |' S& Y
    226 Z5 L0 ~7 Q% R
    23  }; S! {+ u) t  O" ^( }
    24
    5 ~5 \  c% _2 _4 M7 S9 m% Q& j25
    ) t5 \  w* ~  n+ }# }* A0 v* J26( N* [( o! i+ R/ K, E3 G
    27
    . ?" X) @' H* p) O$ [; W28
    % {  F4 M0 O  }' q8 ]- j29, R( p. f. z  b( a2 T# |1 H
    30
    $ |! ?; _& i8 ]' g7 Y% K3 n; }31
    # @, i# o, t$ d32
    6 N8 J- m( H5 b- C33& r, |- \& ~: \  H3 G: Q1 ]5 W& ?
    34
    6 n( K0 ~1 t! z, l6 E, B, U35
    6 w; F+ p6 V" V, Y+ g$ g36
    5 p7 a8 |8 q" e37: I7 F5 n% {9 M0 `
    38) `( ?/ G% z1 g1 z/ T: _% `! _
    39
    ) m: j. z" E( o) L0 B4 S40
    7 X  o6 ~, {4 t6 Y41" ]! N: C/ ]0 W& w0 C+ }3 n
    422 x+ p1 O7 J$ P3 e7 W2 \
    43; c' r% t* y+ t6 H5 {. g
    44
      h& I9 _1 c3 o' {) ^45
    0 Q+ h% Z" Z: L归并排序的特性总结:! R7 v9 ]. B7 n" T0 T

    0 f. W3 R( o0 T% S' D归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。' V+ R& T2 E( ^
    时间复杂度:O(N*logN)
    # E6 j0 y' V4 t: U3 ]6 N) e6 D空间复杂度:O(N). L7 C" p6 A1 G! V) U% Y7 C
    稳定性:稳定
    1 e; J  L% ^' R  i: ]
    5 ?: a, |" _% ?$ j6 r: U, ]: \. J, r9 S4 D————————————————
    % V# `7 s% G- L版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    + |" X  k' M/ @7 Q) V原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657, R/ ^- W: B4 G$ u, L7 _
    ( _3 n# ~6 m* N$ g
    8 s% o: n! C0 I& s
    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, 2025-5-10 09:19 , Processed in 0.625185 second(s), 51 queries .

    回顶部