- 在线时间
- 477 小时
- 最后登录
- 2025-12-17
- 注册时间
- 2023-7-11
- 听众数
- 4
- 收听数
- 0
- 能力
- 0 分
- 体力
- 7772 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 2916
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1169
- 主题
- 1184
- 精华
- 0
- 分享
- 0
- 好友
- 1
该用户从未签到
 |
1 基础介绍1 @: \# Q2 D/ [3 ?, H: S# H
排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。
L! e8 ?& u# X7 s+ Z
$ Z! g3 g( }. P以下是一些常见的排序算法:
8 @% H, a! a# {, i0 l I# S* }2 D% ]0 y1 |0 {
冒泡排序(Bubble Sort)
4 v1 g& o0 |8 j: C' t+ t' L+ h d7 L0 ~' J
插入排序(Insertion Sort)
& D _ @; @1 Z9 A; _# H1 u g9 l8 i- A4 d% o1 r
选择排序(Selection Sort)7 s6 a9 [& X T' H
# S0 Q: H5 a4 g+ H
归并排序(Merge Sort)6 I& B. N3 B: m; _$ u0 J" W: m
+ Y( F. I6 A; z) j3 U! x2 g2 O8 w快速排序(Quick Sort)
$ I3 N2 ^/ O B% r7 n: X4 c3 i
1 H d2 T$ ?; x8 F4 i: R) o堆排序(Heap Sort)& w0 q! D) E4 R. V1 Z
5 v1 [9 W( }* o( N一、基本介绍介绍' b% o/ Y9 Q6 f/ w: ~
1.1 原理介绍
0 C/ _* L0 J- I1 f( I/ F归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。9 Y: T$ r* N' }& \ K e; _
5 F4 p" f8 z7 {; a4 }, V归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:* p; F F8 T" I% O" t
`; e- R4 [8 w1 d" L
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。
% f" v' M. p' @8 Z& O
0 l( S9 t; s1 ]5 R* M U合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。: B* ~( H1 s3 S7 a0 p- J3 t
) n& T6 [6 ^! A+ K: e3 h. m$ g U( k
合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:! @( K& S" }4 I
1 k0 r! y& Z0 g* I% _ ^
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。! V9 I; m5 m& n8 U
+ x: _* S. B4 ]$ R, L: ~5 l比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。% T" B4 |& s3 O* _
k# {# ^3 J& P: t重复步骤 2,直到其中一个数组的元素全部放入 C 中。2 [% C; Z) w! ^$ |/ _
& N# e* C: Q" r/ G1 K& ?' a2 B
将另一个数组中剩余的元素放入 C 中。8 b, L% Z4 m0 R% V
2 A' }. m3 A0 j: ]; r" O归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。1 U& q! X* f3 i/ H
0 d) i. T$ q, Z$ G+ I z" x4 p
原理简单示例 7 h, o0 N5 L7 d- k4 X! @6 C
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:% q7 _' q+ d+ `6 J4 x
( O6 j+ D; `0 E8 F
假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。
% I, k6 o% z" \; Y3 G2 a: `, D% B7 W2 q5 l- n1 q# |7 g
首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。
h8 u' A j2 ?; l# G O/ |9 `+ T7 L: {5 W" | R% A- Y
对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。
( ?3 t0 C" e9 |4 l5 g. s% ~7 j
" U' n! M6 I2 b1 H% _4 l1 p对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。
( n4 M7 ^' p6 }& q% `
$ c6 R; [7 n+ l/ B6 f3 F }+ p. M接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。: I+ a/ M9 m w" T5 H/ a4 Y
' H7 H8 d1 D$ }& s' L将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。" v& G3 C; R; j% H* A2 h
, g# ~* [; ?6 Y6 K& I& C. G
因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。, B% A( e. x% Y9 m; s/ _
% \1 @2 m9 ?' D6 }1.2 复杂度 8 o7 j/ D* P+ ^1 K$ G
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。) C$ V# g) X) f. C% h+ e+ t
) z% N2 A6 Z5 ?1 i4 B这个复杂度可以通过分治的思想来解释。
4 g2 j- Q0 X4 s1 S: N6 M. b; M8 J$ ^' C9 `3 F9 ~" b3 o4 g5 B, V
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。9 v; b! {$ v a6 @- m) L- X
: O# ~$ D1 M5 c
每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。3 Q$ o! ~( E! K. z) S' N
& |8 W2 S. D/ p- P归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。% b8 N; x- d4 t7 U) X4 H2 h
0 F0 u6 F5 z' {5 b) B' S3 r
这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。
! B) p, `: h2 n0 j+ {2 w, b
7 u9 ]$ M2 _# G* Y4 y# |5 s& ~1.3使用场景# c" f Q" g* L; `( I" E
归并排序的应用场景比较广泛,主要适用于以下几种情况:% a5 c c& C4 u- \* E5 \
$ t, ?. W. I6 A# E# c
对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。, l9 u6 s8 r$ [/ m4 K
5 S5 r; e& C) Q% b
对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。0 O" n# t; L: Y- g+ x* D9 o6 S% C
2 I+ r3 n+ j2 t0 _" {3 g对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。
' O; s2 E6 T$ c( K W; ~$ N8 |3 z, O; `1 U* T! g
对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。
- k8 @+ h7 Z. z/ {5 o& m: Z5 h+ t1 S% s) P9 w' Z8 {/ ]
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
b+ g- X& Y b* K! p* a' K6 q- E' D5 @# O( O3 e
总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。
9 G5 ?& ^" O/ B9 i
# C" ?! K, R2 M6 k二、代码实现
& {' u* U* u6 S; c9 [2 E& j: k2.1 Python 实现% F: v, J) a% ?" ]8 D3 P
以下是使用 Python 实现归并排序的完整代码:- def merge_sort(arr):$ @: B5 g) x' `\" @* }/ H
- if len(arr) <= 1:/ ~; A7 m4 L. E! f: C\" [& V
- return arr
- b, B/ X! h& [& n9 k5 I J - . i3 Q& Y8 U5 H
- # 将数组分成两个部分
- k$ y8 N\" c7 Q, J0 X, V - mid = len(arr) // 2% V* L# ]! G7 F
- left_half = arr[:mid]
8 G8 f. S3 d8 w, W7 L - right_half = arr[mid:]- A( T0 S& w7 _! j7 g9 w
-
6 h4 C* W1 I& n- K - # 对左右两部分分别递归调用归并排序
# |. L& d7 K- x7 Q - left_half = merge_sort(left_half), u; y' p2 _) c2 s F9 |' y
- right_half = merge_sort(right_half)/ x: a: P& ]\" h! E- |1 f
- ! c- B/ |) t: t( F0 |
- # 合并左右两部分
8 j2 H u. T2 M& b) }9 z - return merge(left_half, right_half)
8 x, O. u1 ^9 n Q G6 ~4 b/ L -
2 i: S! B) r( t0 V3 Q - def merge(left_half, right_half):
- F' L3 o: n* ^ - i = j = 05 d' Q8 f3 X+ V) k
- merged = []$ z' `' q# F* A* L* e4 I\" A
- $ z- R8 x4 g9 U/ ?5 b' u& I, k
- # 比较左右两部分的元素,将较小的元素添加到 merged 中2 l, H6 _\" _: P1 [
- while i < len(left_half) and j < len(right_half):
0 J {- F! B6 ^. V% H: A, k7 @5 {* b - if left_half[i] < right_half[j]:
! f$ {9 |3 z8 t# c - merged.append(left_half[i])6 E' y; o/ G. S* w& @\" K
- i += 1
, G- \: I. @0 V - else:
Q% l& i7 h4 y; q* N! z - merged.append(right_half[j])# r; L5 M* W) C7 ^2 c0 d) }
- j += 1
3 w% x7 P* n2 W/ G3 l -
0 m0 O/ o2 I- K' y; p - # 将左右两部分中剩余的元素添加到 merged 中
- @: j. S+ @: b& u - merged += left_half[i:]8 G, a8 L4 w: y( C R. l
- merged += right_half[j:]- ^) E: \/ O- D1 ] m* M& p
-
6 S# f0 D6 }5 Z3 r+ ]- p - return merged
复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解: merge_sort() 函数- def merge_sort(arr):
& O1 `( y4 g9 _2 S/ r9 K3 Y - if len(arr) <= 1:
8 E$ A1 U9 y5 W- [2 N - return arr5 d) L7 Z/ |6 m! |
- ( G+ ]$ I% R$ u0 @
- # 将数组分成两个部分* {5 M! D% L- b
- mid = len(arr) // 2
& y0 d+ |. K4 r; `1 U - left_half = arr[:mid]
. [, \1 [) G& i7 e4 x6 W - right_half = arr[mid:]& ~4 t% t7 y6 i; D9 p
-
; y9 u8 i- U- u1 G - # 对左右两部分分别递归调用归并排序3 K) ^& I5 W9 O9 z% t! A
- left_half = merge_sort(left_half)1 Z) `4 m) I2 g! C8 F8 a/ U
- right_half = merge_sort(right_half), A/ e8 ?* D9 X P1 v, S+ Y5 p& B
- 6 W! Q\" f V7 L, B6 |. j* ]
- # 合并左右两部分
1 s3 ^/ f, X% H1 S6 r - return merge(left_half, right_half)
5 g3 r$ {4 C3 K' }4 c4 W - ```
% }\" i$ l9 V7 a0 f- X1 ?3 \ -
$ l. s$ U7 Z ]2 Z( U - 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
+ F$ u% W, ^4 X* y, V -
复制代码 merge() 函数- def merge(left_half, right_half):( B) o; ^$ Y( ]8 z% F7 V$ i; L
- i = j = 0
2 ]7 ~: J6 n7 Y, G5 {! L! n. L - merged = []
$ o\" _' `1 K8 S, {) ^. ~ -
3 Y/ |/ D2 a$ n' j. F - # 比较左右两部分的元素,将较小的元素添加到 merged 中( h8 Q. n v4 y5 H
- while i < len(left_half) and j < len(right_half):
. o: h$ y, T0 Q) \+ P+ A& G - if left_half[i] < right_half[j]:# ?3 G! |$ A+ N
- merged.append(left_half[i])
+ E* S; Z2 \3 Q. X\" l9 _) D - i += 1; K. O6 m. J4 v$ e& ?' k
- else:
/ ]# W0 U. ?8 _5 x# @6 H& Q7 u, ^ - merged.append(right_half[j])
$ Q* Z0 B$ v `+ t\" m3 V - j += 1
% F# W6 e0 C7 N9 s' q8 h n - $ ]; H9 ~( F3 o+ w o' W; s
- # 将左右两部分中剩余的元素添加到 merged 中$ F\" m7 I R0 D/ r- P9 \0 @0 ~
- merged += left_half[i:]
/ }1 g& z- `7 B4 }5 ] - merged += right_half[j:] h$ l* _& b' `# h0 I8 N; v
- q& d3 A3 e; x3 c1 \$ ^. Y
- return merged5 W l- t9 S2 p+ l; K1 r& R. N
- ```' g* V. r. w! P6 X- e1 b' P, q' K
- 4 y4 P; u3 p: P' F- Y
- 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。
复制代码 在实现归并排序时,需要注意以下几点:
/ w0 B+ n, I" c& }( @6 f0 }( Y2 I
6 W& a( v* Y/ ]# }判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。4 u) K, F, ~ x4 ~
Q) u7 [2 R( ~$ T) u
将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。
" u- a/ v$ T8 z" o( W7 U7 J
' D( E2 m# { W8 w3 i6 G) O; M对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。& D1 H3 b! v! N' i6 ]$ p
% j9 _* U: y# F* F- n0 ?合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。
- D+ s8 [; a) D: i/ K
Y! m' T- h) Q测试
5 G0 X5 [. C9 J在使用上述代码实现归并排序时,可以通过以下代码测试:- arr = [3, 5, 1, 9, 7, 2, 8, 4, 6]
7 l& R# F' @7 n, m - print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
# r: a$ a) J" T& e0 J1 d" z( T
! R K7 f7 O0 S' k总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。& l; d, v" [! x
2.2Java实现以下是使用 Java 实现归并排序的代码:
- public class MergeSort {
$ r( s) I0 Q6 `: q* }# F, p% R - public static void main(String[] args) {
$ x2 `3 u$ |7 D$ |' ]9 ^- c9 L+ i# V - int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};
/ L; E$ o4 h9 g4 F' {! }0 D2 o6 V - mergeSort(arr, 0, arr.length - 1);\" ?; g* R. A4 G9 `: f8 E' }\" P
- System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
2 L\" { `8 M3 N8 m+ [. ^ - }
\" P; N+ `6 s4 H\" @) `% h -
$ F: f+ \9 B9 z3 u% l6 a9 [ - public static void mergeSort(int[] arr, int left, int right) {6 F5 f: ~3 y0 `% _& b# o( r3 T$ M- _
- if (left >= right) {
8 k' e$ A1 H# T2 U, z' a/ ~ - return;
, {2 _$ J/ K c8 X) F. K( k - }, ~0 J* }5 m. W; h8 D: {; i7 k
- - P9 B# ^' K X
- int mid = (left + right) / 2;6 Q$ Z! z% M+ Z8 Y
- mergeSort(arr, left, mid);
9 w, w! \* x! E\" r# j% t1 G/ x - mergeSort(arr, mid + 1, right);; s% D\" o0 c( W' E
- merge(arr, left, mid, right);
8 s' G( Z4 E' y8 l/ `* {& l2 g j1 K/ _ - }2 o' q) p* g) @; u- a/ r
-
* t+ K y- N6 t6 k: x - public static void merge(int[] arr, int left, int mid, int right) {
* y4 S2 Y* N. A. Q. g - int[] temp = new int[right - left + 1];
0 s! d* y# o( B - int i = left, j = mid + 1, k = 0;6 I( t# s3 ]9 W$ T
- ( U( \ v1 H7 u0 B- u\" J/ j+ i
- while (i <= mid && j <= right) {
' f# W9 F3 m, [* ^\" d/ ] - if (arr[i] < arr[j]) {$ i: ^4 O7 w% d5 R: }
- temp[k++] = arr[i++];
4 `9 V' a! H3 W# Y - } else {
0 I) g' n4 b6 `) e$ Y\" O3 M - temp[k++] = arr[j++];
! c! ]; I& ?1 Q/ F' e - }, w! z% {0 p- K5 d- a
- }1 {, @% E* D8 v' f' J
-
; C ?, e1 b4 q3 v& \$ t - while (i <= mid) {
4 \& u5 g; b\" w' S\" c - temp[k++] = arr[i++];
! y% c! s: U* t, F - }7 j$ r- a$ k\" F4 O, x3 y
- / v5 P2 Q- t3 Y5 Y# K3 _
- while (j <= right) {8 z3 B. t' {\" a# a9 f; Y8 y
- temp[k++] = arr[j++];
/ z8 z4 d; s4 b$ s - }5 U3 {: H& b( r/ {+ u
-
) r: o( H4 ~$ D - for (int m = 0; m < temp.length; m++) {
# a9 A4 q4 S u% k5 |; q - arr[left + m] = temp[m];/ ]8 K6 H0 z6 ^8 i) c/ t8 w
- }
5 D' A7 D$ {: n* B) O! { - }: |- ?! I4 o2 o5 r# i& j
- }
复制代码这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。 下面对这两个函数进行详细讲解:
& A; }( J0 L g# P. W' _4 y* U/ {0 ymergeSort() 函数- public static void mergeSort(int[] arr, int left, int right) {. q- F6 p\" m+ a/ L/ y2 K1 Q
- if (left >= right) {5 }) ]8 {, p+ h; Z
- return;1 [; h0 j& P- S5 G) ~- d+ @
- }
9 p- G. b3 @\" N* W -
+ n; n% } R$ f4 A t9 c, d, { - int mid = (left + right) / 2;3 @+ O# K/ a B\" n
- mergeSort(arr, left, mid);
0 _ X# J. l( k& ` - mergeSort(arr, mid + 1, right);
* R5 m& G* s: y: D& ]( u9 ?9 F5 s( V - merge(arr, left, mid, right);
$ \3 V4 i7 e2 P2 ?- v7 \/ m9 h. B - }
\" b( L. N/ f2 P: N' \. N( }2 z4 N - ~; t# [% S* [$ S
-
复制代码 这个函数使用递归的方式对数组进行排序。) H! B+ W1 U! @, H F1 d
& s% g5 a) Z; V: E. s+ E对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。# ^6 G# v2 N: V- \
8 p$ D5 R: ~. O6 t; W% _3 y
最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。% D/ K l- D5 N9 O) r: ^
merge() 函数- public static void merge(int[] arr, int left, int mid, int right) {
! P5 ~/ J- F7 x8 r7 x - int[] temp = new int[right - left + 1];
3 i; p$ [\" u! [/ F- a2 u - int i = left, j = mid + 1, k = 0;
8 H8 s' M) A7 E' }7 B6 F m -
7 W8 P0 {* r3 I/ A% a4 j7 _- k - while (i <= mid && j <= right) {
# J* W% g Z* U- v( Q - if (arr[i] < arr[j]) {1 S. t* z5 c7 t# [. D+ M5 L# \
- temp[k++] = arr[i++];
$ R! Z7 j6 r6 V/ j - } else {5 l; j. X8 x\" X5 l1 T
- temp[k++] = arr[j++];) ^5 v( u. Q: m; {* e0 `; F
- }
) l9 c8 z, @' f. L - }
$ { k. X, z\" o, |- j5 z D -
, F7 K2 Y5 u5 d - while (i <= mid) {8 [' B3 q( N( {2 m* Z+ z0 l
- temp[k++] = arr[i++];
% @( [4 r0 J8 p) Y. h8 \* f - }/ l1 z) v3 d, ]( W7 D\" P* _2 t+ U% i
-
: F4 {: F$ j/ P8 x - while (j <= right) {
! i# f# S. C# D$ c! j8 ~ - temp[k++] = arr[j++];
8 n& m5 {; N/ n+ G; y - }
( r8 \2 u9 ?+ E* r% y. L -
8 }6 O7 k) d: H; w6 Z - for (int m = 0; m < temp.length; m++) {
0 C7 h' Y# S' X - arr[left + m] = temp[m];
0 P0 e2 R- L! H f' n4 g - }
! c# B8 [2 }5 Z! s$ s7 e' K - }' j# W& V' [) x. X' v, ]- a0 _
-
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。
9 k' M9 \% f8 X# `0 r4 [5 m! m& K' H* W
合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。
" @/ {% T/ P8 N; S( x% s; k
9 j( |* K- x5 c& ]最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。
. q; L- K; s) g
% L2 [2 B" w6 T1 }( k需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。6 F( O* N b+ o7 x. r
* E/ }. `: z8 }/ H( {
这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。" R' d: J' O) ~
- W' v0 _6 C3 n
. Z# q/ a! D3 p- L9 C% L1 u+ y/ @# }; N- v( _
- ?. a. l L9 Q3 k1 G
! [- s3 X5 ?8 a$ Y0 q9 \* y
( x% p' O2 D% q
; i1 v/ N- N0 N |
zan
|