在线时间 482 小时 最后登录 2026-9-11 注册时间 2023-7-11 听众数 4 收听数 0 能力 0 分 体力 7953 点 威望 0 点 阅读权限 255 积分 2978 相册 0 日志 0 记录 0 帖子 1183 主题 1198 精华 0 分享 0 好友 1
该用户从未签到
1 基础介绍4 V' c- H, M8 W/ I1 p
排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。( b) i! f- \% _ V/ Q* W
- h4 W/ v( l8 o3 [; m 以下是一些常见的排序算法:
' q; t0 U1 ?! Y! b $ i& }5 X! S* T, W
冒泡排序(Bubble Sort)
3 F+ `, f- k( E. l 0 \( ` t8 H# i+ [7 U1 Z( g: @
插入排序(Insertion Sort)( ~% L/ [- v1 Z4 ~" }9 p6 j
( A& ]" ]: G0 Q* Q2 X: Y ^9 D( @6 o 选择排序(Selection Sort)
6 K/ g) E1 V8 e. [" K- N + b3 ^! T5 q, m8 `2 v0 C7 ~. F0 ?
归并排序(Merge Sort)% n. |- w! N5 j( m I/ n
* x: n$ `4 B' l& w2 I3 U
快速排序(Quick Sort)
4 ]- d+ l8 p9 N4 x1 I - v- m; J' _9 Q8 v, {) ?
堆排序(Heap Sort)5 I; \% _: a9 X+ M+ l
+ l9 n9 u8 X- L# u, E9 s O7 U 一、基本介绍介绍* `4 @- `/ y0 D# V5 Q
1.1 原理介绍
2 p" j0 f; C+ E 归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。
u* ?! W5 v& Y2 S& i" `# s 9 a3 F4 A' d, j6 f* Q: U R
归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:/ l2 f& T0 z/ c: c
) K8 l3 Z6 a4 \& ?+ @% g: T$ B3 I
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。" H" P8 r* a4 p' D$ W& K! a. g
" R4 ^, D( |; C& ] i+ [+ V( [ 合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。& H8 L1 c2 {2 ` n
( A& \; P. N- u, a9 a6 | r 合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:) c# s* ^, }% N2 |
+ d( z- [& j2 V6 _9 J, M
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。4 T1 T6 X% X) Z; D2 Z
, t: K; M: ~- y3 m$ a 比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。' o6 Y6 B9 C, [$ N: ?8 R
3 T9 m- k8 ?: e I* w 重复步骤 2,直到其中一个数组的元素全部放入 C 中。/ s, h2 c/ X) F6 V3 B7 q% G$ Q0 s. U
) S& |4 B- `5 z7 g7 g1 V8 v; U
将另一个数组中剩余的元素放入 C 中。
: \6 d1 h/ ~( u% o1 M
2 q' a* k6 A# D' r2 G4 l 归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。5 g2 b4 O' K- F+ ~0 x
, X# Y& X8 F) w
原理简单示例 8 v. R" N3 |' p7 s1 ^/ j: v' f
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:
" F: j: o, `9 o2 N$ g# t4 [
# l e8 ?& F; g8 q9 m! ~5 y% G 假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。
2 Y, W# ~# q( R) X$ g, u) p
' E$ A t5 z2 p8 Z# n: {2 g$ A 首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。
1 T' B$ L+ ^4 @5 t5 Q6 I
' p, s/ X, _; p, s# c 对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。
; v- e" r3 r' ]0 H1 }# c* P, |
0 H; O. f" l1 U7 t3 W" q 对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。# u% P* S5 k$ R) x t" o
E- Z9 g* M/ {( b' T 接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
7 M" {4 B% U0 x8 s3 |# o; V W% i 3 R3 R$ S) K; G, I* L: o
将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。; g Q$ {9 z1 w) B
% u; Y ?% B- A5 q. S" s 因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。' O. _. |$ q6 U: x" Z* y
% M- r; i, c# ]) Z# k
1.2 复杂度 2 S! O+ A& y" l
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。' n8 `: f& D- L9 n: R6 v
/ E$ I8 B# v g) W4 G$ Y# }
这个复杂度可以通过分治的思想来解释。/ O0 v; T" q5 |0 I' H
( V) O2 N/ O) x, n
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。, H9 K8 C8 K2 z) D. N. [4 c
5 U9 C; b$ ~' M1 |7 H$ I 每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。! D/ R0 g- |# m/ |
( F% o P; Q2 A+ P* R! u 归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。6 t* O6 a/ r. ~. x! J( Q
7 g6 Y4 Z' ?; S+ y, K2 @ 这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。
6 \# ]: I2 ]% s' f7 c" A7 J
2 S9 T2 K& w" `" z0 R 1.3使用场景
5 J5 U+ U8 i4 Z [+ w 归并排序的应用场景比较广泛,主要适用于以下几种情况:; \- b {- G N4 R! l) n' r" l
+ `; R) U6 p& o8 j
对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。
, [% {" Z y$ U0 L2 s3 Y D - L: |% j/ q. n2 n
对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。
# X& D* n6 c6 v% s- n' d: ?
# K! _3 b) ]; B0 f& `4 | 对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。
% M3 A F" g" s! P- `
! V! B3 p% ]& Q0 S( F6 R 对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。
/ k# M6 Z0 t7 N; \# L ; f9 N+ E; }8 e2 T0 K
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
: ]4 o7 L2 I- f: \* j# R 6 V2 ]( X! D/ o: @# v0 x
总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。4 \! [" L" d% f8 M4 t
! m2 P% W9 |" C3 e6 \( q 二、代码实现" b; W4 _1 i/ h3 z+ v2 n
2.1 Python 实现4 p/ P+ p0 J, a! S8 d+ h0 @
以下是使用 Python 实现归并排序的完整代码:def merge_sort(arr):- p+ K3 T! m- A7 E
if len(arr) <= 1:5 z2 j3 U$ X. x$ @% G$ ]/ w+ X
return arr
# Q/ x. l: y8 C( S1 K0 y 8 E, A) ^$ @( q: K1 T1 g3 f8 K- l
# 将数组分成两个部分8 W, ?. @\" d4 b' q
mid = len(arr) // 2% l0 r* j0 V3 Y3 G# o% i
left_half = arr[:mid]
( y\" U* x. K, E$ s8 t right_half = arr[mid:]
3 ~/ _2 b% _) ]
2 c3 l% f$ a9 a$ L # 对左右两部分分别递归调用归并排序
S. {0 H+ r\" \! b7 x7 y\" Q3 w left_half = merge_sort(left_half)
: E$ ` v* L: S- Q right_half = merge_sort(right_half)( x! U% @+ n* v+ M
3 p: V: L& m6 T l7 X
# 合并左右两部分# M2 d1 f+ T9 z3 W) L
return merge(left_half, right_half)
5 f$ V, K P+ @! Z: m- o: Z
9 e5 z! W7 W0 H5 Z: b. q2 R def merge(left_half, right_half):# v+ D/ M! i) P4 |8 w2 A# [
i = j = 0
' i5 o; P' L2 q merged = []
8 V6 Y* t2 ~% f5 v / O6 t! i7 Y% c/ f\" D1 Y
# 比较左右两部分的元素,将较小的元素添加到 merged 中% v0 ~0 N+ \8 I0 S: f$ W( ]* n
while i < len(left_half) and j < len(right_half):+ I7 Z\" o3 h0 C( }7 `5 I
if left_half[i] < right_half[j]:6 Y, e* u' E% ~9 x. o- B3 e, I
merged.append(left_half[i])7 Q6 r `/ r% D, j
i += 16 ?2 J2 P g' w( Z W7 S' q
else:2 w9 v\" ^. `4 ^0 d& w k( Q
merged.append(right_half[j])+ u* b7 T4 l; A0 Y R, G% B
j += 16 m) `, [6 Q2 s: w\" N, {: l$ S
- v w2 q( c\" o\" W' ]% P1 S* L9 B
# 将左右两部分中剩余的元素添加到 merged 中\" O& Y9 Z3 X' O+ i4 H
merged += left_half[i:]
6 a6 v; K; O4 b. H merged += right_half[j:]
7 E, B* e! k2 `\" D1 h7 k% B6 i! { 5 }# U4 d\" Y1 W1 Y8 P+ T
return merged 复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解:
merge_sort() 函数 def merge_sort(arr):% |$ Y) m9 j+ c9 Z
if len(arr) <= 1:
\" i r4 l! C: i- N return arr
2 y2 Q0 @% W- f7 Q2 ^ v
3 Q- _. @' ^! F0 [- E+ n( U # 将数组分成两个部分0 N- M. J3 n9 D. I/ c
mid = len(arr) // 2
; i2 B3 E/ z& W\" R( Q9 P' O left_half = arr[:mid]# [1 `* b1 ]7 W7 J( N
right_half = arr[mid:]
) r8 M5 @& _6 Z! r
7 |, `& z\" m; P2 X- \# P! r # 对左右两部分分别递归调用归并排序
. X5 m2 ^# J; p' C# O2 R. | left_half = merge_sort(left_half)
\" v7 o\" ?\" ~9 g9 {$ h) l% O right_half = merge_sort(right_half)
7 O2 ~+ u% m! F' v( Q
4 y* r1 R( {/ w # 合并左右两部分; C+ I1 y/ z* L( ?
return merge(left_half, right_half)
$ }2 Y$ \, G8 I5 M ```
; S( {- _ B9 N1 z. O$ L
( P) d; W- b5 i6 t1 N: O 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
# Y* P K; n4 g. A; v/ r+ D. \! G 复制代码 merge() 函数 def merge(left_half, right_half):1 S6 r Y& D7 c% _; R, I
i = j = 0; y F7 G: _) \
merged = []7 o. S8 i: H4 q0 B! k
) E0 `3 r8 L& R) {9 C3 r6 s
# 比较左右两部分的元素,将较小的元素添加到 merged 中 k) ? T/ b7 B/ L N7 D
while i < len(left_half) and j < len(right_half):
3 k+ |7 p/ e\" T8 H5 W if left_half[i] < right_half[j]:& Z, v/ G$ X. \3 i7 L6 l
merged.append(left_half[i])
; i# W3 t6 T9 U Y7 T8 v6 t! V i += 1
% l) v\" {6 j' b( R6 o, g$ C w else:
t- \# ~+ p% X+ o) X+ U6 l/ s merged.append(right_half[j])- c3 F& O& y& X' ^* x
j += 1
8 u* s3 J, `- G; j4 @/ N
1 t\" J) }' ] [% F+ c. ^4 ?' c- v # 将左右两部分中剩余的元素添加到 merged 中8 J# e$ g k/ F* e& n7 c$ r4 O [
merged += left_half[i:]
1 Y8 I5 j3 s3 r merged += right_half[j:]( n. c% v2 i8 j
' Y5 \( l& ~1 `9 f+ r# m
return merged
2 [: Q2 h1 E\" N& p' u ```
/ J0 Q0 w; q0 k9 U# l
& K& Q! ^3 c6 W( U6 @ 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。 复制代码 在实现归并排序时,需要注意以下几点:
T* k' i: Z- O7 a5 g
7 l* V( {+ G4 {0 n. h# y) [ H 判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。 T% M9 C5 B; N# X! S8 ?; `. `
+ ^( T. n1 p, T8 ~' Z+ R$ v 将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。
n+ ?4 I# e1 E+ n* I : C2 d/ ], r6 p' E
对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。8 g% {, E( ^( T: C9 s
/ X9 ]* z6 W+ W7 [8 E
合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。5 Y) Z! K5 g0 I6 E) ]; N/ A
, u) J" D+ \/ }" C' g: a* m 测试
2 {7 `9 q( a0 ^' O7 j/ o- g 在使用上述代码实现归并排序时,可以通过以下代码测试:arr = [3, 5, 1, 9, 7, 2, 8, 4, 6]4 k- Z6 H; r0 B. h. }0 Y
print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9] 复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
/ h' ?( [( Y Z0 {8 z! L; E 6 R: q' f" ^9 o; I0 n* j
总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。* m9 b5 ]7 f. `
2.2Java实现 以下是使用 Java 实现归并排序的代码:
public class MergeSort {
5 n% }9 H; i1 d: R; i* |0 s public static void main(String[] args) {
( x* q9 S# t; W1 P\" `4 Y$ j, j- \ int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};
S* N( w+ [: w* l) r/ K) \ mergeSort(arr, 0, arr.length - 1);
/ K\" o1 _! ~( K System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
# }: R v9 y0 ]+ j4 p' v }+ y0 c1 t3 I; K1 L
& X: E9 G1 x* N( X, ? public static void mergeSort(int[] arr, int left, int right) {
3 Z6 _1 s. M; Y3 M9 n* k if (left >= right) {* f( ^% U1 C7 ^0 ]
return;
- f4 K8 A* V# v# v: R }6 n9 J3 o# y1 K6 \$ u9 U* L
8 u: L& L- ?. @, l0 f
int mid = (left + right) / 2;
' d8 m/ E3 }# r6 r: U mergeSort(arr, left, mid);4 |4 T9 b2 m% \1 V
mergeSort(arr, mid + 1, right);
$ k h; w* q, Q' n) u! ?\" g0 P, a1 l merge(arr, left, mid, right);, U4 d& a& P8 Z9 @5 Y
}
0 x$ j' \1 G' }7 i) r& ` ^
) K- I! T& b2 J; X3 e: f4 z: ]2 z public static void merge(int[] arr, int left, int mid, int right) {
: X X6 Q ~4 F7 M+ R( g6 H int[] temp = new int[right - left + 1];3 }/ Y3 ~( a\" A0 }& Y
int i = left, j = mid + 1, k = 0;
5 Y0 h# N) m. \\" t' L; S' g8 w; ? 7 t1 @* d1 k( N
while (i <= mid && j <= right) {
2 o5 w% y' b6 ^1 B w1 l\" w, h if (arr[i] < arr[j]) {$ Q: {% Q8 K+ t# Y\" P9 }/ `
temp[k++] = arr[i++];2 N) E\" H\" ?6 G6 c. n7 z/ j& {
} else {4 `& S- v, A% @: j; K\" D& T
temp[k++] = arr[j++];
$ ^2 l& _8 Z- n1 X }
7 G U, a* ?9 c: v }5 Z( ~& W w/ C2 V; E3 V2 p. i
L) O\" x3 a: e! |: Y- `6 q+ q
while (i <= mid) {. }3 l0 x& E7 o
temp[k++] = arr[i++];
0 B& F, M! P( }9 g6 L8 J }
* ]) ]( {% u( ~6 @+ D 9 L' b$ @3 W2 G) V
while (j <= right) {
/ `- S0 l- L; {. s6 q: w: O( t temp[k++] = arr[j++];
/ f# |& T5 W( I }
/ y6 D7 L0 Y1 A: p1 w) h, }3 r4 J9 j + e z( G& }- ~- ^4 \0 }: m+ V _
for (int m = 0; m < temp.length; m++) {; j! p, `: }5 w. H
arr[left + m] = temp[m];1 \' V) t/ S& T8 ^, P% Z( b$ ]
}2 o( t) d8 k- D6 _6 Z
}
' [4 K' I& g! v( S: d: z3 f } 复制代码 这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。
下面对这两个函数进行详细讲解:
O9 y8 Y! ~) M) p0 @
mergeSort() 函数 public static void mergeSort(int[] arr, int left, int right) {
9 K5 Q4 q0 x9 {# l if (left >= right) {
. b' d0 M5 A\" V# }# Q' v return;0 c1 c D: M( C\" Q0 g; o6 b9 G! C
}
9 R$ }: f( ]- t5 t$ B
9 o+ P7 \\" O$ X) ] int mid = (left + right) / 2;
! B+ F: j% a; y mergeSort(arr, left, mid);\" U: | w0 a9 T9 Z9 x- N* w2 V
mergeSort(arr, mid + 1, right);
! x! `1 j2 `3 y) u1 T\" u/ Q merge(arr, left, mid, right);
, m: G; c8 P7 k5 s' j }1 C8 g; V9 j# l) R, [% B- U
) ^& {: B\" o3 a9 G: V, C\" a: m1 E
复制代码 这个函数使用递归的方式对数组进行排序。3 q3 j6 V5 A% G. I+ @1 N
: ^1 \8 n. p9 s* j+ c: l 对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。/ p* p5 C6 m3 x+ _" H
( G) g0 h H6 J: ?8 R 最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
: U0 v* W. L- c/ g ?, p) E merge() 函数 public static void merge(int[] arr, int left, int mid, int right) {
. M: U* ^% P9 Z, s/ r int[] temp = new int[right - left + 1];
8 i' W\" Q9 i8 U; u1 q& U3 v7 M* v int i = left, j = mid + 1, k = 0;# l\" o* y4 y M6 d7 t4 e
1 G. h! s6 o% o1 ] o. l0 D2 ^! Y; ^ while (i <= mid && j <= right) {1 q) h; j$ t+ `- R
if (arr[i] < arr[j]) {; f6 D0 ~. l: \
temp[k++] = arr[i++];: k4 y! P* a- J6 @& m
} else {2 F, [% s! a\" C: T5 |$ x4 a
temp[k++] = arr[j++];
( G( B7 a: y& i/ n& g/ a }
\" i\" b& S% S. N$ m ^8 ?+ F. f O7 X- P }! H. e- G( s; Y8 Q; O; Q
, |* @( g3 |5 t$ p while (i <= mid) {- D# p/ R( q% S9 l8 Y2 z
temp[k++] = arr[i++];
; i) ^4 N) e8 i' z& V z' i }
) }% w! m; x0 \. Q1 T. T, y
( L' U! B, L b9 t0 L while (j <= right) {
% f3 w# b' E- [, |8 s- s temp[k++] = arr[j++];! j6 X) J; _\" C& l# j. ^
}
# C2 R$ r5 W& m # ^$ \! j, S' d8 q+ K
for (int m = 0; m < temp.length; m++) { ]) F$ e% e' A! j; B. T) P
arr[left + m] = temp[m];
% P* {' M/ c0 a- O\" J5 C( L6 x }
7 X; h$ ~4 w\" e- V$ e5 p1 i }1 q5 q; C: N: Z\" X+ p* \
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。
8 K7 X( S' z* ]6 D1 O6 r
3 O- K7 h# g7 u5 S3 l2 n, z* u 合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。
9 h/ c/ e; M1 b$ D d( F+ [1 \4 M' L
5 [& z, K& V; \# ? 最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。9 v8 |3 `( j$ S/ x
6 ^- z; a; K' I% {& E
需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。
L+ `6 h) j$ A; z* a& I" X& a - c, {& O1 [. Y6 k3 ?
这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。/ Q8 a# G: R8 T! i0 ]- Z
J: |0 @: F- O( x2 ] , g/ s# L G4 p- z* p1 h
: M/ E$ d+ {" z" l * L8 r5 X+ z1 r5 S4 d: ?, Y( p; G
! O0 u' ^# {: N2 l 4 }+ l& g6 c+ u3 s9 n% C2 D
) x& e% K+ C0 L
zan