- 在线时间
- 481 小时
- 最后登录
- 2026-8-25
- 注册时间
- 2023-7-11
- 听众数
- 4
- 收听数
- 0
- 能力
- 0 分
- 体力
- 7859 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 2946
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1177
- 主题
- 1192
- 精华
- 0
- 分享
- 0
- 好友
- 1
该用户从未签到
 |
1 基础介绍: z0 l, @, V/ d% T8 x; ^& o2 @
排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。
: H( R7 Q1 p: n# L: ~5 h$ w, S/ {, ?- o0 w% b( p+ j
以下是一些常见的排序算法:
5 I+ o/ B' `) s! p6 }; @' w
$ I0 z5 a$ r) \* c- ~9 Y. i; M冒泡排序(Bubble Sort)
% S# M X* I% p) }. k. L) H% B
( r0 s; x! e* P9 M H1 Y) Q插入排序(Insertion Sort)8 S" }8 Q; ?$ z) }. C
* }+ L( [( s1 Q选择排序(Selection Sort)
) b; v" q& c. a2 @1 f
# n. B) Z3 q0 ]: s$ @8 _归并排序(Merge Sort)# u" T- T0 t9 o( h! a" a# J
! Z' S5 ]" j! I& T/ Z6 [快速排序(Quick Sort)
# O* i! a, o7 t& ^; S9 t) g2 r( @
* k# }% Z# |3 @0 b% t z堆排序(Heap Sort)
! S% X( F1 Z0 X# N
5 u5 |) E: g% `& u& S7 _5 O3 {$ R一、基本介绍介绍7 D/ R/ }: L2 y# p
1.1 原理介绍
: [% M* s1 ^: `1 m) K) m归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。7 w0 _2 R5 W0 O% B. h @, t1 ^) G" Y
) w# m& k/ C3 O; y; F归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:
1 L* c I- n; M! f' b# R$ @. t& D# @6 l+ L
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。
" Z$ o) ]! I/ K) t7 V% o- G
& J; j( `9 l1 h- y1 b合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。. p- N2 j1 k+ E( y- ]- J, S
% ?# I+ n) `# N1 y6 N9 \合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:# ^7 C4 F w$ V0 |' o
% s5 e4 ]% K5 @ x7 D9 O
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。: H! ?, n( B4 g- W( p
# c9 g+ d5 m! y: \/ j$ }/ p" h比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。1 ~; h3 V0 f' P2 Y! ]1 T
; g8 i4 O6 Y/ V重复步骤 2,直到其中一个数组的元素全部放入 C 中。
9 \( r& o7 z& q% ~! e' J5 v" j0 v9 V1 e3 _8 O, N
将另一个数组中剩余的元素放入 C 中。
7 u& S/ ^$ l% z$ j6 M& m0 z5 }. L7 W. B4 a, k
归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。
5 x7 [3 N0 K% g0 K0 l9 e
; [, q# w( L0 }6 a* F; o原理简单示例
6 g# D) J0 j5 y, w以下是一个示例,演示了如何使用归并排序对一个数组进行排序:3 E6 A& Q3 y% p: c6 u( m4 d# z
. T7 h% i8 c& J$ X& }假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。
: e/ g. L2 p$ {$ s3 ]+ d8 p% M7 T9 `
首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。: A6 X- t- p b3 f0 G0 I4 O* r4 G% N
& V0 G* e `2 ~8 q0 N& ]$ n+ m对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。' y: d) k: @4 s! P! i
5 @& Z* Y; u# @$ e1 s
对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。0 x% V0 q3 d- H! X" H* ~
( s8 }0 R+ J' O& b, o! w- ?) v接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
( T1 {6 {. o0 j8 E0 e7 m6 R
1 b4 x: @3 \/ O- n9 y将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 i 指向其起始位置,即 0;对于右半部分,指针 j 指向其起始位置,即 0。比较左右两部分的元素大小,发现左半部分的第一个元素 5 大于右半部分的第一个元素 1,因此将 1 添加到新的数组 sorted_arr 中,并将右半部分的指针 j 向后移动一位。此时,sorted_arr 的内容为 [1]。接着比较左半部分的第二个元素 2 和右半部分的第一个元素 3,发现左半部分的元素较小,因此将 2 添加到 sorted_arr 中,并将左半部分的指针 i 向后移动一位。此时,sorted_arr 的内容为 [1, 2]。接着继续比较左右两部分的元素大小,将它们依次添加到 sorted_arr 中。最终得到排好序的数组 [1, 2, 3, 5, 6]。
; M% U$ A. D5 H% B
: D/ {8 e4 X. }3 r因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。0 G- n3 P3 P/ O! E: O
) S* G4 R8 P- |/ m% Q H7 J, C1.2 复杂度 - @; z( M- Z- J1 g4 e0 r
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。) U4 K4 ?% e; u9 G
6 v! q6 B( l* ?- z! c6 f这个复杂度可以通过分治的思想来解释。: z' U& M* f& q3 \7 n1 S
2 x' v9 N [1 _( D* [首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。
! U# u {; k7 v3 ~; U7 J" ~7 w7 J) U, A* W
每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。" O' { H: N5 ]0 r' w
0 C% a, m$ X. F3 C: |' F; ]" D
归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。6 l6 m* C* y+ c3 N5 Q( o8 I# D3 l
7 D1 p! }' z8 @* P
这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。
: h* x) b# @( Y2 Z. C
& Q" E, V0 _: _1.3使用场景+ Y2 M1 s- z3 T6 C3 S# G
归并排序的应用场景比较广泛,主要适用于以下几种情况:+ e% U X# U% K: J9 l
7 c/ V3 `1 m9 m' l
对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。
) A4 \, O& h0 e& e1 `1 j; ]$ [& i- b0 `2 P9 n0 Y
对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。 r. \* ?) y: ?. v1 C
7 _9 D* C+ W/ ]/ R( N: C对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。0 o4 z2 d# `) q1 L. e0 A
8 Y! e( N! t+ Z- \0 y& N
对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。
1 z' k- y# b( g& R5 F4 |( A2 [- e% i0 ^
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
9 q4 G6 b W/ n, G0 @/ L# E* q5 y" x4 D' t0 R
总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。5 M+ t/ ~1 N' U# x/ e! a
/ Z: n/ z- r& p1 }- `0 D; d" b
二、代码实现
6 V v+ W$ L0 V3 z8 t2.1 Python 实现/ ]; C% M5 ~2 u$ ?& b
以下是使用 Python 实现归并排序的完整代码:- def merge_sort(arr):+ d% X' M- p7 L g6 e1 ^
- if len(arr) <= 1:! y6 O3 }6 n# e t
- return arr1 m3 y1 |6 V8 U; N# j5 R4 X5 D. t
- ) J) M# @2 y6 ^ {* l4 V6 H+ p
- # 将数组分成两个部分4 Z0 i, q: u\" H: D# K+ |) l) e
- mid = len(arr) // 21 |8 _ g1 E: c( J$ U
- left_half = arr[:mid]7 ?) \; o5 [7 E\" t1 I
- right_half = arr[mid:]
1 v\" J% z W( V - / D9 G6 R5 E. q5 e; {6 T/ E% j
- # 对左右两部分分别递归调用归并排序
0 q# V2 E1 Q/ o- r3 X N - left_half = merge_sort(left_half) ~* ^ P2 i; P7 i, v! v
- right_half = merge_sort(right_half)
/ G6 S3 C Q9 V5 z# A; ]. v - / z, [- e( H: X- q, N
- # 合并左右两部分& q& M1 m6 Q1 T\" h. [7 r% C$ [; r
- return merge(left_half, right_half)# y5 P! }1 N# x* f
- / \/ l* w9 P: }& ]5 v
- def merge(left_half, right_half):& R& O( J8 t\" H0 h/ K) i: p z
- i = j = 0& |: K9 x/ r) @( C, s. s( t
- merged = []! K* b, }. D) {7 m
- ! b. Q9 v {2 \. z8 p: s
- # 比较左右两部分的元素,将较小的元素添加到 merged 中0 X7 I+ E- ?. R, c
- while i < len(left_half) and j < len(right_half):$ b/ @0 n9 P2 \9 ~0 C' m. s {3 f
- if left_half[i] < right_half[j]:: \% ~8 S7 S! x+ j% R
- merged.append(left_half[i])/ N6 G P. ?- z0 c$ [4 k9 }
- i += 1
) r5 J4 i1 u1 T3 \( ? - else:
\" z+ y6 Y6 C% ?: w' N1 ? - merged.append(right_half[j])
, V7 d& u2 b: ]- W( M3 \ - j += 1- E9 P# P% d; b! [. L5 O, L1 `
-
$ c0 i' g6 Z/ c2 e& O - # 将左右两部分中剩余的元素添加到 merged 中
- e' e# O0 i7 T& w x+ A9 ? - merged += left_half[i:]. M$ x7 j2 a! m9 S/ x8 P7 j
- merged += right_half[j:]\" F2 |( V) q; X! N) d
- ( @9 G. W( |: a
- return merged
复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解: merge_sort() 函数- def merge_sort(arr):
# N2 F- A- s- h# N\" F6 I$ V - if len(arr) <= 1:
% Z; H$ R4 `/ ^ k* F - return arr* _/ e: h0 R. _, h
- \" |2 \( b* R7 t5 t4 H. P7 D
- # 将数组分成两个部分7 p1 Q6 P, P& D& v4 d# @1 ^
- mid = len(arr) // 2
6 v/ C1 d( M1 e% O9 K - left_half = arr[:mid]
% o* B8 l& F7 T* P' @( W - right_half = arr[mid:]
: f( _' ~, _: P( E -
9 [- m4 I# M9 {: u/ q - # 对左右两部分分别递归调用归并排序
5 R. s6 Q9 r) { W# N) x% N4 A - left_half = merge_sort(left_half)( J9 y' C* k8 R* L1 b5 B
- right_half = merge_sort(right_half)
+ ]9 x+ }8 A, l: B - 0 t7 i6 Z8 n4 L/ x
- # 合并左右两部分
# i8 ~3 e! N+ O# O\" x - return merge(left_half, right_half)0 F3 Q' Z\" m2 r2 U
- ```2 x& L6 X1 @! B2 J: [ ?- s
- $ U+ N* F6 e5 O. d' A. y0 y
- 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。$ h( Q# \7 E- h! D. M
-
复制代码 merge() 函数- def merge(left_half, right_half):$ t5 D\" k0 C0 P/ L0 ]
- i = j = 0
5 r; j' k. ~( v# @! D - merged = []+ G9 o, O# B2 y, Z; d1 z! G
- \" X) {5 M( F1 z, Z% p
- # 比较左右两部分的元素,将较小的元素添加到 merged 中+ y* {0 a1 o5 z* j( i4 q
- while i < len(left_half) and j < len(right_half):' i( t% S+ Y; _- D
- if left_half[i] < right_half[j]:( }- Z) ] v8 t( Q/ ~
- merged.append(left_half[i])
- {& w7 G0 ^/ `4 ]8 k/ h+ U - i += 19 E& e+ U3 G! Y; S3 U
- else:
) e& U4 c) u- s+ V - merged.append(right_half[j])
: |& s! g2 S7 Y. N; q - j += 1
3 d\" q7 F' v# u -
! R/ u% ^. ]3 e/ _! [4 m5 { - # 将左右两部分中剩余的元素添加到 merged 中
, g, ^0 b; @/ F: S - merged += left_half[i:]1 U2 {. N2 J. E5 W' C
- merged += right_half[j:]
: Q; o; H' [5 t6 q0 u - . b& Y) E. \! V6 n, n
- return merged% D) _: R1 \; Z
- ```, u. ?. h' {0 g: {: q
-
3 B4 T1 A* m) b8 Q\" x - 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。
复制代码 在实现归并排序时,需要注意以下几点:
- R; v, r H/ e7 _
* t' e4 `6 h, q$ K5 A判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。& ~ t$ W4 z3 _2 t$ d3 N/ w; f
% P3 q- o* c; \# t' |2 f1 R将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。8 l. `) H( b+ w8 m5 ?- E4 e
9 R8 `6 L7 L5 I对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。7 a( R# F* T3 I# N( x7 }8 o' r. `
) N" Z7 b7 L2 T! p9 `合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。
) d! A( l) p/ t3 }( r6 L! `" `; S3 b4 c- G' |3 f) [* }
测试
+ B& Y3 [# z( {! x4 D2 j在使用上述代码实现归并排序时,可以通过以下代码测试:- arr = [3, 5, 1, 9, 7, 2, 8, 4, 6]
- g& [* m: v4 a- }5 B - print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
. d5 f, E& T3 P" w, I) n3 \
) Z$ g3 A: c" p+ K总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。- ~9 F) A6 m0 U2 T( F' E4 y
2.2Java实现以下是使用 Java 实现归并排序的代码:
- public class MergeSort {! u0 d0 u. N0 S' q\" U* p! \( x
- public static void main(String[] args) {' w3 J. [+ Y5 e/ L) r! W% |
- int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};
# n6 U( d {# F: M! F# @' d5 `0 o - mergeSort(arr, 0, arr.length - 1); O6 k: c7 ^* |
- System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
Z& g3 `2 J! ?1 R4 k0 g* } - }
0 y0 x% F& y; ^; R e - / j$ R8 x) G; H! I( z
- public static void mergeSort(int[] arr, int left, int right) {
' \3 Y1 T5 f9 E& p - if (left >= right) {
7 s6 f3 Q5 n) h5 L - return;
( P' |8 s' n5 a) W7 g$ C - }
4 l4 D# O. P9 A% m6 j - + M: Y/ N; h' J& q% E+ p\" F
- int mid = (left + right) / 2;9 c9 r D8 n6 k. R& _! M! i8 P9 L
- mergeSort(arr, left, mid);- \, m0 m3 o9 ]! s2 q\" m
- mergeSort(arr, mid + 1, right);
* J; B& o% @8 r* h& ] - merge(arr, left, mid, right);
\" U( f1 o( ^( p W* _; v' s: p! w - }8 g2 K( h, Y0 A1 }, r* r/ F
-
6 d- m2 J' W: u& L+ y: R - public static void merge(int[] arr, int left, int mid, int right) {
8 x/ t& L; i% Q9 P- V; d - int[] temp = new int[right - left + 1];
' o& k\" a, \- Q W( g8 o3 Q0 z - int i = left, j = mid + 1, k = 0;) W P/ u2 O) J
-
2 B, R/ J; H: b1 j) ]2 q - while (i <= mid && j <= right) {
4 U5 {! e6 [# J2 d* _ b- p& j) d - if (arr[i] < arr[j]) {
1 }+ s& `5 w0 O4 }5 U% ^# z - temp[k++] = arr[i++];% ~1 J2 ^\" w5 u& }, {: t9 C\" T
- } else {
* i; Q! ?7 K+ v9 ^/ a. n0 d - temp[k++] = arr[j++];+ ~; h) w+ W7 j. ]2 g' p
- }8 G; a2 z; R$ S) p/ |# T- n2 s# Y
- }+ j# j) u3 y! X6 }2 w+ F
- % q+ B\" y2 e& E' C# t7 y( z
- while (i <= mid) {- _& u/ v. R+ V! z; u
- temp[k++] = arr[i++];
M9 t, Y5 w4 |* w1 ]: K% m - }
( w6 Q' W1 ~$ [ - $ t2 W* B; U/ M& E4 o( c7 Y5 t$ q
- while (j <= right) {
8 f3 ~5 b x# }+ k; Y/ y5 H - temp[k++] = arr[j++];
( x8 X4 N3 z+ t% d+ Z! t - }3 T$ x6 W8 `\" n
- - V; ~% s; V3 X% i7 O4 t) I
- for (int m = 0; m < temp.length; m++) {
2 A2 t6 t\" ^7 G4 n! h) u - arr[left + m] = temp[m];8 h1 E% g, d! B$ @ R
- }
/ g$ z3 X7 I1 a - }: D% `( ] N5 J
- }
复制代码这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。 下面对这两个函数进行详细讲解: 0 P1 w- o1 f- w. ~, O5 D
mergeSort() 函数- public static void mergeSort(int[] arr, int left, int right) {
. z9 t) D; r7 G% U# D1 ^/ o3 j* z - if (left >= right) {& Y% |/ S8 j( ^3 m\" {$ c+ R1 Q
- return;
) ] M, K& _& `% N$ Y0 b - }; f/ b5 N3 Y1 ?' K. o
- - E) |& p7 \% {\" _4 |
- int mid = (left + right) / 2;
5 E! [& T f0 ^, x - mergeSort(arr, left, mid);6 u0 }8 f8 G) T# e' m2 L- i5 \. g! C
- mergeSort(arr, mid + 1, right);$ E/ B; H8 h1 ?' E# m$ T
- merge(arr, left, mid, right);; N% D1 a5 J% K# X6 ~% O0 ?* U/ R
- }$ j9 I3 r$ ]$ [( \' Y, R# N
- 1 J- @) x/ a$ W
-
复制代码 这个函数使用递归的方式对数组进行排序。. I; S+ K9 J# @
9 {% p+ p1 i ?& z1 u5 G
对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。* ?/ a! N- Y# T. { \
9 m% l! [" e2 z' T
最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
+ @8 e. w8 m$ bmerge() 函数- public static void merge(int[] arr, int left, int mid, int right) {, }3 H1 P {- a: s
- int[] temp = new int[right - left + 1];4 Z: V2 N9 o2 H* _+ b8 q
- int i = left, j = mid + 1, k = 0;
j, ]: X: \0 L3 m/ A2 E - * a; v\" q( m3 y. K) v' Z; X7 V
- while (i <= mid && j <= right) {! t. ^! S2 ]( ^1 _5 u$ [
- if (arr[i] < arr[j]) {1 a6 L! `/ F. ]2 ?
- temp[k++] = arr[i++];' O* S6 K4 Z3 [+ d, I
- } else {1 F\" }\" c+ C0 v0 Q9 B! k
- temp[k++] = arr[j++];* g6 K: Z& L2 U, s) D\" h* R
- }2 T1 W9 f6 v( w% W- G
- }
7 ?4 I2 d8 m. y) z0 B -
' p/ Y1 R2 R/ P2 t\" V - while (i <= mid) {
' `9 t3 U. L\" u3 Z4 t( ~8 |$ @' ] - temp[k++] = arr[i++];
' P' \# P! R* [ F% T - }. p* m7 B; j- I\" w( j2 e
- 4 ^7 R' y$ y4 h! S6 r
- while (j <= right) {* [* C9 ]( e0 E% o2 J2 |6 w
- temp[k++] = arr[j++];8 D# X4 ]. H5 N4 w1 ?7 ^1 F7 P
- }' }6 @9 ~5 H! z
-
* ]( c0 |( `0 u0 \# Q3 e6 u - for (int m = 0; m < temp.length; m++) {, P9 Q2 ~! ]\" C9 Y+ W8 \( q7 f* R
- arr[left + m] = temp[m];
+ ?, R# _* l1 o% F( G - }
/ {. B, U+ J6 S5 `( i5 V\" ?\" N - }9 _1 F* U$ H5 ]: T\" ?
-
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。
; h/ B0 |6 O7 S( a9 E
( b5 U( d+ x% g& D* j' {- A合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。; p& s! g& D0 n( h1 _* Q
2 | F& a# q1 _" x/ I* |5 w最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。
: f: H: D/ ?1 x9 t7 ~- o
. _3 q) J0 v' d& r- g3 r9 S: [需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。
% a3 H0 @4 ?+ h7 T! N; A
! W) U3 J8 @' P9 b* I这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。. Z) n) s3 x1 T$ s7 U
# H: f1 F0 y- u1 T8 t
2 A$ l8 h- B1 @" l3 _0 `9 h" D6 G
$ w: w# S3 l( ~
u j1 p# ^0 t3 I9 _
: O, w* K; r" A$ G$ t0 {+ H
: U4 [5 z f0 r+ }0 \. i! a* w8 f5 T( X+ o' J% Y; g
|
zan
|