QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3318|回复: 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的排序算法】归并排序
    8 u5 }7 N0 f6 L% F; W# Z0 j( \9 t- a3 M) ^8 T
    前言
    9 Y, b; {% j% d4 N本文基于C语言来分享一波笔者对于排序算法的归并排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。- f! [; @0 P( t3 o; a# e

    4 I# F: m6 X+ \7 o$ g6 y7 v归并排序& p8 E5 S- T: i; C/ j
    基本思想! \5 U8 M" e0 v4 R* k
    ​ 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。& T/ w! O! Y0 r' R/ I' ]) g

    + P+ `; W, p& q+ `) ~8 @8 [: R* w9 U5 U$ `
    * X# L: c, h! z3 U9 X4 g: s
    ​ 合并的思想其实和有道题目的思想如出一辙:
    6 ]6 I6 a; B+ p
    8 x" l! K1 k7 J% s5 }, w2 n) y& Z( s) J& |# J
      G+ B4 `& |* C& e1 g& }
    ​ 我们考虑新开一个数组来放入排序好的值,要不改变顺序的话就要用尾插,让nums1和nums2数组元素的较小值尾插到新数组中,两个数组总会有一个先插完,另一个数组就把剩下的全部尾插接在新数组后面。2 M  M# C$ J" t6 Y8 ^: I* x* b

    4 ~0 u0 B" R6 J+ D# K7 l[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gsgj7Cmx-1662793985599)(https://typora-picture-1313051246.cos.ap-beijing.myqcloud.com/归并原理.gif)]
    ' w7 t8 |: s: ]
    4 _+ I1 s8 u4 Q' L+ R& Pint* merge(int* nums1, int m, int* nums2, int n)
    ) J- b6 |8 Y! I1 G9 H  C( R{7 c+ B% Q* ]" `% X
            int* arr = (int*)malloc((m + n));5 B. U7 U7 @" [( O* P. H) F
        if(arr == NULL)% e- j8 W0 P" J/ h: k
        {+ s2 a! X- @* T2 p
            perror("malloc fail");
    0 C/ Z$ z2 s+ b/ p9 Q" j        return;; d; y8 b% U3 [& A+ Q
        }. R9 T7 M4 b& E

    6 ^3 M! o% F8 q    int p1 = 0;
    2 r! a9 P6 t+ M% u. |0 Q- r4 J4 G    int p2 = 0;
    # y7 q, x: s2 |- R8 g    int cnt = 0;3 ^9 Y( ]; u2 c, l/ L+ {
        while(p1 < m && p2 < n)
    . Z, Y- u$ G* ~# Z' D    {
    9 i' C/ u. |9 T5 \' i        if(nums1[p1] < nums2[p2])
    " d; R/ E6 p8 B( O; Q& r# E3 n( D        {
    * j* e: |3 H3 L! P( m            arr[cnt++] = nums1[p1++];
    ; q/ }& R! q2 f" d9 G        }- C" H' v2 \% M, u& v/ }9 o) j
            else
    / \" _! D' z) w9 @7 O9 l        {, X, A1 l' z+ ]7 r# I( ?$ q
                arr[cnt++] = nums2[p2++];, J8 Y) |, _; i
            }
    ) ^+ \. c; G7 R) C6 E8 B, z. t    }
    0 b! K" o& |# a2 i    while(p1 < m)
    9 ?6 n8 }6 C4 J: c; u        arr[cnt++] = nums1[p1++];
    " \. \7 h/ R$ p; i6 _: |! M$ e; ?* j2 B. Y- l
        while(p2 < n)
    ' F1 X% a; B: {9 p5 z        arr[cnt++] = nums2[p2++];% J' [. i  B  ?, e

    0 a3 ]5 Y( S3 N) c; _3 j: s8 s    return arr;& U3 i8 o5 D' g. }/ H; Z: y9 y
    }
    * C4 }: m3 @( R+ i7 \2 m+ J
    - a; G3 p; I% G2 L+ I1
    ( M2 k. W6 a- G& B" n9 E; Z0 u- v2+ H! E$ i: O0 T' t6 I0 Q. Q
    3
    5 O3 u) E4 u/ {+ N9 T; U4+ V) D6 O7 N- L$ y6 Y. Q
    5) Q4 ^+ ?* U4 F* O; J
    6
    2 N3 q7 T( x7 T- K! S7" _" M, U! F& R. H' r9 ?
    85 ?8 Q9 C2 A7 N" Y5 T% z
    9% i2 t7 G& s! T5 C. y: q
    10" y# @: B1 ?+ t% m. t
    11
    # w( l/ S# `: v$ q5 Y2 K12  x( j4 h& }) A' u6 \  p: c
    13
    % s( q; w! _1 D2 T  S3 f2 G14
    " |+ O7 r" O* j% v9 {3 {150 k$ F' G2 h" E: F' j; x) u* c. a% S! R+ o
    167 l( h! s# f  {8 e# X5 a- W! Z
    17
    # @, b! O4 ]: C0 x0 |; g188 E4 d  M$ w" V- P
    195 X5 ~1 `5 u8 r8 p1 r0 w. ?) Q
    20, ]$ m1 \. K7 Q4 \/ D
    21
    ) C. I, A# P% y& c- a, }; m226 R* ~1 S! e' I3 F0 M! r
    23- q+ W; R, j# u6 b
    242 A8 c: J2 s5 B; l5 e8 M: H& G2 i
    25& S* U2 K: g. b, n8 ?9 p
    26
    $ O' t6 y: ?4 J4 G! @$ V+ ^) u! V- T273 q4 s* J4 H) D' ]/ L
    28
    ' B! w$ k3 d% S2 K7 }4 V# b5 h29
    + r+ ?! q3 K  I30% C( B% ~# [- G# Q! R# |' B" ^5 d
    31
    0 O4 z! H4 ^( ]8 A2 o​ 所谓的合并就是利用这样尾插的思路,我们就想到要把原数组分解成两个有序子序列来合并,那么如何将原数组分解成有序子序列呢?容易想到用递归,其实非递归(迭代)也能实现,我们接下来具体来看看实现方法。) s) A; e: p5 E" ~& [& [1 W

    - W) G4 {' K! u0 N9 Z/ e! L8 k递归实现
    : K/ |1 E+ T6 \$ p, S0 H; b, r​ 通过二分分割出两个子序列,然后进行递归,先左后右,不断分割直到子序列仅有一个元素时子序列一定有序,这时候就可以往回退了,等到左右子序列都退回后就可以归并了,不过不能直接归并到原数组,因为会覆盖而丢失值,不妨归并到另一个辅助数组,归并后再拷贝回原数组,思想就是前面讲的合并的思想。
    6 R, t) p4 K$ e( ]% C6 k  M6 ^7 s) x! F' M' u) W1 O
    0 j$ h) s$ R+ a: @5 ?

    * r+ ?7 \  E0 K+ b- s
    : i  U( M& O0 O% I' j* z) X  |. E' n! c- |& a8 T
    void _MergeSort(int* arr, int* tmp, int left, int right)% ]& Q0 M- {& @) F! E) L
    {/ D' w: w+ w5 l
        assert(arr);4 s6 q4 f2 b* z; k
    $ e9 x/ ^# b( N7 X
        if (left >= right)//递归结束条件不要漏了
    " \6 k* E' \; g, O6 U2 l  @        return;7 Y! M6 z) x+ ?9 w% a  D

    ) j1 W/ ^, u/ \( {0 a# O7 @    int mid = (right - left) / 2 + left;
    % _0 }8 c3 h- ?' T6 P2 Z5 C. ^3 e) u4 H) G  O  Z) ?, ?& }" ~# m
        //划分左右子区间[left, mid]和[mid + 1, right]9 q4 |* l5 A! x
        _MergeSort(arr, tmp, left, mid);1 J8 a" z1 @% S1 l1 q  }* \
        _MergeSort(arr, tmp, mid + 1, right);: f& }' S- J5 a* V: C

    ' e# e" f3 \- ^: Y! f    //归并
    ' J4 a" I1 y1 v' d6 ^- D$ g; n1 E    int begin1 = left, end1 = mid;+ O7 k3 G& }) L* z
        int begin2 = mid + 1, end2 = right;7 ^9 |8 [% T; R* N. m- O7 F
        int i = left;9 R' M8 q% D, y" [7 }1 q& O4 x
        while (begin1 <= end1 && begin2 <= end2)
    & g3 V8 r: ]+ r    {
    ) ^) A  r' c! P6 ^- `) g        if (arr[begin1] < arr[begin2])
    9 J7 B* y3 X4 O  C0 l' b4 ~& N- t            tmp[i++] = arr[begin1++];8 i* C( i, P: [0 K
            else
      T- ?7 @2 V' K* c' i! S/ k! h            tmp[i++] = arr[begin2++];7 I" \& e  ?2 a8 L1 Q- d' ]
        }$ E* V  R+ v1 R" A

    . s& p9 j; U% C( O+ y' O: {+ h    while (begin1 <= end1)
    ! x* V7 b" @" K7 i* D        tmp[i++] = arr[begin1++];
    , @/ f1 ^! v& T0 z. p: V    while (begin2 <= end2)
    5 _+ b& g5 x  P( `( ~/ B' `        tmp[i++] = arr[begin2++];) Y- S1 l3 C3 K4 e. {9 X
            - B" J, v+ F% m' A7 o# |) n% q
        //拷贝回原数组——归并哪部分就拷贝哪部分回去* n1 t9 Z% _' w& N) ^5 O
        //而不是拷贝整个数组回去, r- P! i. S6 {5 }8 D$ Q
        memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
    # @" Y" `/ U& X0 L0 x}% E& W' J, q& K4 \

    . G! c* a  P, v1 B: evoid MergeSort(int* arr, int left, int right)3 e5 }' D# D5 |! R  Q
    {
    8 n, g# q& B8 ^  x) C    assert(arr);
    * K" u5 {; w# m! E8 K0 L& z3 k  ~3 K4 z7 J7 ^1 D) V9 Y
        int* tmp = (int*)malloc((right - left + 1) * sizeof(int));- h6 T( q* g" ^
        if (tmp == NULL)
      O$ r' @. Y) V7 ]    {0 A9 k* u8 r# w0 o) k
            perror("malloc fail");
    2 B# x. x1 R+ O! k: p        return;
    ( Q+ p' f: A6 z    }& H0 E. a9 f. c0 Y' D) F
    9 r' J, L+ H9 k5 |" t7 \
        _MergeSort(arr, tmp, left, right);9 m# P+ B9 z0 L0 }$ H
    $ o5 c! ~* d0 B  Y0 ?& H
        free(tmp);
    + R% Y" B9 g" Q: B" G6 |  g    tmp = NULL;
    8 O6 m& y/ i& s}
    / u) x0 q  j# }0 V; A
    4 P. `5 I! h% p3 H( Y1  Z4 ~7 ?* G8 v: l" A$ b4 k- n6 I- ^
    2- l+ U" ]. l' E
    3
    8 q. ~! C7 d3 c  |- O3 ]3 q8 g. C% L4
    ' s7 J/ ~+ t/ w# t- B5
    & {) c3 t& E( S$ ]8 J68 @$ L6 L: y, n# l
    7, p/ g8 W7 d4 g! w* N
    8# T; G0 B9 f5 P4 Z# @
    9. C. I' U6 ~! k0 t. q3 X3 y4 |: {
    10
    6 ^- Q1 ~. _0 \* i" M  M+ ]2 \11# }6 W; F: C* M/ C: X: ~
    12+ {! p- i5 s4 x5 F0 f0 z1 E7 W" v
    13' L3 H) v4 M( u& K5 K% w
    14
    # W* T: S: u* ?4 r/ R15& w/ j% N$ K" l0 }3 @& h- X
    161 v( F3 ?- E7 V& Z& o; V
    17
    : N/ e8 m. Q( I% Y; e18- y- m' p8 Y; m5 m, p# U  @% J
    19
    9 A7 i/ i/ Q8 b2 Z20
    . T+ B& S! D" S21
    " Z* y* X& A+ W, U2 f7 H22
    ; D3 S3 [5 P' n! m1 o23* V3 N) Y+ M1 L5 S) B8 N4 j
    24, s4 S2 V2 p  f: p0 ^! H
    25
    & T1 `, g( S) L26
    5 b2 u+ C+ x4 ~! L; ^8 s27
    4 c( l/ Z" l' C. ^1 }  W3 F' q! |28$ z( N9 N8 j5 U0 @7 q
    29- X; [% ]+ R6 Y
    30
    & F. G( I0 |2 Q, L5 r& `: F31
    * ^# P! U- p  x; M32* s. b: O- R; X
    33% ]6 t* z, M0 M; ~  F" b
    34
    2 g/ p: P4 i% j. ^) L& ~35# z, `) |% m* a; _, @, Z
    36& O7 H5 w$ c3 \- h* G, r7 y$ j
    37/ O; Q5 t& t. E' m, y8 \
    381 K6 E1 A) r' R" O7 D' n, q
    39
    $ o- I, Y" M2 p6 K$ P& E( d40
    0 d- @8 o' G* |5 ]) a2 {1 ?6 C" i41
    ! y& W9 ~5 A7 M6 v; ]42
    # v" @) c! ~% s- g7 U9 {43
    0 C. J; [, z2 ~0 C+ H: K& {44/ z* E8 N& Q6 s7 ~6 l
    451 [. l+ _% ^3 ^0 ~
    46
    ( D' f. F: I4 R! I47  z) w/ Y: k& J1 T
    483 {1 O+ f0 K9 P
    49! z9 P" \% u8 Q) H' W! D
    50  s' H: E2 ?6 ^6 y9 m8 ?$ Q
    51
    / K" D- y+ T) g非递归实现
    2 T& h$ s$ |$ g3 o* q​ 直接在原数组基础上归并,设gap是子区间元素个数,从gap = 1开始,因为仅有一个元素的子区间一定有序。为了方便,我们把gap=1叫做第一层,以此类推。/ @. ^" J1 M" k( |: v- k

    * w& Q- e8 r6 D6 U* Q
    ; ~. o7 b1 p/ Y/ \4 {/ ^% A: U+ j: `" O
    ​ 不同的gap值代表所在层数不同,每一层都是从左到右两组为一对地取对配对归并,i就是每对起始位置,之所以更新i的时候要i += 2 * gap是因为每队两组、每组gap个元素,所以要让i跑到下一对的起始位置的话不就要跳过一整对的空间嘛。" V3 g& Z+ n5 ~4 \; |: y/ h# M" ?
    ' h" l2 `/ Q1 M6 B; I0 `
    ​ 还要注意区间的取值,每个区间就是一组,就有gap个元素。6 s2 m% j9 u$ w! M

    7 d  y: R( k7 e) Q​ 整体拷贝遇到越界就会比较难搞,所以我们这里用部分拷贝的思路,每次归并后直接拷贝,要注意一下指针偏移量不是begin1而是i,因为begin1已经在归并过程中被改变了。
    * l1 n( M1 Q+ A" _. F5 t1 T
    3 X  c' L5 I  T  s8 [& X! B. ]代码实现
    : t6 `' |7 G" u# n5 n& [5 y" z) H: Z  ^
    void MergeSortNonR(int* arr, int sz)9 Y% y, y# c/ t$ W' z
    {! a+ O% z' K. K1 K9 D9 a
        assert(arr);. f' h' F4 f& W0 C- c. x) q/ W2 O

    ) G. B$ y# Y* {6 `& h" `* }    int* tmp = (int*)malloc(sz * sizeof(int));
    : {7 M  b) B, b, \* r. v    if (tmp == NULL)
    8 P5 K7 k: o" `5 S0 M. a# L    {4 X# b) |0 Y3 `. V$ \
            perror("malloc fail");
    / e  X0 Y, `6 e7 O  @        return;9 O" P7 s; r, y; t% j6 A4 E
        }
    9 m. v: M# q& {  L( ]) I0 j8 J; S7 }$ {! g8 F
        int gap = 1;
    - E# {% U& @; X6 d* |" [0 H    while (gap < sz)9 P: |, T6 E6 W$ @
        {7 ^9 [" u6 A, N+ K
            for (int i = 0; i < sz; i += 2 * gap)' R4 N5 c$ l  c* g4 X
            {3 v$ e0 W9 B& f( `
                int begin1 = i, end1 = begin1 + gap - 1;+ e. d3 T6 d# m! z, x
                int begin2 = end1 + 1, end2 = begin2 + gap - 1;
    1 X; l1 P" Z& Q+ U* r/ l9 X            int j = begin1;$ j& o" _; q$ x$ ]0 r
    ; Q+ N: q5 Q7 M" [( a2 p  j' W2 o  P
                //归并4 t0 x1 D; q( T$ X5 e) N9 |( M
                while (begin1 <= end1 && begin2 <= end2)
    6 w9 T; r& h7 g  Q9 c; R0 t            {, t0 ]5 F. `+ g
                    if (arr[begin1] < arr[begin2]). r* G/ j" a0 c  g/ @& X
                        tmp[j++] = arr[begin1++];
    ; p& k( r$ d) K- E" ^                else     
    9 y5 [, o4 J% h3 g4 B; Z                    tmp[j++] = arr[begin2++];
    $ F& q. C+ ?4 J; h8 m6 @( ?6 k6 {            }, o, a2 l& }# H4 B9 I7 R) g

      I( ~; D6 @# _. T            while (begin1 <= end1)" q% j% S! z2 t% Y, D5 A
                    tmp[j++] = arr[begin1++];5 S$ U3 b  S* {0 `3 y- j/ p2 i
                while (begin2 <= end2)/ p6 Y' j* [% y' b+ A+ \( h( k$ L
                    tmp[j++] = arr[begin2++];1 \& e6 S( Y4 I! I( Z+ c

    # [8 m4 H8 f6 a6 O* u4 H7 M            //拷贝回原数组——归并哪部分就拷贝哪部分回去6 m$ y( E+ E. S3 n+ {+ [. n8 B
                memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));
    ! r' T7 [  z* `4 m        }. g7 d% N& c4 l2 s& v6 y' y; E; }
            gap *= 2;! g( |/ n% Q& W3 C. l, u
        }
    . u1 O" ~; u7 }4 F6 w5 E" ~+ s9 k/ z- w. c% Z) K
    }
    9 ^7 b/ {% ]6 n+ S. i9 c: h4 P+ D4 O. v& u: m; T7 P, h
    1
    " o; a3 ]7 H( `4 W  C$ x2. t$ g' b, H! j5 _& l
    3
    3 ?0 J! _5 y8 n4 f: l4
    $ c7 Y% e% d; N) o! i5
    4 x0 u& {4 k% I/ T$ `60 r, J5 W; N( \/ d4 m
    7
    " n: j& S. Y$ O7 O8
    3 L0 L0 C0 {% `- F% _! b/ X9
    + B" a& x: P6 v/ [10
    9 m" u  T3 V2 B0 y; a11. f- _* f0 D7 m  ]& P- X2 I8 g# R
    12+ T1 X; ~; E7 L9 l  h: U- Z3 S0 `4 ?
    139 n" ]3 M. E$ V
    145 W) d. S! [6 L; h
    15
    9 @6 W* J6 A/ H1 D6 ^0 {. G" N162 a" ?: v& y8 v3 s5 _& Y
    17
    8 |: A  r) q$ ^1 w; w$ I, n4 m18( v  L3 ^" C" v4 P/ o* ~
    19
    " A/ w/ v) F: ~0 n1 S% |204 ^/ W6 q4 ?% t4 b
    21# c: X. ?- r4 N  M
    221 H) E8 J. r: [, H5 u( R
    23
    $ `5 j# |3 x- W+ M: A24: x' L. y# h- M4 f8 X8 {
    256 V' S9 q- u. U
    26
    % ^* b( U3 x" |1 n27& g! h* K1 f8 `
    282 v3 a$ t6 a* p+ N0 D( u2 y; J9 F
    29
    6 M' X% G8 d/ t6 @) F/ G1 t30/ V% N; Q6 Y6 L5 [$ p" S9 a7 ?" G
    31
    $ F' V, f( T' |  @6 C32
    6 ]# f9 N( D" I1 ?33$ v& z4 u* h; o. \; e
    34$ J: b; Y0 ^2 K
    35
    0 n- Q! f$ N4 u1 g9 G$ g36
    - z8 q; y3 p. ^& |, e6 l8 y37
    / G9 N( `% r, h& Z! x8 ^38
    2 }, s" h3 _* l! Y' C3 x39
    0 U3 ~- c2 S' o. T2 t, K0 `403 L+ |2 D" h8 u: G5 f
    41/ b" L. g/ [) c0 P
    边界问题5 }6 d' ?% G% l- S2 `6 s/ u
    ​ 实际上还需考虑是否越界的问题,上面那段代码并没有考虑,所以还需一些改进。为什么会存在越界的可能呢?因为我们是以gap的整数倍去取区间来归并的,而区间个数不一定总能满足两两配对。/ Y( T7 b* c7 e2 ?, M$ ^1 ^4 ]
    6 {8 L9 O- s; H) X5 G* V1 q
    举个例子,就把前面的那个数组后面加上个元素5,没有越界检测时出现的情况:! o$ a' m) g1 y0 o! ^& [
    + i+ ]2 c) b$ A0 L6 J

    7 K) Y( n! O% m  d
    " v, K' M4 ~; {0 V2 H* d由上图可知越界分为三类(这里将[begin1, end1]、[begin2, end2]分别作为第一和第二组)
    & V7 t# F# e1 R7 V; b6 r% Q" n" a  Y* E* _- F3 I
    第一组越界(即end1越界)6 n8 l3 H2 B( g/ i- L/ ^1 C

    " L8 Y+ C0 L* v0 l1 I应对方法:这种情况一般介于第一层和最后一层之间,break跳出for循环,不让越界值被访问。
    . z# V  T: P) P7 I+ G) {5 @; O7 Y) k* ^" _3 n4 |' Y) Y# A
    第二组全部越界(即begin2和end2越界)
    , _+ X2 a% A5 N8 L3 v. V% V* T# j) J% _: |( z% f4 s6 ]8 G
    应对方法:这种情况一般在第一层,break跳出for循环,不让越界值被访问。
    3 u% n: i! k0 \5 B0 G* a: @0 d# ?. F+ N- k
    第二组部分越界(即end2越界)
    8 M( q5 _' @* v9 R$ c8 L! u. X
    4 a7 z0 S% b2 p# N应对方法:实际上这时候就到了最后一层了,把end2修正为sz - 1,不跳出for循环而继续归并。3 y/ B6 L4 h' _* D

    ( L7 F& {1 {5 C8 w" K0 C5 L6 x​ 其实第一种情况和第二种情况可以合并为一种情况,原因:: ~6 t' m: y/ o, V/ B

    5 X  }  V/ }7 {% P3 _3 n3 {​ end1越界时begin2和end2由于比end1大,它们两个肯定也越界了,也就是说发生第一组越界时满足end1、begin2和end2都越界,即包括了第二组越界的条件,这两种情况都满足判断条件begin2 >= sz && end2 >= sz,同时第一和第二种情况的操作都一样——break跳出for循环,所以可以合并为只判断第二组是否全部越界。
    # e7 A5 e' [: K' z- l& @6 y
    % E4 x: \+ K' ?: X8 {" Z​ 拿两个数组试一下:
    9 r$ e: u9 j3 {5 T, Y3 J& |! [, i( m

    # b* w- S9 S: O% D+ l4 @* i7 g5 \: X$ S& V+ y* J

    ; Z2 [( r8 G: q  Z1 T" Y( i+ @6 f0 u, a
    代码实现2 j: y* \3 m2 l" S& W" o

    , ?. A! `$ y; N9 Wvoid MergeSortNonR(int* arr, int sz)- X0 w- D2 K( m6 |% Z
    {
      K! s7 E, \4 k* ?7 w+ {    assert(arr);2 v  m5 `) v6 \. h% W

    * Y8 c+ ?" t' Z    int* tmp = (int*)malloc(sz * sizeof(int));+ }, d, g4 T4 Z8 |& h" Y
        if (tmp == NULL)
    ' l; S$ h9 o( H3 F7 U/ O) \8 Y  E    {
    9 {! {. v7 A* l9 W: \        perror("malloc fail");' A  S- v! P$ B: a
            return;3 `# H! P6 g- X7 N8 h7 e
        }! t+ x& o8 p! n; h% w# X

    " q2 M  F# f- ~9 Y. \    int gap = 1;
    ( q/ J" Y& a% E0 g    while (gap < sz)6 ~0 u6 o0 @' x# j, ]6 m
        {$ s& s6 T( D: G& L6 E8 n
            for (int i = 0; i < sz; i += 2 * gap)- q9 W9 b& X" O4 {: r
            {' A0 l1 d: _. K! m
                int begin1 = i, end1 = begin1 + gap - 1;
    5 m1 k3 `/ {6 O9 C            int begin2 = end1 + 1, end2 = begin2 + gap - 1;$ B1 U% B6 `$ A0 H
                int j = begin1;, g" k) K/ B4 H6 a$ D* F
                            //越界检测
    : M- B  }# o/ U' d  P- \1 y8 {            if (begin2 >= sz && end2 >= sz)2 m& j  f8 T3 z+ ~9 `7 ?$ H
                    break;1 m9 n: {2 M  H2 g; ]
                if (end2 >= sz)
    4 i# W2 T% o/ x6 f) Y                end2 = sz - 1;5 \$ I5 ^' n" f3 R
                //归并
    4 U4 F, M1 S9 N' O! p            while (begin1 <= end1 && begin2 <= end2)  C# K: W" O$ z8 S- W
                {( O5 T! ^' V4 I
                    if (arr[begin1] < arr[begin2])% g/ P. R" H  R4 R9 C) L5 O$ f# g( k
                        tmp[j++] = arr[begin1++];
    ( X& F( v9 S: b3 {5 Y" f, a+ }                else     
    # e5 S; P; N0 U! w# p6 Z, k- w                    tmp[j++] = arr[begin2++];
    9 m4 L# Y8 p% Y# d/ R& }8 {            }9 ]# m6 q: r8 S& R
    4 ~7 i1 V+ k5 G, V! ]  _
                while (begin1 <= end1)
    3 }7 W5 U5 G! m7 F! Q                tmp[j++] = arr[begin1++];
    9 U4 V& p+ \. |3 ]' R3 r/ O$ c7 l            while (begin2 <= end2)
    0 `# X5 h: Y* s% \/ X                tmp[j++] = arr[begin2++];
    8 l( q4 n$ }3 j$ d" o" K3 U/ [, @$ a. C; k) g. e
                //拷贝回原数组——归并哪部分就拷贝哪部分回去
    : Y$ l1 K" l+ L+ ]" }            memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));# E) L4 V. C1 \& y0 J
            }/ v9 }- b$ ~5 L, U& a
            gap *= 2;
    " q% b. [7 e0 h4 A    }
    * {/ k% C  R7 t
    6 b3 H0 _: b( L1 z/ F}
    ( H- B) L0 Y: E' I$ h& z
    2 u; U5 r2 v3 L1 n: d1& @* K9 S. |' u( V* U$ k" Z
    2. D. z" a* X1 {0 W7 x1 U
    3
    4 ?; j5 a5 b& O4% L' Z& z6 {, Q6 t9 l$ a& w* W
    5
    7 {1 N( \4 Q; O6
    # ?# F( g& m: U$ X7
    : w  l  x* N2 t8. f. l% f% `& v# ^. n% X
    9
    4 M. Y4 S) P; F10
    1 }! ^) n* {. G" t* U11
    8 x% g/ L0 D( V- @% I12
    4 _' [6 C! a1 o" p13  V) W. H4 ^( R* e
    14% w- n6 h( N% v% Y* q$ B4 C: L
    15  T! E. ~( w1 I% d6 @+ n& t
    161 J, Z0 S- @$ i+ H, K
    17
    : {" F" R1 Z* Z8 t18' Z5 r; z7 ^  A& ^5 j
    19
    1 s; d; [2 _' }+ @; u& O2 ~20
    - P2 X5 b" x1 @. e21/ z  }8 ?5 O% \2 |
    229 B3 ?9 g4 s, T5 a9 w
    23) \2 K. p/ h! v* `& e' ?  `* }5 V
    242 t4 S. f3 M; A
    25& E8 _% Z4 h' b7 l4 D% J. J
    260 R, q* q6 u0 d( l2 A- v
    27" b) H) ^7 ]& T) V1 u, ?
    28, u3 `( k! e2 }( d* P. O
    29
    ; w4 b. k/ l7 W6 p: t( Y* S  q4 o30) O% C. ]: [7 w- n+ T
    31/ D3 c0 Y& U( z# j% z
    32
    " H& Z# N# Z. f/ L- e33+ @! s2 {- F) ?
    34
    8 |+ c% H! R: V35
    : M  Z% @) M- Y! k& G0 i36
    : ^! a0 C& M+ M' U2 P: ]: N37  }  p4 L$ U# p7 e/ ]
    38  c; q( J, s3 B5 D4 Q
    392 O  A. X0 {; f) J# o8 }
    40
      U. r( s0 D5 s, z  u( z. y41, H2 J1 ?9 d* P: ?. G) U% P( s
    42
    3 N/ l, D/ ]" y) p0 w43' i" w- C  n4 A- W% V, l
    44
    : ]& Z5 F5 {2 ]+ |/ O45
    $ S9 j/ B+ N: t% i. q* l6 [9 |归并排序的特性总结:
    $ w# \9 v, _$ h, A, x
    / N& o) ^' n+ B归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。) q9 z) b; y! Q3 C. s* ~) ^* P
    时间复杂度:O(N*logN)/ u3 u' A1 Z& m7 a& ~! t
    空间复杂度:O(N)# T# ?8 a8 ~( j0 x
    稳定性:稳定) d: O; i' t+ ~7 l- ^
    & p+ I$ y9 j! e# B
    ————————————————  \, V) S5 I0 \3 i
    版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    0 t- w! D/ C$ L% E  _/ o: n原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796657
    5 b/ l4 [: T& b1 G% ]$ [% m; O; R! P8 J

    5 U; w& H: w  _
    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 11:19 , Processed in 0.434631 second(s), 50 queries .

    回顶部