在线时间 462 小时 最后登录 2025-4-26 注册时间 2023-7-11 听众数 4 收听数 0 能力 0 分 体力 7236 点 威望 0 点 阅读权限 255 积分 2749 相册 0 日志 0 记录 0 帖子 1156 主题 1171 精华 0 分享 0 好友 1
该用户从未签到
1 基础介绍
' S& J# u( K0 a 排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。3 l: L& T3 E+ t+ p K. l" A$ l+ _
) n( k* i5 D4 W* }/ M: `* [
以下是一些常见的排序算法:# I+ u: b$ q7 i& L
& w" L' K) f) a; F5 R 冒泡排序(Bubble Sort)2 S' A, N) k4 m9 T4 L& |2 D5 g
: D/ A6 s7 t" j$ a% I4 c3 h 插入排序(Insertion Sort)
( B) [, D/ `2 o0 c% `9 G; s
* O+ @0 \- _6 Y 选择排序(Selection Sort): x) k* k! n J8 x. r% W
$ e2 P6 K p; [7 Y' f+ f* z+ m2 t
归并排序(Merge Sort)
1 Y' n1 x0 G8 x/ I" N % z9 @8 I7 B; R! C% M! D
快速排序(Quick Sort)2 c+ K4 u* k. M# m9 B7 ]
+ `. {( }5 S5 a 堆排序(Heap Sort)
2 N U) @" s5 C+ m * ]3 w* G. l. C
一、基本介绍介绍6 F! [& i# V4 h, P
1.1 原理介绍
5 F8 |1 L8 X1 \2 @! Y 归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。: Y& M7 X3 x& `( @7 D: o `
- \: W9 ^ q0 t. W( ]
归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:) Z( c6 G) @6 l3 J1 p
1 ^3 U7 m1 E ~4 j/ I( P+ Z
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。
2 d* q/ H* q* }# {3 ^, i! d / g h5 J7 v0 c
合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。& \. A- b# t) O, j0 W0 K
4 O0 m: a& z# L# R' S 合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:5 Z d% T5 y u3 H6 I9 y: h
7 l7 x7 V5 \6 B& E2 b) M
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。 E' ~! D. ~3 |7 ]
" f2 W4 B5 P) t9 J 比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。
9 F5 G G* g3 h$ i ( h3 T7 j$ W- r2 D
重复步骤 2,直到其中一个数组的元素全部放入 C 中。
, v7 W. c. [/ o, S7 b * Z: Y7 c: o1 ^# D. y
将另一个数组中剩余的元素放入 C 中。: }; W0 t( h( j/ J
: [' C) n, R: c9 i2 _/ {: z( B 归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。
! q- }) ]/ B5 \* u5 ` : P- V. E( L+ d7 }( ^, b; h) y+ I
原理简单示例 , c& w. d, v8 x$ F# y! B9 R: l, r
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:* h3 t) L( Z" s4 A3 Y( @" i
3 q+ E: } A8 ?+ N. h
假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。
: e: X) m3 w1 X& Y# _ + K% ?& n+ }* ?: o& n/ s
首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。 d( }( r2 o4 _: d3 Q. i
5 G8 W2 z% q/ W) e8 B( i
对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。
, K! s( Y' E$ b% O! D# ~3 x
$ X q8 w! l d. s$ [. c, K9 Z5 ] 对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。% D2 B- ]% q a
/ d! q0 X" ?$ V8 f$ O 接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
1 g3 x4 X9 ~# h' B5 M
2 k! k6 e6 _' D8 U" g( ~ 将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。1 T) J# Q$ W' a" m2 Q1 O' h
, J5 ~% I/ V' g' a% K
因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。
! ~, w- I. e4 `( f. X0 s, p/ O7 K/ C U: h# Y* y9 _5 c8 Z1 y- ~8 y# W7 D
1.2 复杂度 1 j9 D9 u! n1 q! r
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。' P# {# [% C1 o7 S% c! E# h
7 e. H5 p4 W% }6 S! r 这个复杂度可以通过分治的思想来解释。
+ }. U. C& H5 S' ~) C # H$ A4 _# N5 {, b; d
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。
# ^9 J, W1 ?' p& K8 _0 Z% n& }* C
* Z2 s- A3 B8 C1 V* }; c4 T 每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。
" C1 B0 k6 N$ {2 o( Y" @( f- }
" U* \. |& t; X 归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。& h# \. G" G+ d8 S
8 J* ^) |% W% D9 o 这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。
+ `3 K2 {$ y" K1 ` I; f' M 5 {4 ^4 |5 n! X. B
1.3使用场景4 f$ n( H4 V5 |8 P' \: }$ t, O2 [
归并排序的应用场景比较广泛,主要适用于以下几种情况:9 @$ T9 x4 W+ U
- ?! V& o3 G8 a$ ~4 S9 K' p 对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。
! V& a& z& G" t& ?0 L5 I- N
3 Y# n& [) X7 c; w 对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。3 z. c* m- v9 P/ j) M# v
7 q8 ?" U7 N+ \ 对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。
$ ^! H6 R* k6 ^) H9 [- e- I8 W + n, ?# k4 Y, r/ W
对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。5 r& n( D: W, \( S; H z. ]
x8 V8 |6 b% }2 @% X' G
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
& S6 y& K1 _7 ^) H# j+ `
5 y+ D) [. N) l E( i" D 总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。6 Y& W* w7 |1 e% m6 r
0 H( b2 `# R3 j. z3 j+ |! R4 T 二、代码实现
+ N6 c- k# O: b1 c4 o 2.1 Python 实现
4 e& {5 S9 M$ C$ Q4 n+ [ 以下是使用 Python 实现归并排序的完整代码:def merge_sort(arr):
L* A\" ]# N' a! }, @7 z\" e) U1 |# E if len(arr) <= 1:
# Z! Y- O3 p, ~\" r- L return arr
& y\" t% u3 \, ~0 P
8 J* l* `+ D1 B, V8 w # 将数组分成两个部分
/ K! R5 ^. z* z, z- A2 O: f mid = len(arr) // 25 a9 j+ [+ @- g! V4 Z8 Q- [
left_half = arr[:mid]4 N1 H+ }1 `) p4 Y& D$ a& W
right_half = arr[mid:]; Y: Q: u; G. e
* G8 W1 v\" S0 O2 }0 l* ^ # 对左右两部分分别递归调用归并排序
+ d) D\" N8 j: `- j- ~ left_half = merge_sort(left_half)( P& C5 [2 A0 s9 l% _ ?
right_half = merge_sort(right_half)# L: C\" \& `* b( j! w+ C/ d
+ w, r- B, J( ^' G5 A4 e; } # 合并左右两部分7 u\" f3 @5 `1 C. K
return merge(left_half, right_half)
# u z, H0 E\" L& T\" k $ A$ ]9 |8 q. d- e& O& E& g) i
def merge(left_half, right_half):; h0 d: {- d, k
i = j = 0
; i# z1 P/ W* h* k8 J\" N merged = []% A: @8 A7 x6 P% c/ v( [
7 D' h/ u& O E% @ J: I # 比较左右两部分的元素,将较小的元素添加到 merged 中+ [- l9 L1 s+ w# L
while i < len(left_half) and j < len(right_half):3 O9 {( D; u3 y% t( Q6 W
if left_half[i] < right_half[j]:
. ^1 S$ v# Y3 Q2 g\" [ merged.append(left_half[i]): {- Z! u5 d0 }' s3 W0 M
i += 1
% I; E5 J) I: F( Z2 r+ x else:) O) ?! g8 U5 W+ t
merged.append(right_half[j])3 Q' B6 ~0 H* b+ N
j += 1
+ a+ U' d$ Z3 M; D, E. p
8 I! x\" Y* Q% N y # 将左右两部分中剩余的元素添加到 merged 中6 a& ^! v2 t* ^+ n/ {0 _
merged += left_half[i:]; s8 }/ i! U, a
merged += right_half[j:]
( D6 H9 w- ~+ C5 K $ G9 J/ z$ `3 e3 I
return merged 复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解:
merge_sort() 函数 def merge_sort(arr):+ i7 X& c5 [( M; {
if len(arr) <= 1:
H* J: T/ n0 j' o, ?6 E1 k return arr1 w6 s- ^) J7 j; S1 D
( O/ K: G9 z; L; x # 将数组分成两个部分
: w o; r\" D! g mid = len(arr) // 2! K+ d\" P- ]: K2 r( I: `, }
left_half = arr[:mid]; b' }; l\" j& c
right_half = arr[mid:]# w& d! n9 i0 _9 u* L0 D
% x r+ W\" ^- \( b) B0 R) b
# 对左右两部分分别递归调用归并排序: I! M5 z& t- @# D
left_half = merge_sort(left_half)4 z% D0 t\" F\" r( G U
right_half = merge_sort(right_half)
) W3 t6 D7 ~2 G 8 P# }, K\" J1 B3 u\" S+ @( J
# 合并左右两部分9 K* l\" q, p. M+ b# j' Z
return merge(left_half, right_half)9 m, k& V. O3 f1 n6 x+ S- {
``` w! x5 |6 l0 ~% s5 k
5 m, M- [: R9 v7 x% i9 ]% d
这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
5 b, r [1 k4 y* f% D9 ` 复制代码 merge() 函数 def merge(left_half, right_half):
! K; \0 l. e; q4 Y. L$ u* M' t i = j = 0
. U' T0 C$ r3 W5 \- g) u merged = []4 J\" D2 L; |+ r7 c
4 e$ g+ G' T, m # 比较左右两部分的元素,将较小的元素添加到 merged 中
' E/ N H2 a/ @ while i < len(left_half) and j < len(right_half):% p7 }* M6 J6 h7 _/ a
if left_half[i] < right_half[j]:# Q5 A; q1 S! A4 ?
merged.append(left_half[i])
: T' y4 @- j7 u i += 10 x- g9 c* n! H4 b/ F3 V
else:
: p$ _9 v( _( K, x* x; I merged.append(right_half[j])1 Z5 T\" M\" y/ X6 }\" l! Z
j += 1
( X9 M2 K) f) J2 {. b
- }& h% |; d9 i4 Y5 L # 将左右两部分中剩余的元素添加到 merged 中! K, S. c: D& l; B* U: @2 `! e
merged += left_half[i:]$ J4 O( A\" Z. E9 H$ m6 \$ Y
merged += right_half[j:]
; ]& c. m6 K' j6 l- B) _ 1 @2 I# _/ Q n
return merged/ E) D; b. C9 J3 k9 X
```1 P- r- z1 T1 O- v; C1 U4 ?
2 i+ r* r8 K M# n; c 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。 复制代码 在实现归并排序时,需要注意以下几点:
9 c9 C% c5 F! _- J \; C0 }. @/ o' P: Q8 D
判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。, y. q; X3 W, ^+ [% p6 @4 r7 T, D
) ~5 C$ f9 ?- k0 y, q
将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。" x2 A0 h: m( g8 K7 {% R1 q5 k& F
! Z( O x2 G% v& ~, o
对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。
% e5 |/ T0 X% v2 i- x
6 b. P% |' |1 M( E q6 c, N 合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。3 ~$ S( n/ S0 b, [
b; a, l" F( ^ 测试
7 P. ?- f7 G$ A w# \ A+ _ 在使用上述代码实现归并排序时,可以通过以下代码测试:arr = [3, 5, 1, 9, 7, 2, 8, 4, 6] `/ C$ _+ j* R+ H& N) S# ~
print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9] 复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。& L$ g; Z: Z0 \+ X
, W: v9 K9 O" V. T5 B 总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。4 Y9 |4 f3 v/ `& l
2.2Java实现 以下是使用 Java 实现归并排序的代码:
public class MergeSort {9 Z c/ F$ A\" F2 P: Q+ C+ ~ G
public static void main(String[] args) {
) S\" A' m/ z- d$ a int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};: [6 W\" ?+ J F. V( B2 m9 d
mergeSort(arr, 0, arr.length - 1);
\" p8 l3 |8 g) Z9 V- x System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
* A1 H, H6 t7 K- ^4 v2 Z }3 [0 j& a. Z# U
( ~/ ^$ i8 I1 Y- n/ E8 m public static void mergeSort(int[] arr, int left, int right) {/ k! ]$ Y7 I' R0 s1 E! u5 L
if (left >= right) {
0 j\" w4 e- E, A& E/ L! e7 p return;$ c4 m- n6 \$ Q! O3 S5 S9 p
}
& t0 C7 i' i( S3 z
0 J# s, t5 k: a int mid = (left + right) / 2;
$ k2 X. S* c9 Y6 m1 E mergeSort(arr, left, mid);
0 R) C4 y& t) { mergeSort(arr, mid + 1, right);
; c+ W8 D1 N. o1 J merge(arr, left, mid, right);. b9 o+ o5 h* E- y3 U& _ \6 j5 a
}! l: e9 b2 f7 K+ S\" }
L0 H' ?5 J, U/ e* ]
public static void merge(int[] arr, int left, int mid, int right) {
( i7 X+ |- U\" n& f# _1 \ int[] temp = new int[right - left + 1];. h$ q( Q$ ^/ z$ f5 v
int i = left, j = mid + 1, k = 0;1 I7 L8 ?& Q- I
9 K( z. l$ T) j2 m' D5 n
while (i <= mid && j <= right) {
, u- }1 u3 [& e3 X if (arr[i] < arr[j]) {0 k% N- b) [: D5 K( l\" H+ v
temp[k++] = arr[i++];
# h# x- k v3 p, ~$ o( z } else {
: B& |- ?7 ~2 G% N# ]% P+ V2 N temp[k++] = arr[j++];
0 y, Z7 H9 J9 H, ]( u3 X3 R }
5 x+ R( p% q( R9 h& s }
8 p5 ^7 N9 y; T* y& p) d ; k6 s/ f, y }7 a2 J
while (i <= mid) {; ^$ q\" T7 f# {7 g. z
temp[k++] = arr[i++];
9 b! B9 h3 V: u+ x5 ^ }
5 n: ^1 A# M6 W+ S0 A \" f6 ` N; r; K! p! b- u8 [
while (j <= right) {. x: C# z# |/ Z% F
temp[k++] = arr[j++];
! [% g' k) s! T! t+ O0 E2 e7 b }
. t0 j. Q1 l3 v3 c, m8 h $ i! J F- m0 `7 w$ A* J
for (int m = 0; m < temp.length; m++) {
: F: l4 [3 H9 R+ F( w6 U4 J arr[left + m] = temp[m];1 F' O8 S' {+ I: X
}& _5 r6 O; S2 O* [3 |: i
}, I O+ c) |: U1 A\" ]5 B
} 复制代码 这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。
下面对这两个函数进行详细讲解:
. d9 A. |! U6 C& g
mergeSort() 函数 public static void mergeSort(int[] arr, int left, int right) {8 l6 [5 n6 g) ~
if (left >= right) {0 L, L. r& u/ G! L; F
return;# |. g: I& r7 u& c& a! t7 d
}
/ e! {6 f+ f u\" Z; b9 [
' l, c3 E\" Q* v$ s& g9 P int mid = (left + right) / 2;
3 k1 w+ X$ b: b6 j% V9 X, ?( y mergeSort(arr, left, mid);
+ k& ~) F8 \# @ mergeSort(arr, mid + 1, right);\" b% G w* e# ^+ ^6 s9 L
merge(arr, left, mid, right);
! I. O+ E, M: l) E0 v* R }& A% X/ X; |9 r7 |+ l& ?- w' T
1 L& n( @) V3 l5 [
复制代码 这个函数使用递归的方式对数组进行排序。. m; N& x' w2 e3 c: D2 ^
1 S% I" Q- P8 G e; L, V; ] 对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。
' m) L2 c% Y% d
8 p' s2 d/ {5 G 最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。" C4 c) `( u- a! m
merge() 函数 public static void merge(int[] arr, int left, int mid, int right) {0 _9 `7 }4 S2 J- ]- I% q0 }9 ?
int[] temp = new int[right - left + 1];7 u: \# j) G Q: }. ~\" q
int i = left, j = mid + 1, k = 0;5 y' I8 r6 u9 |# r) {7 }' V
$ K4 f5 D9 N. ]- p2 M2 x8 S/ m while (i <= mid && j <= right) {\" z5 e6 |/ q; n3 ~4 d8 F\" c
if (arr[i] < arr[j]) {4 E# h4 [\" [+ J4 x3 K
temp[k++] = arr[i++];8 U) @: v3 L# _1 v- L
} else {; i\" g) H0 R9 ~
temp[k++] = arr[j++];
/ R' Y( o* Q O7 i- T$ n5 R }2 u6 n0 ?( g o
}
; \7 r, E5 H0 }6 A: X- r. T ) U' B0 u5 F5 x& T! N) D( l' `/ t, t
while (i <= mid) {8 Z [( W\" c; _: b0 i( \/ l
temp[k++] = arr[i++];! o! L- Q- v5 T0 F
}0 |7 g6 N& j9 n& P
4 k2 A$ i' l2 Z. Q; l' e8 f while (j <= right) {
% h* ^9 Y3 }1 Y- G temp[k++] = arr[j++];
2 v1 Y\" ~$ M3 U* d, @, `: F }6 Y4 Z5 X\" ^\" w( Z
# g! w& B( M( `: D
for (int m = 0; m < temp.length; m++) {) b: B8 |. z7 R* S2 J7 r' a% s
arr[left + m] = temp[m];# v4 M5 W3 a: J- u. E W, L
}
+ j& Q3 B5 c# \& A, o }# E5 V% r8 U: j, T! o
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。0 v9 m% r7 |# A* M
1 {6 [3 F/ [4 R- E- I0 _
合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。+ F. t' @* Q. M& X' ^3 \: T
% X5 I! s# w0 y2 n( S: B9 q* S
最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。
8 f9 Z% z- w8 {, c
( ^6 X0 c# @ o) b8 H! ~ 需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。
$ F1 b1 M7 Z* Z8 Y
# T+ i/ a& l5 @2 V# E8 N2 x' [ 这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。- u3 ~1 p. y) k, y
# s' D) _' e, @! b* K1 y1 X ; x2 x: h# ^. B" s, u) r
( I3 [4 d# K n" h; i$ x3 M; H+ m2 f # ?+ q! v, a* D- C( H6 T, C9 B/ s
9 T& Y" r' p2 ?+ t
4 g! h+ D- M) w" ]$ U$ W6 `
5 w6 t, a. S1 @' \- s
zan