QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3400|回复: 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的排序算法】归并排序; T! u. G1 S5 ]. _* I0 x

    * |7 T; p* Q: \: ], J; W前言6 S/ L; v: @3 V' h- R
    本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。0 E$ y4 y6 C$ p4 `1 a

    . d* o6 f4 b5 j, A8 F- Q4 }归并排序
    . R3 z8 Z  I' B8 {% \' V7 Z基本思想
    8 ?- q5 m2 U9 @0 t: U% P​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
      n. q( @8 a- t8 l+ n, Y/ G2 _0 }1 L9 U

    5 i+ E5 p3 l% ], j( i& v" P+ T8 e# C  {0 w! _+ k
    ​ 合并的思想其实和有道题目的思想如出一辙:5 ?% H, v& c1 b' b0 g( c

    ( z$ b% l3 @4 O) q8 Y& Q' P9 V2 M6 W1 X  X" H6 f' _

    ; T* b6 k4 f- X7 A​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。* e$ ?% s# k2 m% K

      ~* ?$ Z6 j8 y6 F" @% c& P[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]7 z8 P, Q7 s/ w0 S3 M
    - B6 P0 t- r- v3 ~  w
    int* merge(int* nums1, int m, int* nums2, int n)
    + b0 K. |* H  ~{4 _/ @. ]; v, o  t7 b+ _
            int* arr = (int*)malloc((m + n));9 w) V3 F' `# d3 M) m( M
        if(arr == NULL)
    . g3 E) w5 O& X4 k% R. g$ `% ?    {2 O' r' H4 m* Z' R. V7 |1 k. U# f
            perror("malloc fail");, d, \1 a& Q1 P  f* _# }
            return;  x7 g2 F; E" X2 ]
        }  }+ s% B7 B  z; w  j8 T

    ! m) ^) l+ r. ~' P0 d# O    int p1 = 0;( Z9 ^" p1 G3 ~
        int p2 = 0;
    0 u& ^+ ^0 k7 h1 m/ w    int cnt = 0;
    0 g' L8 g1 a+ H- l, j- q6 u    while(p1 < m && p2 < n)1 l1 I, k/ U6 t1 H0 C
        {; l+ S4 ]- S* ]6 X, Y+ m: S
            if(nums1[p1] < nums2[p2])
    ' ?8 }2 v  z; I- E* u% q8 \& z  v        {% M( q2 `" d1 v9 T+ f% B2 O0 A
                arr[cnt++] = nums1[p1++];
    ' y% ~, F- E1 r2 F        }
    8 B3 B  U1 }3 ~        else" H2 T) f6 G/ ~; ~) w4 h0 `
            {. S& S$ j# N* ^
                arr[cnt++] = nums2[p2++];/ W/ M2 @4 F/ X( v
            }; I. t/ {! A' z2 R% z
        }
      [. A( ]6 R$ H$ R. X& t4 ^    while(p1 < m)
    3 y1 M: r! Z+ l/ M- N, O/ `) @6 e        arr[cnt++] = nums1[p1++];8 v1 i5 W# k: b6 ]: ^  I
    4 V3 p; `. w9 X( ?1 F
        while(p2 < n)' f5 o# D7 i, l
            arr[cnt++] = nums2[p2++];( X4 y6 ?9 u* m9 t
    / p$ B3 ]; A8 b+ q
        return arr;/ E; L# K  B$ i0 |4 f# S$ \
    }8 K0 I% ^$ A" B& n
    & U$ h4 W( p+ n# [/ ?9 }
    1
    + E- K. v1 K( D" e- l6 B/ w2
    ; y! k5 g6 P$ x9 k) M1 S) e3
    1 T6 `' ?* v7 X/ S! L, T4
    ) `6 M9 S; ]( M; N$ I( D' T5
    ' q/ s: l) x5 c9 l; K6+ n* y3 V3 H# C
    7
    . T+ q! \: o, v) z8
    . P0 g) X% J6 [9
    1 Q# K( l1 L9 D107 g1 D4 s2 E8 l, T; V  t
    11, I! ~$ M. ?5 E: P3 }9 A- ^1 j
    12; a. @) I/ u% Q2 n" f
    13, c  Y/ w* z0 k7 j
    143 m! a, i7 v) J% ^* P* X7 l6 D
    15) M: {+ w# d4 Q  t7 m# E; }& V7 O
    16- D' }  M7 R/ d. {0 z( m
    17! t1 x1 N" n& o! t/ p/ M8 ~" B: y
    18
    4 w( C; G) p2 Q4 N' u$ w4 B4 H; s19
    3 @+ \0 w0 r8 ]& J" ~, e20
    : z3 ?% {; j% o( l' R& `, N* j21
    3 E: I7 u) N( h) f6 Z22
    7 B2 ^5 Z7 M2 B7 c: ?1 @1 d9 [23; p& x3 E& z* j) X2 {4 D
    24
    2 T7 S, y* q) \  G25; K" |3 G; @6 T- I4 G
    26
    2 X" x: A. v8 z( n27
    . j2 L3 L' K8 K' @% l, E28/ V9 r- K4 V  N
    291 R- y5 S* k4 U; B: W+ G* g8 D0 W
    30
    * b6 b. d5 x1 c31
    " m1 _- F1 i' S8 h' ?​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。( ?4 b% {4 i/ C7 @) l
    / Q! D3 ?" G+ @- A6 G  J" W/ d& u9 ]
    递归实现
    6 k" A' V* d, q  T. \​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。$ K$ f+ d1 W: }- `6 O' a
    & U, V9 q1 b% o; C) i( H

    & f. h1 N, X6 |% w2 o) _9 V! e4 o- _# H9 Y9 D% X& p7 M

    7 ^# b7 G/ Q( _* ~# p4 @& n
    # i+ ~) N8 Y4 T/ e; bvoid _MergeSort(int* arr, int* tmp, int left, int right)
    , X- J: c- f  t4 K6 I( V" V7 a+ N{9 A5 z( c8 \7 P/ I
        assert(arr);: P/ v" z8 |* C4 W6 _( k7 B1 v

    2 u/ t) k  b, v1 p+ m7 _    if (left >= right)//递归结束条件不要漏了+ s( _) p8 x+ X5 l
            return;
    + l" O* ~8 \$ m7 P
    6 \& \; U6 F. q( L" m0 W    int mid = (right - left) / 2 + left;( B: g- j# i2 u' x* N
    6 ^% S* ]9 f- ~3 \: Q* m
        //划分左右子区间[left, mid]和[mid + 1, right]
    0 `' _4 d1 P) o7 f* J4 Y. A2 V    _MergeSort(arr, tmp, left, mid);
    ! ^* C: X5 @; H* ?* M6 \    _MergeSort(arr, tmp, mid + 1, right);& R1 s( B0 n* G9 u/ Z

    8 o# q# H! {  D+ d- M* S    //归并9 N8 ?, b6 s% Z: e' w. b  |
        int begin1 = left, end1 = mid;# I' A: }% s2 \* R5 D8 N& x
        int begin2 = mid + 1, end2 = right;
    0 m  z- C6 ^+ {! B/ j/ H    int i = left;7 `9 Q, b3 g) r6 N3 C& D. h
        while (begin1 <= end1 && begin2 <= end2); Y" o# E4 p# ]6 y. t  _
        {8 A8 w4 s- n! }/ _
            if (arr[begin1] < arr[begin2]); k5 X' J$ B* F$ w4 ?
                tmp[i++] = arr[begin1++];
    & [' f  k5 }" x  Y        else4 x- H6 v: w6 J. i
                tmp[i++] = arr[begin2++];
    " B2 M6 y& `) Q' ]* f1 z    }
    * ^+ w' f% |0 X/ X
    ( ^8 [; I7 Y! y# L+ K' |    while (begin1 <= end1)
    # x& v2 H* m- i7 V- E* p, o- k0 p) x        tmp[i++] = arr[begin1++];- S- H% n+ m2 J0 y4 w* T
        while (begin2 <= end2)  U0 ^3 Y' `6 i1 ?! l" `& T( B
            tmp[i++] = arr[begin2++];! N  S# s- M# C
            6 L! t* x' F! h) c, s
        //拷贝回原数组——归并哪部分就拷贝哪部分回去
    0 ^! b1 L/ l; x8 X2 W; P! H    //而不是拷贝整个数组回去3 F# ], s% u" ^: ]$ j$ o
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));4 z: A3 f* _1 ~/ a, ?2 H
    }
    0 [9 c, f" x" J) y7 O$ {5 R
    ) c, e, X9 V* ~7 k2 Ovoid MergeSort(int* arr, int left, int right)
    6 t4 r; @8 W0 A  V{
    / R6 h* d- B; B0 A6 S; `    assert(arr);
    ; v: f& W5 U) i- z7 w0 j1 e( h& }3 O; z" T( r* u
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));
    % G: Z" J8 H# n) v    if (tmp == NULL)
    4 T/ e  E) Y; i8 `1 w) w/ G; h    {/ d. [; M7 u! k1 J2 C
            perror("malloc fail");
    8 I" J7 B6 h: j" P        return;
    # Q2 h5 [7 _6 D8 \6 e$ M4 w2 i8 C$ `    }
    % \( x( _; U1 o! u7 @. s# S* J  E  g, z9 r7 f' ?1 v! I% L
        _MergeSort(arr, tmp, left, right);& L' T3 p( l8 N% ], E
    * B0 k% t7 `3 s6 B6 A# M7 A
        free(tmp);
    ) U7 V3 J: J- z0 ?1 J% v) P    tmp = NULL;
    5 W+ Q; x2 y* x}! T4 a9 x3 N$ U. h; Q! K
    # I7 n( n( P- T3 f; t2 @! f
    1+ k* {+ f) P& D
    2, q) ]% r. f7 A& A
    3) p9 g% m  X# \+ m7 n1 U1 o
    4
    * [5 b" J. T" g4 T) ]- d5- A9 y5 A: g7 `* O6 U$ b! ~
    6! A( ?4 m# d  J2 Y7 s! T% h! K2 |8 c
    7
    8 @7 H- ?' O( O7 m+ |85 o1 H% v) L$ n9 f6 }8 W
    9
    # x" t5 z& m- u% B! l0 a10
    7 c1 R) u5 h, P  Z- r" [11/ X  u9 H# U( G$ y& D, q
    12
    , }% `. Z) h0 B. u. m# F  _0 k4 S139 Z& G7 z; G$ B# F, U8 ~
    14
    $ m2 x& r( U! T7 W* \15/ L( m& {  o% H/ N
    160 T0 {% q- I3 B. R& b* w& _2 v) c$ e
    17' C# Z% |- |$ s. Y
    184 O9 i+ D, g. b. \
    19
    6 O- R4 u3 \) x' h- q20
    5 I+ `- h% E% W& r21
    7 [0 g1 P% {2 Z/ h8 m226 v% ?# {: W( o( h; f
    23& b: V2 b* Q  s- j9 I
    24
    ; Y" x; ~3 H% ~! G25$ u! ^/ l8 b1 y! ]& s
    26
    ! _: X9 U3 k: p. C6 l4 R27
    6 N6 K& q/ J: L3 q28
    0 i4 [8 O7 U- n8 M  R29
    5 _7 f9 J3 [' P+ v( b30( S+ R8 ]9 S7 C5 @& r- S
    31
    7 Z+ y" m$ A% Y" h# i4 s32- b; C5 |& P: i9 ^: G( h$ w3 w
    333 l: ?- o$ X) ?: [# K
    34
    7 N5 A, v- |  i+ z( P9 w35
    8 F; |: G0 M) k" {& h36
    1 y$ B' Z" {5 W8 K  N0 ~1 I' l37
    , l  r1 b6 v( R7 X& D38
    ! R5 ?7 t* `2 p+ ?397 C' s; n0 A) \
    40/ O: s( T4 b9 m: A4 E6 f  Z- q1 a. u
    41
    ! z+ c8 j4 q8 R, p0 e+ F42& `6 q0 J, S6 }
    43  k1 D8 [( P, I5 ]. @
    44
    + y8 U0 L- ]7 }* }: k' ^" m  e  ]45
    4 N3 |! _  C0 d- B1 ]5 Q46. W- n  A8 z" h+ n! R* @
    479 w. L7 V6 _  G; v% _  P
    484 U3 z" U! }. p4 g  e
    496 X" T2 f4 J  U& ]" ?" T0 K
    50
    ; V- U1 Y- b; P, m5 o! {51
    & Q( z; v9 O$ T0 ~非递归实现
    + K, }; N, e# \& F. S  a+ y​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。: ]' ^9 u$ B3 r$ U6 f
    9 @. n( p% L, F, f& g9 K6 H; b4 Q- e
    8 c' j3 H% E* W3 R
    9 _0 j) c& q+ d" }: x. i( t
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。
    ( |  w$ W; s3 D3 E; w, s. I  b( g; D
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。
    3 j* i1 b$ P" d: P
    ' w5 v  N" }. ^9 B2 p; g​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    / o  |3 p( S, q& \7 d3 L
    0 g& y$ F$ u+ R; j5 U) [代码实现9 l- n) I& z" {1 y! v, s$ `$ [5 q

    * g' e. z4 K5 a: E3 U& E! \void MergeSortNonR(int* arr, int sz)+ h( Y) c8 F* P- o9 e
    {3 L+ v1 L: H8 s/ `" Q! U% Z+ G
        assert(arr);
    % d9 W8 v# U/ M
    0 Z7 h. E" L) E5 N2 A" |& B- N' k    int* tmp = (int*)malloc(sz * sizeof(int));
    $ N  J! ^/ j7 Y+ c) q0 g    if (tmp == NULL)1 T! i- [7 {2 `% Y! U* y
        {
    & ?: d: a9 L- Y5 E        perror("malloc fail");3 Z) e( v1 r3 Y: Y( {9 |3 N( l
            return;% f3 A/ K% ~! w# c& M2 s+ Q' _6 z
        }
    . j5 `8 r, p- Q1 `, M" e+ z: C
        int gap = 1;
    7 Y5 L/ P2 M; }- G6 o1 O    while (gap < sz)
    " v7 U' q% r/ ]' J- G    {: O) o; c' L, o
            for (int i = 0; i < sz; i += 2 * gap)! M  J7 ^. Z1 \! T% q* r  M
            {
    ) q+ q. j( T/ S' o4 g, `            int begin1 = i, end1 = begin1 + gap - 1;9 b7 P- t- q% F/ p/ H4 T! ~( k7 m+ u" @" w
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    & _0 e6 u9 _, A/ c# k1 c            int j = begin1;* R5 w& |* e& \  M
    6 I) n7 ?4 U# v$ J! m  j
                //归并! v3 B* y7 L( |, c2 i
                while (begin1 <= end1 && begin2 <= end2)
    ; U% i6 f$ S" o: E, n            {- W- c6 \/ k* `* i8 Q. S" Q" t( }( {
                    if (arr[begin1] < arr[begin2]); P* b) X' E4 p( m
                        tmp[j++] = arr[begin1++];
    0 h2 Q: U: l: K0 ]% z* t                else     
      c+ C$ |4 R* P( Y  s! C, y2 W                    tmp[j++] = arr[begin2++];
    % ^% R6 v( t; B( h8 K  x            }1 n$ e7 ~$ V7 F8 U' }

    ( Z5 T. @" u5 M; A& N2 B8 A- Z            while (begin1 <= end1)
    & `9 z, @# T  @; u- j. H" M* B                tmp[j++] = arr[begin1++];) R- k9 ?& q0 r: V8 R- Z9 ~
                while (begin2 <= end2)
    # ^$ i: `5 M7 F3 A& Y1 `                tmp[j++] = arr[begin2++];
    & Z+ H, z; Y. }
    " {, X, a' s# ^8 Z- N            //拷贝回原数组——归并哪部分就拷贝哪部分回去, `. N4 m$ j1 n' j. I' Q, K
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));$ }# z$ w. V/ D1 \; g
            }
    / j( m8 K! e: u1 \- c        gap *= 2;
    ! A$ K) @2 T2 `' @9 }2 a    }
    1 O' c! n# h5 P9 Z4 l6 u# V5 ?7 @4 `) R  `, T% H
    }
    6 U& g; u+ B: F% q2 @/ }8 {; K' P+ C+ ]% P3 b2 R
    1
    ) O/ ?& u0 W9 R/ x3 `2% ]5 G$ C1 _) f1 t+ y) z
    33 P8 v# Q$ S6 I! A7 r( }# B8 j
    4
    # E! Z, C/ n9 q8 w  W53 D7 F5 g* p2 B4 s; w+ ^' ~
    6
    4 M5 Z# k3 g9 f) [' N; A7& o+ d, |$ w1 f9 ]( D9 z! g
    8( W, b8 ]3 L) d$ I- k
    9
    9 ^: j9 h5 g+ m3 n- e7 Z103 t3 g* l% W; S9 p, Q
    11
    ' Z% G+ q4 U. Q12
    ) s& P* K7 E, O- A- l13
    6 p& {% @/ Z. o6 ?( s14
    + M& j& F7 i- a- y15; W# E; h; @; k/ c6 k' e9 {6 ~
    161 ^+ I9 ^$ O7 i* s0 Y
    179 b' p- |2 U$ l5 ]/ v4 \4 y
    18
    . I: A  @! W; B19
    4 M& p8 Y' l; Q) I9 [20' u) ?# F. K  b5 X3 ^- j/ |, Z
    21
    + U: ?& M! t$ E9 [4 g  C! w22
      O) ]2 `0 P, ^* L. S  M  M! R, U23
    % s# Z' H% B' {& k2 Z' Z$ H2 l244 u1 f" J4 T: a# n5 d) b
    25* o5 ~, S# E; O, u0 `; a
    26; A9 {$ y, C' p3 ~/ P$ ~
    279 e' b7 S1 W) z
    281 C7 A( r7 k$ W! C( w" @0 _% f" l
    29, X& n& H) _5 b: C, O4 I
    30
    1 {: R8 _% M, h! T# C; U& R312 L; i! k3 W8 V1 n% V0 m% Y% ~
    32
    - b3 w1 {" `7 J4 N33) f& z, G' P) p2 Z9 P
    34- m6 {! M6 u& r, O: h
    35
    7 I" J/ W" K0 B! W* a8 q( u9 M7 D3 J36
    7 V( z. x/ `$ ^37& @/ t! ^' \: d( }. d- Q7 K
    38  `- z/ o8 U; P" v: o3 j
    39  h& V, x# m+ U" L
    406 m1 G, U8 s8 }* e! L: |
    41. N8 i8 }$ F- Y6 L# E
    边界问题5 M/ E0 Q, R1 Q& T2 n
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。
    6 y7 c$ j4 l- i
    4 y" d+ V3 v# @# c- G! x+ X% X举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:
    8 o, k0 v1 `- w9 T  ?- @4 R% N/ n! X" i( p: `. |

    6 n5 G) {/ r6 b8 b
    - T  B& u8 b" v/ l由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)2 S( N# f) w" k7 G1 k, J

    4 n& W# z8 C% N0 N- W: t) B# m6 m% |第一组越界(即end1越界)
    ! b& @2 T  L8 Z7 }6 u3 o2 O! f) r
    . o# B" N) [( z; H( u9 T应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    / n6 \/ R5 y: L3 B# n* Q: O
      I  e/ E0 Y% F7 Q& W7 ~2 w第二组全部越界(即begin2和end2越界)
    3 Q+ q, i! E2 i/ I9 M8 n
    # M: O7 }1 c: Q( U- [; L应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    - D6 d* P5 `' }& Q2 B" U* T+ h  [: m6 A
    第二组部分越界(即end2越界)8 @) T0 X, D/ U) o
    # s# ~7 M, N! M" s; \
    应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。
    0 O4 F+ V% h; @+ r1 h' w# E% b( t2 T( V
    ​ 其实第一种情况和第二种情况可以合并为一种情况,原因:2 @1 I. @3 H. ?7 H) ^

    % ]$ \9 d! G3 f​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。( F6 L4 }" Q6 {% w, d

    : v* F' `# f* I! N​ 拿两个数组试一下:
    3 c4 @" k. A; g. C
    " V! N/ @+ b% Q2 B1 L" G9 {; L, h% Y
    ! n% H. C1 f5 f8 \

    9 v" Z9 a/ J1 U* Y8 t" ~/ W4 O1 U- E' S# A# v& f0 A/ x
    代码实现
    2 o6 H/ f. I' p8 o9 v  Z
    9 e+ X- u+ c3 ~- wvoid MergeSortNonR(int* arr, int sz)
    ' [! C" R; d2 `! o{
    ( p' Z) V* d' f1 |1 Q, K  ^( E! g    assert(arr);
    * T- q3 l) L; D$ y: _8 `- m
    2 ^9 K+ V% J3 Q# H  ?. M8 ~    int* tmp = (int*)malloc(sz * sizeof(int));3 a6 t- J" N$ Z7 S. S% Z0 `% ]
        if (tmp == NULL)0 k# Z( @6 y. E( J2 N
        {' X* r/ _, ]- n- M. ^- u
            perror("malloc fail");  s: h- k# P5 A9 y& L7 {9 R
            return;, h1 K* K* \: b' `) k
        }: I7 I( j4 Y9 E' j6 M4 K
    * S- G5 e8 |* {+ u
        int gap = 1;+ R8 Q) ~1 Z! p& R$ _8 X
        while (gap < sz)" f" ^* L4 E* J  H
        {
    3 F: @0 U" x: [- X        for (int i = 0; i < sz; i += 2 * gap)9 n, Z4 I5 {' q, r+ f. W6 ~: l! l
            {
    3 S7 G1 W, H+ g4 {9 |7 Q            int begin1 = i, end1 = begin1 + gap - 1;
    # l: q, U9 d8 }' f$ K2 `* A            int begin2 = end1 + 1, end2 = begin2 + gap - 1;; P* j$ D/ d8 Y* L3 a7 Y6 r9 r
                int j = begin1;# r7 M" M; J9 r/ d
                            //越界检测
    ' l, E; d+ x" b8 F8 T            if (begin2 >= sz && end2 >= sz)
    # X( v- U" x1 b  O; q+ n                break;
    + e7 j- x, c9 V. p1 W            if (end2 >= sz)
    9 f/ w* D5 r5 O! q# J                end2 = sz - 1;$ S2 ]! P  h: G) l/ R! L  A
                //归并
    $ O9 G3 r3 |% \  S            while (begin1 <= end1 && begin2 <= end2)
    , s# U. @  l0 F; W            {& ^7 J* M% m' O3 Q7 d+ I) v
                    if (arr[begin1] < arr[begin2])6 R# E6 i$ S9 n& s
                        tmp[j++] = arr[begin1++];! V1 p5 a8 v6 O& m5 Z" `
                    else     
    7 w4 N( U3 {+ h2 z; P0 `                    tmp[j++] = arr[begin2++];
    5 G0 x9 @; x5 b8 n) m            }
    , Z+ B, w- K) c8 \" A' z8 Z8 x* h% p1 C; v3 E
                while (begin1 <= end1)$ d; d8 ^/ \0 }  T
                    tmp[j++] = arr[begin1++];
    ) b$ }' P( v, k( b8 Y3 f6 ]            while (begin2 <= end2)4 m1 p3 |: a, ?9 j; x
                    tmp[j++] = arr[begin2++];% t0 s1 t) E+ F
    $ x7 Q8 n9 d( h* v  k5 F
                //拷贝回原数组——归并哪部分就拷贝哪部分回去1 s" P9 J) N( [" j
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    6 \4 i" L+ @4 x) e+ f/ p0 \        }
    1 G  ^: V6 O. @. L; b, a+ d/ Q        gap *= 2;
    & v) [5 j, E$ S9 q) C    }
    * H4 X. @. |: w5 k3 Y& H% O2 q0 f2 _) ]4 |1 [$ W4 z0 r
    }2 ~7 {  d3 D' t% o+ K

    * m0 o/ Q, x/ T* F( l1
    / `5 d# x: ~) T) d2
    + T  a1 A: p( g! P' p2 ~' Z- O5 F3* b5 Z$ X& h' ^2 G
    4/ e6 }3 t! x, k' `  h9 v; S4 p+ r
    5
    + R8 p. |6 y) V+ b# _, p& F62 t( }" I. [( H/ k+ Y  {# Z
    7
    . w) P* e+ _1 \' S3 x9 k. H. j80 @6 _9 b) A7 u9 ~
    95 ?& `& {* U4 `# K# }; n6 X, B
    10+ E2 x5 x+ y: n; X* `+ r8 v
    119 j+ v/ S: y( w  N3 `  J
    12& W& c" T4 f! |1 f& f* o
    13
    & d+ p& y+ k! v& F14
    ( T; k: \+ r7 A* b& o" `15, b) J* m1 r0 ~% z& j
    16
    : u/ z+ O2 v' W& a& i1 e$ h/ J1 N. j17  D, u# N5 k( H5 ^+ l5 L1 q( i
    183 X; {$ k  p3 \+ l0 B; o! d
    19" l2 w! z! J' u2 T; i$ b0 z. ^1 b
    20! P: T5 M+ X1 }1 @! u
    215 i+ {3 X, e" k- i
    22
    ) n! M0 ?: o) w" b2 B7 U( r; M232 _( i# \& p! J% n
    24
    * v" h- _) B6 ?25
    8 @( ~; k& G4 i/ v/ y( r26! z" z; a# H3 q) m. L& P
    27% M5 Y, H' {9 @5 [. V' L
    28
    3 i6 Y+ [& j1 D; \6 ?/ E3 ~+ y29& P' }, P: o7 j" w
    309 r3 ?2 H" U( I/ d& Z4 ~
    31
    3 F; K$ `$ L% f% w. u# F32' i& S( E+ r5 Z3 S5 E" G/ D0 {0 i' R7 Y
    33
    0 _: c/ ?/ x/ i0 m34
    5 [4 k+ a$ d! o; I5 f$ r; F35" u; y& ^: `& a3 E9 u
    36
    8 k" t% F9 P  C, v+ ]0 O/ Q$ I37
    6 h1 [6 W% i3 Z& X38" w" ]7 l# o# u% p7 A0 [5 m8 u" L& {
    39
    7 F5 `* Y. r5 d" `7 D2 v40
    4 r9 B& h8 }5 c41& l& p* k/ H$ t& x4 l, `- z
    421 {. n$ ^( j% n6 B( b$ |- S
    43
    ' J$ y* P: n& l: [' r44
    : h4 `* ^- [  a" ^45
    ! N( X5 C. K: U* i$ W4 `7 a! D! g归并排序的特性总结:
    4 G- C4 U0 j6 ~) u7 b" }* ~8 z1 x8 A: ~$ r" a( b
    归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
    " e( r8 b% p, N, B$ u0 g, v& W时间复杂度:O(N*logN)
    , B6 c; R7 ?  J5 x# y空间复杂度:O(N)
    9 ]- T8 N; c: V' |1 X3 A稳定性:稳定0 ]: }8 G2 A  l9 s

    2 C! W( C% u4 a. [" _9 _————————————————
    . y3 [# @$ l2 `) R& j: f版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    5 c8 d- N* M. E  w原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    * v- X, p' {! V& @$ o
    , v; g+ O) z& ^$ }9 M3 f! u2 C# \9 o0 @7 ~( y! M7 q* 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-10-11 06:23 , Processed in 0.369039 second(s), 50 queries .

    回顶部