- 在线时间
- 462 小时
- 最后登录
- 2025-4-26
- 注册时间
- 2023-7-11
- 听众数
- 4
- 收听数
- 0
- 能力
- 0 分
- 体力
- 7236 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 2749
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1156
- 主题
- 1171
- 精华
- 0
- 分享
- 0
- 好友
- 1
该用户从未签到
 |
1 基础介绍
3 [9 [0 i g. b3 P0 ]排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。5 L* f$ \8 k0 C9 A% u8 }
. n+ h4 U, \5 {5 s5 Z以下是一些常见的排序算法:) L% Q0 J/ x$ B; ?$ f) w# D6 m
: \3 F! s, [1 \6 U% T* x& i冒泡排序(Bubble Sort)
/ C ^; J' S! f1 U, J: K, T5 Q& _# O! {5 H
插入排序(Insertion Sort)
& \, v' }: N3 z. j M& H+ v; C5 y# b; s3 }! K( [7 G% p
选择排序(Selection Sort)7 }; D" s& v: }9 q! W
! N! c, K2 g8 @; {" L1 S: L6 d归并排序(Merge Sort)
) i- [; u3 \. q: q* F; h5 E
5 c t- [! w, H$ x8 e' ?5 l& n快速排序(Quick Sort)
) U6 ~4 |. K4 h5 s+ U8 Y. A" t9 R/ f9 b
堆排序(Heap Sort)
5 B. q9 Q8 _* P$ B9 e
+ N! | Z% @, h C2 N; _% W( }8 k/ r一、基本介绍介绍9 s/ s; e9 e1 t7 S0 k! D
1.1 原理介绍
- q' @6 ^7 _# D归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。- |& e+ s5 h/ Z' p) \& }- o8 C
9 o: h$ B8 W/ U7 p* y) Q5 O归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:
0 `) w0 n0 H. v* x4 l2 M1 H, W$ Y& U, n- p) Q3 P- g
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。( {( P1 ]( n5 T, g2 E' G7 I
/ S2 ^+ y6 ^' T) W _1 M* x0 C
合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。9 H( H/ b, n% T
1 G) c. R# e4 `; P @: A* T. y5 H
合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:( Q4 ~; P# k3 }
2 e9 N1 ?* d, ]3 K: l9 D! B( U" H: A: [
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。. M/ k. I" D3 Y% {/ k+ W6 L
4 B! p2 B, C) x( S+ L0 C
比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。
9 v1 ^' J- H, I
N6 u# X$ R, E; v/ x0 t; f$ E重复步骤 2,直到其中一个数组的元素全部放入 C 中。 {: t$ t: H+ ^( [( Z
+ r- F. X9 y& r* |2 }2 {* M
将另一个数组中剩余的元素放入 C 中。
$ i3 w8 c3 u2 S' v1 p, d$ q/ s7 M# @, o; Z: Y2 s) v
归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。0 S' Q, o1 K) N H
! H5 M/ |( G" U1 ]& t原理简单示例 5 H J/ T/ T$ r/ ` [( t
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:7 P% t: D+ B( h, v- c
5 \4 ~7 A& w) i" s
假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。: [* _8 b u! U/ O* @1 H
0 g O/ |# A1 o3 a首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。
& S) ^* s* g$ M y Q# r- q6 S& z3 [6 B6 q5 C
对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。/ v! V: l, ~7 D0 Z5 [
' ^( f7 w+ n# C0 \" {* N+ F对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。/ A. ]/ s" V* Y7 G Z
5 j. h4 g6 Y: f) P
接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
% X9 D/ W. a0 r6 r6 R) @
. p0 l. f# k6 c/ m7 O: F将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。) L1 d7 D) h% T2 a% Z
7 f0 q: n3 M2 A# j2 r' q* }
因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。
; D& W3 w+ H/ m9 f, \* V6 t* ~+ ?" h3 K6 |. }$ Z
1.2 复杂度
6 p$ |& i- _- Z9 m, b3 ~5 {归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。+ w/ U% U8 h1 }
0 |& N* Y! O: M2 o$ {! o) h这个复杂度可以通过分治的思想来解释。4 C7 s0 r( C8 I6 W
3 N$ q N9 @% R, O1 N8 B
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。2 e% z4 L5 @4 r+ N% `% i' J5 B
3 }+ w, y( f3 a! E每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。! A% t a* R7 ^9 c2 D. L- `
9 @( ]; ?, N8 P; I- { o
归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。9 @( K2 q7 ]5 o7 E$ H# _! l% K
( Q: L6 W! \" H6 I. s! w1 s
这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。7 N2 H; u; l( X; A" s) Y3 ~
3 E: L7 m h/ g8 T
1.3使用场景
$ X H4 V% l: D# {% a6 s: f归并排序的应用场景比较广泛,主要适用于以下几种情况:7 A: v/ j$ N! _# U2 i
4 _3 K' Q& {4 _- n2 H. d4 Y/ i
对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。1 v4 b7 j" b5 O) Y# m% D
( a# z8 C; E1 V' d! X9 U- t# N( w6 v
对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。
4 k( I# z* t& @! z2 B, P; H2 @3 a. n, Y
对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。$ d, B# \# Q: C; N! r
9 |( u! ?9 z4 p3 S5 q0 S( ~* s
对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。
. p( J3 U5 O" I9 B1 g0 B; h+ K
$ r+ s3 j9 d7 G' c/ [9 q对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。( u! r7 H1 U0 @. i+ ^! A
! {8 g; h; d+ }! ^9 [5 a总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。
( ]! G% k0 m6 Z6 C( [
& w2 i& Z2 m; h A* B) N1 X二、代码实现" C2 R1 E8 |& i6 r! @7 p8 s' Q( a
2.1 Python 实现
' A0 y' {' \( y3 b2 n# C以下是使用 Python 实现归并排序的完整代码:- def merge_sort(arr):8 v% I1 R8 u+ X' y+ G* |$ \6 F* _
- if len(arr) <= 1:( L% Q5 t3 w2 P( _ M1 f
- return arr5 x; ? t) G$ o* n\" G3 g; E1 E
- . [4 x\" o$ Z; o( T. i
- # 将数组分成两个部分4 H {\" T t* T9 a) |- A4 p
- mid = len(arr) // 2
+ m- ?- b1 d\" x# y m$ e! c! `% Y - left_half = arr[:mid]9 Y8 p9 j4 V\" x: z
- right_half = arr[mid:]9 n0 ?6 Y* g( X2 t1 q2 c\" A$ |2 r, l% y
- . Z4 F0 M( ~- _\" ?& ~- u; r
- # 对左右两部分分别递归调用归并排序5 [' c4 S6 m9 j5 n
- left_half = merge_sort(left_half)
+ \3 F) L: y W* S! x6 {8 `% Q - right_half = merge_sort(right_half)
7 c. k/ f1 F! n5 y9 i# X y -
8 w\" a1 |$ Q( c; v) @: X - # 合并左右两部分
9 W8 b% ~, \4 Q& P f6 C' E5 h% w - return merge(left_half, right_half)
% _7 k$ G' s* D9 n2 Z( r -
' l8 @# [) [% M' @4 ? - def merge(left_half, right_half):( s: I) A+ r' _% Y& H
- i = j = 0& O8 Z\" `! }' B+ P; Z+ E! I% k2 i6 d
- merged = []3 o( ~ ?1 u' A2 s
-
z- M4 }' n/ S3 a- P9 m, L - # 比较左右两部分的元素,将较小的元素添加到 merged 中
/ h9 U+ s9 a: I3 C$ { - while i < len(left_half) and j < len(right_half):
0 N7 K, M& x7 U# \5 A7 T - if left_half[i] < right_half[j]:
0 Z- Z\" d( E! q( T* o* P# U - merged.append(left_half[i])& |\" f a( K* T; Y# J$ t
- i += 1
8 }7 z9 @$ @/ l( ~8 m k( u- z\" ^4 X - else:
5 m\" k0 h4 q! p ] - merged.append(right_half[j])4 c6 O$ G- d- d2 T+ F& G% b
- j += 1
/ M- }& }2 H J: o2 C9 j -
3 e r. f. U7 p0 \ u. u - # 将左右两部分中剩余的元素添加到 merged 中; h# V6 ~- U$ e n
- merged += left_half[i:]0 |4 ^! K% w\" |\" c* m+ ^6 `
- merged += right_half[j:]/ u: u5 n% Y0 T
-
5 v% n$ w& W& Z' K2 ^% O0 K - return merged
复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解: merge_sort() 函数- def merge_sort(arr):& W; M! i8 G5 c0 `
- if len(arr) <= 1:
, _6 ^7 R5 O* q# ^ - return arr `) T3 e7 B' W' Y7 C
-
- }( i$ u3 `) C0 w - # 将数组分成两个部分
0 j: `0 B% m8 i1 b$ i - mid = len(arr) // 29 m! A M; k, m+ D6 s
- left_half = arr[:mid]! R& h7 Q5 j. ^2 @0 _\" g: O
- right_half = arr[mid:]
\" u2 P: H9 r! A8 e& M* o1 B, f - ) i# I! C# r/ z9 l+ S
- # 对左右两部分分别递归调用归并排序
1 {* y+ X; A Q/ K! f - left_half = merge_sort(left_half)* |* J9 Z) D( w8 z7 F
- right_half = merge_sort(right_half)
/ H0 m, j: a* t7 Y, G - 9 L4 {: f9 l) J
- # 合并左右两部分
1 r; }( \; r& j, ~# M8 y - return merge(left_half, right_half); C0 _) U+ l/ Y! C+ `0 ?
- ```9 |7 o3 T- e5 T3 y5 K
-
9 s1 _( Y% K* w0 [2 ` - 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
2 h& x) |5 X' b+ t( a `1 h/ C -
复制代码 merge() 函数- def merge(left_half, right_half):$ t/ i6 c. T8 V
- i = j = 0' a) J1 o9 C, z/ u' u
- merged = []5 t( H4 C9 v. u3 p
-
: t\" y8 N5 v; B: W% u* O- e. u - # 比较左右两部分的元素,将较小的元素添加到 merged 中
/ }- P9 G6 v! F! d0 b* Z) o7 e - while i < len(left_half) and j < len(right_half):# S- [2 m A/ M2 Z
- if left_half[i] < right_half[j]:
) b/ s' c' W3 C% \4 q8 w$ N - merged.append(left_half[i])# e% X* ^' P) U/ l8 z, E6 o* ]: `' y
- i += 1
- r& K6 k3 ]9 l# _# s - else:
: r5 P. u9 R& p\" G0 { - merged.append(right_half[j]); i( f& W9 c9 j( K
- j += 12 O' D+ Q. R8 B% k
-
; f7 `4 U# C6 \\" ]$ {5 v9 j: `, i - # 将左右两部分中剩余的元素添加到 merged 中
) i0 O/ A7 {\" c: p M6 [+ d - merged += left_half[i:]4 Q+ N/ R0 |& A; q1 C9 {0 j
- merged += right_half[j:]
% d9 \# [! J9 r1 q - 0 z) k* }, A2 {- G' y% e, K# K3 d
- return merged! V b* N+ {/ c+ J\" z( b7 Q
- ```
- `* A6 Z: i J# _. J; l - % R0 W1 H3 |6 O$ u
- 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。
复制代码 在实现归并排序时,需要注意以下几点:. P( F, K+ e1 X! W' w
$ ~( l- M5 }' u B+ X9 V' W
判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。
* h+ b4 ~, N! I# f5 O* z; g7 i
# k! j4 h# M2 Q9 j, C2 ~将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。( W% b5 y0 i7 R% S3 @# W9 E
# _* h/ e/ Q/ E. P- Z7 }
对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。" c: p" i+ O3 _- Z. q
/ a/ ^* n8 b2 S9 \" x
合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。
3 l, z1 A0 m4 i) q/ a9 q
: i; ~2 I. L% D" F7 P; c. E% y) ^测试 - z `) a! H5 R8 k( }: L
在使用上述代码实现归并排序时,可以通过以下代码测试:- arr = [3, 5, 1, 9, 7, 2, 8, 4, 6]3 R- @8 b6 O9 Q0 M8 ]. F
- print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
6 Y# A( `- W, I' r; j- V* k1 w
- k% |5 F% C6 U: m3 L2 _- E. M总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。0 v- {/ \& X) j" H/ x
2.2Java实现以下是使用 Java 实现归并排序的代码:
- public class MergeSort {+ o! V) f/ x6 A& {/ x7 |\" X, N
- public static void main(String[] args) {. N2 i2 i\" F& F\" V, n3 E
- int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};
0 m* J! u8 t* \, `) t$ p - mergeSort(arr, 0, arr.length - 1);
W- Q! q! ?2 n1 g+ H3 f8 [+ a - System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
6 a% D l0 p: e; C1 k3 g - }
2 ^, w3 L. V! \. u# w f% ~ -
0 n$ H/ g& ]) H8 K- z7 C - public static void mergeSort(int[] arr, int left, int right) {& Q! ^) t3 C. [6 i; ]\" @3 q
- if (left >= right) {* [( g6 B/ N* w5 U: k% P! G8 w* j
- return;& K* Y7 Y* F C1 [: |
- }
/ R- F1 z) {- C9 A - 5 z' Q6 H K1 d. a
- int mid = (left + right) / 2;. a; g! i8 a0 R\" n! c
- mergeSort(arr, left, mid);3 q7 @/ M7 I1 w1 `
- mergeSort(arr, mid + 1, right);4 F+ X/ v. R/ ?' A
- merge(arr, left, mid, right);3 q3 i- b3 i) r! [8 o) s4 T
- }# Y; s! M# p9 H
- ) z* s\" n4 g. T# j2 L( l; I( W
- public static void merge(int[] arr, int left, int mid, int right) {
; C3 r0 z% b! m7 i2 P0 E - int[] temp = new int[right - left + 1];
) @# j% n# d# v0 K7 i( z - int i = left, j = mid + 1, k = 0;! _4 N) d8 ?2 Z! x7 e% p
-
3 u+ @5 h, ^% S; V - while (i <= mid && j <= right) {\" S# g( j9 @2 F% Q% N* j/ U1 l
- if (arr[i] < arr[j]) {
, n* c8 k& ]* T/ ?- n) l - temp[k++] = arr[i++];
\" \& l3 l' b9 T* v& g - } else {
- d( |2 j% L$ R; M& T - temp[k++] = arr[j++];# K4 G* [6 B! ^+ i$ r- X5 o; Y
- }* s8 E( d1 `. o q5 `9 d
- }% N7 v5 q/ R8 |1 l5 z) J. ?' G
-
& @: |# a: x: Z$ L/ M* F: L - while (i <= mid) {) G6 `% `, j% M' E
- temp[k++] = arr[i++];
8 ]) L% o A/ Y, n - }( }$ D+ A, U/ `+ O! N
-
; B, z9 A0 p9 A: o- m\" T( R - while (j <= right) {' y5 ], ]. f& d\" V4 d
- temp[k++] = arr[j++];9 e/ V& C4 |) Q
- }9 e3 W# r# ]% f
- * p- f, W% O- m, @/ ~
- for (int m = 0; m < temp.length; m++) {* u7 N: }( V( m
- arr[left + m] = temp[m];
( P6 H* a6 c4 j! \ - }3 l+ I% L8 s( Q
- }; U: A- ?$ N8 q& O8 v! K
- }
复制代码这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。 下面对这两个函数进行详细讲解: 8 p' w1 A) @# |& p3 m4 d- W
mergeSort() 函数- public static void mergeSort(int[] arr, int left, int right) {
- C B! y, c) @0 c1 n\" u1 C - if (left >= right) {. J6 T6 b6 K: B' v& o
- return;
: i+ P2 D% T# y4 d: T- \# `$ L- x - }\" I/ M3 h4 u: p& |1 j/ f7 W
-
/ e% o5 q\" h) U - int mid = (left + right) / 2;
0 O5 ]( |5 h9 p% f\" g1 S - mergeSort(arr, left, mid);
* E: l$ V( ~' W, J+ R - mergeSort(arr, mid + 1, right);\" a& ]4 [: k# D' Q: V1 N3 M, }! N
- merge(arr, left, mid, right);( `! l- E L b6 J1 h9 P
- }
: P4 `$ X; r# O -
/ P( `% {9 h# d8 V* x -
复制代码 这个函数使用递归的方式对数组进行排序。) k: B# ^6 C- H/ p' k O1 r: p3 B
& a- f$ i' h. _对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。$ B# S% L' Z' I) |2 F
/ \) D! S' n3 P5 v
最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。+ W, [# B) N7 x) H9 g
merge() 函数- public static void merge(int[] arr, int left, int mid, int right) {
1 o4 r* D0 Y\" x7 h7 V2 w - int[] temp = new int[right - left + 1];
Q$ l\" M/ M3 R6 [! v - int i = left, j = mid + 1, k = 0;
6 h8 b0 k E% w$ A u8 l& t -
* p# E2 ~1 _) y' ]3 q+ D - while (i <= mid && j <= right) {# J, V5 a' h7 U5 D. b, S3 \0 ]
- if (arr[i] < arr[j]) {
# P9 G- b, T( b! f - temp[k++] = arr[i++];. V# V ^9 h3 V0 F
- } else {9 P# i- f+ t+ o0 a
- temp[k++] = arr[j++];8 J% R1 z0 r0 q9 |3 D
- }# r B: a( a7 |. c3 ?\" {* M
- }2 w2 n7 P1 Y3 g
-
* m: Y5 J) c' n - while (i <= mid) {5 Z& n9 P5 t6 Z+ w: a
- temp[k++] = arr[i++];# Y9 e8 o6 ?5 m: a( n\" e
- }1 F: h8 ?\" v6 Q7 l) U
-
& d1 p4 I( P; \/ S* B. j - while (j <= right) {3 q2 L! Q+ o) R2 q
- temp[k++] = arr[j++];- p8 E7 q& z9 T
- }' b% P2 p8 C) V5 V
- - D$ d# O- Y9 A4 J2 b @5 e
- for (int m = 0; m < temp.length; m++) {
- Y/ d; d' d/ p& e0 ?) {# k - arr[left + m] = temp[m];
! C7 q% Y$ |. c; h! S# I - }# \$ K! a1 a5 B4 X6 o. V\" |
- }
* h1 \6 h\" ]$ v1 t6 o7 G- y -
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。" @2 `, p8 L- I( K4 @
0 n5 b( r" v C5 d
合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。
0 |' v; N, Z7 F6 z
5 d1 T u2 G @& o最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。8 O' C# U/ W4 ^+ p3 G5 D! r4 r [
% q; P6 I# B4 b
需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。
% J9 W- t# z# `% H( F6 u* x* |
3 q6 d$ ^' c8 X. T. m这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。
; z& o; ~9 q/ T$ t, x( i+ Q
0 Y/ l/ T- C9 k0 P9 B8 r5 K: @2 K9 f4 N- C
) s6 ~" Z* E! ` v7 M# ~( b- F& [' I: G$ m8 @3 F
1 d6 R% j# ^4 Q6 F3 m. ~2 Y! X x
' V- W2 ^+ G5 _1 \1 F* ^8 u7 m2 h% j2 k& {; ?# {! S- Q1 o
|
zan
|