- 在线时间
- 481 小时
- 最后登录
- 2026-8-25
- 注册时间
- 2023-7-11
- 听众数
- 4
- 收听数
- 0
- 能力
- 0 分
- 体力
- 7859 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 2946
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1177
- 主题
- 1192
- 精华
- 0
- 分享
- 0
- 好友
- 1
该用户从未签到
 |
1 基础介绍 u' {. z( V& R" p
排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。. Z* L& c. c. M1 |5 v' L- D
3 b. K8 `! I/ b' n9 e以下是一些常见的排序算法:5 ?+ K3 t+ ?4 H3 M5 t
7 W' g$ f- t. B. w冒泡排序(Bubble Sort)
`2 A/ ^8 \" i/ x4 S% {9 h& W2 }0 F f6 m
插入排序(Insertion Sort)
5 b Z2 y% g. T, S* i. n* g& c# X8 b0 a/ K4 t3 w
选择排序(Selection Sort), U' u7 | P+ W6 j1 T
4 n) Q: [" r! Q/ i0 C x9 K0 U
归并排序(Merge Sort)
3 ^0 V( S1 U1 b1 L7 h( v1 k: U/ L! u7 B7 x* D* `
快速排序(Quick Sort)
6 d4 {1 m+ ?3 V. p6 L; z2 I0 \2 Z$ {
堆排序(Heap Sort)$ O1 k* W8 t' G$ Y% B* Z# `
2 `+ N- Z T' [: X8 G
一、基本介绍介绍
2 L. d B4 z" I! X' `2 }% r+ ?1.1 原理介绍. o+ H5 @+ g2 `/ {' @
归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。5 u A5 `# S: r3 X, _
" o0 @6 z9 R8 ?$ u# ~' m归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:
# v' o; s* W+ V& q2 U4 n
! b5 e# e& T$ _) V0 q+ P; C分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。
& f* ^, j# D0 N$ h3 H- y' ^6 V% B; _ a2 |' X. J$ l$ ^+ s- h
合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。
: H) s) ~) S v4 p
1 V: J4 A( o- K D; l合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:
7 N% w2 A, J: F/ A! |' |% ]/ u% M; C8 w6 H
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。
5 \; j9 e0 L* [& ^6 B9 n# x, F {% ]( m2 V2 r* y$ P
比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。
( s1 ~, `& k$ W/ `; Q# o4 b9 y) G, N: `) ?/ J4 U4 q L6 l
重复步骤 2,直到其中一个数组的元素全部放入 C 中。, t% e9 g2 I7 f5 i% ~# ^9 [) j
& j3 \8 q( }: H, a) z+ W( g将另一个数组中剩余的元素放入 C 中。4 V9 @9 V/ |) y& |
- y7 A+ j: r0 L& }; {0 w
归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。
) R0 k% t$ U. e8 @! l. z( G7 Q! k- x) j) U. Y3 v- n* ^
原理简单示例 / ~ y( L# u9 b; C
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:
. c& @* u+ i+ x5 B, y5 X) j/ D2 p. @; M/ ?3 q u b5 R
假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。+ [9 q' ~& v! `) |1 H
' }. z ^9 P$ w$ q9 k0 ]6 J! D
首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。
& W G& A! A1 l: t/ Y% @0 j- g; D' e- a
对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。
8 J. L! A+ c; w1 ?
1 a0 \$ v% a1 U+ \ @) K对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。1 a2 U; `5 s( l
5 q7 I0 a, s' H5 Y. O1 b接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
4 {9 S. _ Q; o$ T" U' [
6 ^7 M* O1 \+ i将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。
0 X3 g: q+ ^9 Y w4 q: M# Y. V6 P4 C: o/ f) b6 R$ d
因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。9 W, {" _8 F h( z# u& i; T
( k: h V* m. ^0 \ @
1.2 复杂度
i i# s1 _8 W9 q归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。
0 C1 O' `9 B& v" H8 T3 t# H! F- e9 G8 [' i% A
这个复杂度可以通过分治的思想来解释。
0 P$ f8 B' }! V: O Z" A5 ]" {! t& z2 F5 s& v
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。
1 x+ f2 v9 v% i' X& a; u' A' A8 k( l1 w
每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。
/ B3 S! e, ^. X4 k3 R ^; P. _* Z }2 [) n% p8 o$ t% ]& R' P# |6 [, C
归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。
5 ~) {1 a4 w$ C8 S# `. k5 C; F# x4 b$ p/ v2 v) }- |
这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。+ T. n$ u) S( I
7 U, ?1 j6 n' v1 W4 d2 |
1.3使用场景0 \ k1 V! c* \$ Y
归并排序的应用场景比较广泛,主要适用于以下几种情况:# x( C0 m0 z4 }7 |$ x2 g. X: m
. r# L/ v9 @5 C* U. M对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。4 X$ u3 a& w x! D# Q4 r
; o) w6 ~. O% p7 N+ Q对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。
S5 h$ w9 z, }3 e9 { Z2 t7 J# B% W) `2 Y( g$ e; F
对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。# @, j7 E1 Y8 [ ]
4 T4 K" R1 U; J; V. w+ Q
对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。' ]& y( }4 n6 ~+ k4 Z$ p6 R
, U- L" ~$ }4 p. S
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
7 g5 v: A- D5 _
1 q: s& K8 E& l- A总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。
& _5 ~# F: s% b9 e
' x5 ]5 ]5 e& q6 }7 B; z二、代码实现
" Y! k# z9 l# v7 g" M9 I0 e, A) \2.1 Python 实现: J: w' ^, h- p: r! m5 ], r ?( x% P
以下是使用 Python 实现归并排序的完整代码:- def merge_sort(arr):0 x/ H$ ^. W% h\" i# C% M: `. l) n
- if len(arr) <= 1:
\" _& `4 N( J Q2 d m - return arr
1 ]: \# q( I3 A -
\" R! C2 C$ O; i3 ?& d& M8 }2 O x - # 将数组分成两个部分
: e% Z3 B; [; L4 m- V, t% a - mid = len(arr) // 20 g3 \9 {8 _; Q+ B7 f0 B
- left_half = arr[:mid]0 b\" V6 B% i8 i9 N
- right_half = arr[mid:]; N: c' G5 @1 j# _: T
- 5 u( V3 h7 f) z
- # 对左右两部分分别递归调用归并排序$ l& x9 t) d3 E, L
- left_half = merge_sort(left_half)
& R\" v S& K2 h: x; m( [3 i& y - right_half = merge_sort(right_half)
\" M\" C: Y! s9 R9 {2 h; Q -
0 R$ g! X. G1 k8 E0 j: ?' J- x% k - # 合并左右两部分, G/ [- `8 `5 I( X
- return merge(left_half, right_half)\" {& N) B5 \9 p/ X' r
- % Q\" G. U e( E) R' p/ e7 s* J V
- def merge(left_half, right_half):; @4 B# Q' h1 {' z* B9 ]
- i = j = 0
. X2 p& K I- S' Y7 e1 [8 C. S: o - merged = []
1 O. l) E2 V' P- ^- l\" X -
$ c' g3 t; g* r/ ~, | - # 比较左右两部分的元素,将较小的元素添加到 merged 中 k& a5 h; s' k! m
- while i < len(left_half) and j < len(right_half):
$ X2 T+ g5 x5 U4 J4 D8 ^: { - if left_half[i] < right_half[j]:
3 L8 T# B9 _3 N - merged.append(left_half[i])& k% G. Y$ } ]+ l
- i += 1, X) a4 Q! f9 G5 Q. W6 Y0 W- W: H3 b
- else:
# S/ ~; q- D, \, N( ]; {/ r; B: p - merged.append(right_half[j])
& _) M9 L' t* j8 u- e ?/ x% Q - j += 1
4 ]8 g3 I3 D/ t: K -
0 x! h3 Z$ I% l - # 将左右两部分中剩余的元素添加到 merged 中
* ]% Y4 [: f8 D9 s+ ?- p# l - merged += left_half[i:]
' [- z) b, a! t3 S - merged += right_half[j:]
* V\" j7 j0 s( U5 K: g\" D k% k -
2 S. r. B- u. p4 i1 P% s) J\" Z - return merged
复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解: merge_sort() 函数- def merge_sort(arr):
O' b* Z5 j( ~( i: c _ - if len(arr) <= 1:
1 H& @2 a6 e7 @9 ]$ G\" n - return arr
, d- v% W0 H4 I) c1 y+ ~ - ( ?/ {1 i$ T, A! {- O9 _9 O; q
- # 将数组分成两个部分% @( [5 C. T, q; p; g
- mid = len(arr) // 29 \: J# t* K7 m. f5 ?
- left_half = arr[:mid]) F4 [$ M2 ~7 P6 n# F
- right_half = arr[mid:]
# P7 p# @: }! |% }) i -
9 g; r2 `. Y* _- L6 ~7 q* H - # 对左右两部分分别递归调用归并排序) a+ |* @+ i7 m, Z B
- left_half = merge_sort(left_half) K( p$ t9 A; a6 E1 r/ S5 H+ H7 V5 x; c
- right_half = merge_sort(right_half)
9 W0 h9 o' T: ]7 I- O9 ^' q - - p2 b1 i7 d) e5 K+ d\" I1 r/ I5 o
- # 合并左右两部分( d8 U3 O+ R) Q q- N7 y
- return merge(left_half, right_half)
0 s( W. V& @4 o! \% T4 g - ```
! t/ U( J. m) I9 b% Q\" N - . Z# x# S# P8 z6 U0 m
- 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。5 d7 @& ?! L/ p& D0 o
-
复制代码 merge() 函数- def merge(left_half, right_half):
* U; g! B! J3 V( s - i = j = 0' ]- B0 z7 D* h
- merged = []
' P0 g/ e, `, |' ^6 s - 0 H$ G6 D# c7 z8 }9 D
- # 比较左右两部分的元素,将较小的元素添加到 merged 中
' X5 H( K+ K2 e) ~8 l - while i < len(left_half) and j < len(right_half):) G( Y2 ?! b5 W/ u' p) m
- if left_half[i] < right_half[j]:! ^8 F: I+ @5 }( K; S7 o8 L
- merged.append(left_half[i])
T* r4 o& w6 B - i += 1
( k1 T7 G' h! v% L, j - else:5 \ d) u' P2 J3 ~! m+ }\" s
- merged.append(right_half[j])
9 ]4 {$ |% @1 ~4 d - j += 1
/ m9 A; ^) i$ Z5 ` -
8 O# y% j) b$ L/ A' N4 ^ - # 将左右两部分中剩余的元素添加到 merged 中
) ]0 B) ? E) \& l - merged += left_half[i:]
6 {9 d: y V$ ^: s/ D0 @ - merged += right_half[j:]; q* N6 r3 o\" L* w
-
6 |2 d8 a8 t# i - return merged
2 n3 V' K0 t- r0 i4 T- K - ```5 [6 \% i5 N/ r9 D9 b
- . x, Y7 o, N M. k! R1 n9 U) Q
- 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。
复制代码 在实现归并排序时,需要注意以下几点:: E& ?1 P1 p, p0 z$ e
3 X8 Y' M. b. ?
判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。! s6 C7 u- {$ g) N0 b3 u
: f& f7 y9 D1 M
将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。
. W6 T( S; \5 w. ]6 G
. ~( N( v2 b' J2 z, ~8 F对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。
3 U, X5 U9 `, }
; F7 q* H* ~2 D$ g, W合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。
& b0 @8 p) }( o* \( e$ M
9 v( U/ z5 P: n) c测试 " R# v# z3 {! I0 ?8 C9 [
在使用上述代码实现归并排序时,可以通过以下代码测试:- arr = [3, 5, 1, 9, 7, 2, 8, 4, 6] P7 y+ Z& d. _* b8 q2 @
- print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
_' ?+ a: p& _3 ]: r* d3 ^) q! M1 {0 u" ]+ ^. F! E2 j# r! _2 @
总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。
* k! [" o) o8 P5 m, k2.2Java实现以下是使用 Java 实现归并排序的代码:
- public class MergeSort {
# D6 d/ k# q7 _, h @% J - public static void main(String[] args) {& F+ I( @/ M% I# h% Z1 Z
- int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};1 T' b/ k: e- D3 M& }# [
- mergeSort(arr, 0, arr.length - 1);) y4 w, p8 n\" q! ?4 v
- System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]! k9 S8 [3 Y6 @
- }' U8 n3 r5 A6 W6 r x
-
% u( h# }6 W# {6 i8 u - public static void mergeSort(int[] arr, int left, int right) {
, A6 Y2 c9 r# d9 \8 |. S- w - if (left >= right) {/ F5 w0 s, S+ t' c\" q; W
- return;3 Q& z, |+ q6 c! t
- }
) z- a: r& C# Y; ~ -
: K ^0 z& b6 b* Q8 m/ j - int mid = (left + right) / 2;
0 `: t* I2 m% r$ W - mergeSort(arr, left, mid);
- ]8 ~% i9 R) j/ i - mergeSort(arr, mid + 1, right);
6 r, D& J; o$ ], w4 g& P% K. B - merge(arr, left, mid, right);
6 R, b' C2 p$ q: f. I9 ]$ S0 `# j - }' u, l8 T9 |7 ?) I; p2 N* E, I
- ' L! P$ u4 k R7 z' w
- public static void merge(int[] arr, int left, int mid, int right) {8 ?\" x! r+ P. J& P( G. s8 p
- int[] temp = new int[right - left + 1];$ c9 N0 L\" _' z* [
- int i = left, j = mid + 1, k = 0;
8 G' h ?7 J# x* j, H+ g3 X- ] - 0 Q6 v) G- R( k# S3 D. {3 z
- while (i <= mid && j <= right) {2 W. d' ~ Q3 d' H9 [8 u
- if (arr[i] < arr[j]) {* S% `# x$ M* l0 B
- temp[k++] = arr[i++];
2 b# J+ B8 a6 P/ q! ~6 F - } else {
- ~6 b# P; S5 d: s( d - temp[k++] = arr[j++];
) V4 g% S c6 E\" h) O) A\" [: W - }
( I- V4 |+ I2 i2 F% S- q - }
2 N# O) H, g6 A' w -
# j/ j: E z2 y7 }3 O% I3 l- X - while (i <= mid) {
+ q- r! L% R% r( [8 }! K# I - temp[k++] = arr[i++];: H& l2 y\" h# f
- }
1 L\" [, x4 z7 d1 l/ K5 q -
$ \! M6 ~8 }0 x9 a( Z1 W - while (j <= right) {8 G# u: [- @) i* T) e3 M
- temp[k++] = arr[j++];* ~+ T: {) m* V( y0 S( c
- }, [: u4 k0 T1 T$ O- m' O0 }
-
3 B5 Z& l1 P5 D, z\" h+ q( ` - for (int m = 0; m < temp.length; m++) {
3 h& w' I4 M3 A; [! w( ^+ p - arr[left + m] = temp[m];* |; h* w$ Y8 o D
- }; I* E+ N4 g8 B- y: S\" E0 q
- }
1 v+ m+ A M; ]- b2 c v - }
复制代码这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。 下面对这两个函数进行详细讲解: B4 Y! U) P# `+ `% Y
mergeSort() 函数- public static void mergeSort(int[] arr, int left, int right) {8 u0 K3 y0 V6 f* P\" T
- if (left >= right) {# S6 [+ T9 @/ B\" C( a2 v3 }( a+ }
- return;( [( [3 p# h- T\" I5 U% a9 |
- }2 s6 q\" Y2 b m3 ]' P
- 5 s; U6 k9 s8 g, v% K
- int mid = (left + right) / 2;7 i. s+ M! Y8 L/ O* z/ q
- mergeSort(arr, left, mid);5 }, p- g1 T4 Z
- mergeSort(arr, mid + 1, right);) W& s# c( y/ l( h. D9 q( R
- merge(arr, left, mid, right);; ]: l1 }8 \4 H# E) P
- }: j: J' J( g* r2 v2 b+ d; Z
- / @( U0 B! F. [
-
复制代码 这个函数使用递归的方式对数组进行排序。
! e: X% D" k8 y5 K! R' O" D) e; v: G' l8 p* z# H! B
对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。
' T7 p. y3 f! |( |" I
( p( i3 Z9 ]$ C最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
! M9 M, t& h- V9 `merge() 函数- public static void merge(int[] arr, int left, int mid, int right) {. p& l1 s2 w% u! A- H! K
- int[] temp = new int[right - left + 1];, c! C v8 o6 x# L0 G3 X4 k
- int i = left, j = mid + 1, k = 0;
: r/ X; a8 d* Y2 E( e( }\" X - * O2 Z! a1 s( ~1 u, I
- while (i <= mid && j <= right) {* K# M! O9 Y L/ R( E6 R, {7 w$ n
- if (arr[i] < arr[j]) {
$ Y/ b+ y4 V! c - temp[k++] = arr[i++];; u2 X* H0 P( w S
- } else {
2 a2 ?0 ~& H: C: m0 |, [7 r- Z9 t - temp[k++] = arr[j++];
) b( Z) |6 _\" R. D! k - }
! _. {. f5 Z# s# m* y% q, ]5 C - }
# F! N6 O/ e, [' c -
. s6 Y7 f, J. K Q - while (i <= mid) {
! ?2 R9 X, j1 V3 W- h - temp[k++] = arr[i++];5 P2 V6 _9 p3 N
- }
: u7 A. D0 b- A9 b$ M; t, T2 a - 7 x# [# g9 T( X& k
- while (j <= right) {9 v. N0 [3 ~0 b! P) C8 K: B
- temp[k++] = arr[j++];# u6 j- C6 f5 {9 X& V
- }
7 p. q/ [6 Z) `: _# g - \" t1 ~& A: T! X
- for (int m = 0; m < temp.length; m++) {6 k& Y5 D/ b3 k2 O
- arr[left + m] = temp[m];4 J: { d. W; n2 W
- }2 Y7 J\" l/ _6 A$ u( z! \& t
- }
) I/ ?\" Q: `1 A -
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。
/ A& t4 k( _7 F& I+ j- j
* h: T$ o1 ?4 {. d2 B合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。
3 x. L' G; w6 g! y* {& a, J! J- N2 J8 e7 D. }8 z
最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。: _/ W4 J$ H c
7 ?+ `# V$ x& Y! Q
需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。
4 `7 V1 L& {0 h0 Y4 ]/ Q P$ ^% a- ]
! ?) i& \/ H, T2 Z: I" L3 X; I这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。/ V# I/ D( g$ S; o# m, c5 U" r
; W R! Y$ `7 @- g, n
3 n7 B% ^# t0 h+ l" l
9 Y) V% f+ V6 } ]- u; u9 w$ {: Z
, P* d3 z- j+ s5 b0 T7 F; ^
3 U: |( M+ Z1 Q; H
7 `' b, ^- Y; g3 Q% U' [4 z% h5 k$ H1 |
|
zan
|