- 在线时间
- 478 小时
- 最后登录
- 2026-4-9
- 注册时间
- 2023-7-11
- 听众数
- 4
- 收听数
- 0
- 能力
- 0 分
- 体力
- 7788 点
- 威望
- 0 点
- 阅读权限
- 255
- 积分
- 2922
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1171
- 主题
- 1186
- 精华
- 0
- 分享
- 0
- 好友
- 1
该用户从未签到
 |
1 基础介绍
0 j9 O2 g0 s+ @ O) U$ h排序算法是很常见的一类问题,主要是将一组数据按照某种规则进行排序。6 T1 W! w9 Y" o7 r2 ~! T+ L
% c- r; E' g' L& |以下是一些常见的排序算法:6 G4 C& I0 }- a, q
# T! Q* G4 L6 |) A. Y m冒泡排序(Bubble Sort)
: N3 r' h3 M ~& G' b0 X6 ~) o
9 V7 b5 b3 A9 E$ n+ z插入排序(Insertion Sort)
) K9 _: [6 {. `! P. F: l7 D5 n/ y8 G
选择排序(Selection Sort)
$ r. {/ j5 ]" L9 O. X1 m% e9 z4 p8 q& W3 S6 p( q5 @- w4 W
归并排序(Merge Sort)
: t) l( h6 N' D2 a. r6 p1 _ O# U
7 g/ E$ M3 q+ t) a$ O: }快速排序(Quick Sort)
; d! m; G, p) j1 o& _7 e8 N
8 e8 O' d9 v9 i$ ?, R2 q堆排序(Heap Sort); K& v5 ~0 F/ t% G3 v2 O% X9 D* Y
' {$ Z& c9 X# r, c
一、基本介绍介绍
' g- m I: [! V, i+ j1.1 原理介绍- X4 J# C& @& a7 h/ J6 |5 {+ b9 |6 ^
归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。; c' S8 ?/ J& @
f2 D" C! O5 r" j# Y归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:/ ]# w& M$ F: a/ [0 `- G
3 r5 N1 D6 {4 z' x5 k
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。( A; L' ]' E t+ l
0 ]1 w! h* o5 R$ q. D3 j2 r: Q
合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。. q8 ~) ?+ t2 x" ]
! J W& [* U2 }. H9 r# f
合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:' `7 F! H1 D& F% D7 z
& m$ ~/ k l5 Z0 c5 k
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。& i! L( K q, Y
+ Q% v; X) S: T: \ |9 y比较 A 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。
1 u5 A9 Z$ }8 u2 e' s* s* s# V5 V9 y5 g% y
重复步骤 2,直到其中一个数组的元素全部放入 C 中。7 Z" t6 \/ R0 Y- [- n
$ ^* D% T- U2 p- C- ?
将另一个数组中剩余的元素放入 C 中。
# N/ k2 g3 i% k$ x: w
# O- j6 {6 I; s归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。
7 E+ d$ K# e; u6 {1 U) a) I: M
! J, k4 V5 X6 [0 u2 p* b6 S( j原理简单示例 ' D9 w" e; S' `& O9 B* a
以下是一个示例,演示了如何使用归并排序对一个数组进行排序:3 ^- r+ B2 E6 F* Q
. P/ J" N" R' u' N" T% g m" K假设要对数组 [5, 2, 4, 6, 1, 3] 进行排序。
5 J% h; v7 z! _' N" p
y- r/ d7 F8 @7 X首先将数组分成两部分:[5, 2, 4] 和 [6, 1, 3]。7 A5 L+ ? b3 |8 I
9 d/ J1 A; T" C
对左右两部分分别递归调用归并排序。对于左半部分,继续进行分解,将其分成两部分:[5] 和 [2, 4]。对于右半部分,也进行相同的操作,将其分成两部分:[6] 和 [1, 3]。, y/ q- D# R) `7 }+ u, k: l7 z
0 j9 W- [$ U0 J) }) K& Z6 J, t4 u对于 [5] 和 [2, 4],由于它们的长度都小于等于 1,因此直接返回它们本身。对于 [6] 和 [1, 3],同样返回它们本身。, m) ^% j9 l' U6 ^, D0 k
- }% R; u1 S9 l( I
接下来将排好序的左右两部分合并成一个有序数组。对于左半部分,由于它只有一个元素,因此可以直接将其作为有序数组。对于右半部分,需要将 [1, 3] 进行排序,排序后得到 [1, 3, 6]。
" U/ @ [1 W) c5 q2 m. m4 B$ X% O" K2 C( g, w
将排好序的左右两部分合并成一个有序数组。对于左半部分,指针 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]。
p. D2 R* b; J+ W0 x% U, w. B4 N
2 J, r% `* g' k- i6 C因此,对于输入的数组 [5, 2, 4, 6, 1, 3],使用归并排序后得到的排好序的数组为 [1, 2, 3, 4, 5, 6]。
; i4 {$ a3 h3 n4 q$ E9 `
6 v) f# K% g$ P* R E7 L+ P1.2 复杂度 / C& a0 k4 v+ H8 B: y
归并排序的时间复杂度为 O(nlogn),其中 n 是待排序数组的长度。1 G& {! \3 {7 `
" U8 F) \' J: p1 ?- u5 r3 N5 z4 q2 f这个复杂度可以通过分治的思想来解释。; J {: a2 T( U& ?) z
9 {5 a" u, V+ M: l& I7 u$ w* X$ @
首先将待排序的数组分成两部分,对每一部分递归调用归并排序,然后将两部分合并成一个有序数组。& e1 K" Q0 r1 U8 }
. h0 u/ a5 z! T, j" [- f0 | ?
每次递归调用都将数组的长度减半,因此需要进行 logn 次递归调用。在每个递归层次中,需要将两个有序数组合并成一个有序数组,这一过程需要线性时间 O(n)。因此,归并排序的总时间复杂度为 O(nlogn)。8 W) X/ s( G0 E6 E5 d
+ H6 d8 f) k) W归并排序的空间复杂度为 O(n),其中 n 是待排序数组的长度。在排序过程中,需要使用一个辅助数组来存储合并后的有序数组。) h& _# w# \& l. [7 x) z
! D- I: q# C. @+ O! {8 |这个辅助数组的长度等于待排序数组的长度,因此归并排序的空间复杂度为 O(n)。如果实现中使用链表来存储数据,空间复杂度可以降低为 O(1)。! O* r A: l* p r [/ N) k" n
& L( D% S4 ?& K, b1.3使用场景
( y0 U# L7 K; r: B) B3 a# q& s$ k归并排序的应用场景比较广泛,主要适用于以下几种情况:' `1 X, B& a3 f* E% n. w
3 I' r8 ? F7 @3 U5 Z3 d- P
对于大规模的数据排序:归并排序的时间复杂度为 O(nlogn),相比于其他排序算法如冒泡排序、插入排序等,它在处理大规模数据时更加高效。
5 H; {( _. c" b2 P# P/ r6 c
5 t1 h* c' y% B0 S对于稳定排序的需求:归并排序是一种稳定排序算法,即对于相等的元素,在排序前后它们的相对位置不会改变。
3 Z( Q7 q* w' D& l; S) I, W2 }) |& v+ j
对于需要保证排序稳定性的需求:归并排序是一种基于比较的排序算法,不依赖于数据的初始状态,具有较好的稳定性。
3 h( S5 N1 w% y+ g
& l0 X1 L1 r4 G( ^& {8 d) T! d对于需要多路排序的需求:归并排序可以轻松地扩展到多路排序,即将待排序的数组分成多个子数组,对每个子数组分别进行归并排序,然后将它们合并成一个有序数组。2 ^) V5 S5 Y: _: q/ r4 u
+ O* M+ } \( r" `7 N
对于需要外部排序的需求:归并排序可以应用于外部排序,即在排序过程中将数据存储在外部存储器中,而不是在内存中。在外部排序中,需要使用多路归并排序来合并不同的子文件。
& T! q- w5 L1 u3 E
: R6 W. Z( ^0 _ ?& c ^% a$ c总的来说,归并排序是一种高效、稳定的排序算法,适用于大规模数据的排序、需要保证排序稳定性的需求以及外部排序等场景。
( ]) N- J8 c- O8 }/ f! U; ]* m v! f/ }! ^4 f* P
二、代码实现) f) @3 q: a- c
2.1 Python 实现( z! Y9 t k! I" C8 p/ g& C( F
以下是使用 Python 实现归并排序的完整代码:- def merge_sort(arr):5 `- I) W0 o\" t3 d/ ~4 U$ Q
- if len(arr) <= 1:6 e& S# g7 m& Y2 U7 c) `; v0 h) J
- return arr
6 y4 {6 N& @/ L - + d9 r* P! i5 |\" V- q\" P/ }
- # 将数组分成两个部分, k\" ~% |% v5 A2 d8 ^
- mid = len(arr) // 2) d1 G1 r! O! n8 {% q. w
- left_half = arr[:mid]
8 {6 N. N0 U$ r# O5 J- S, t4 Y' d - right_half = arr[mid:]
5 i, S: q# Z4 Q# C* }# i/ C -
% |4 `+ Y) q# y/ n) V1 ~5 E) r - # 对左右两部分分别递归调用归并排序
0 B+ P\" F+ h' k, [) ~ - left_half = merge_sort(left_half)
1 \( ?$ x5 x' ]( ?9 f - right_half = merge_sort(right_half)8 \* P2 l$ N3 [
-
# N0 y) r/ `9 ^* v- ~7 Z* s - # 合并左右两部分2 B8 u6 |7 U9 r& G/ x& x
- return merge(left_half, right_half)\" F: l; H7 ~7 g( X) I2 b
-
3 {9 x, z4 {$ N# V9 A - def merge(left_half, right_half):
/ F0 ^) z8 V* l1 w- m\" z' \4 h# Z - i = j = 0
7 W$ C8 @6 p6 Z - merged = []
* U5 D0 X5 s( ~0 E7 C - # S) h# d7 C; q\" g' t g
- # 比较左右两部分的元素,将较小的元素添加到 merged 中. I0 A\" B3 U9 P7 g, w0 j
- while i < len(left_half) and j < len(right_half):/ Y$ Q( g+ K0 X$ p; u! s+ p9 @
- if left_half[i] < right_half[j]: j\" Y9 D, r$ i$ D. d* F a4 [
- merged.append(left_half[i]) g' C/ A( m8 v8 o
- i += 1
5 E/ G L, O) F6 a g& z\" L0 |: | - else:
! y; _4 I/ C+ @* }) L! ]6 {% h - merged.append(right_half[j])# [3 a. A6 H- h' L2 g: | f4 Q8 a
- j += 1
0 w0 i9 D7 x# p. W- T$ S$ U. j -
7 V9 `( ?& W b - # 将左右两部分中剩余的元素添加到 merged 中
! R7 j- F\" ]\" }5 v! y7 r - merged += left_half[i:]
2 H# w# n; _( t9 Z& j - merged += right_half[j:]3 c' H! b\" y- T P9 T
-
5 |% e7 D0 u6 D; A$ F3 M* W - return merged
复制代码 代码讲解 这个实现使用了两个函数,一个是 merge_sort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。下面对这两个函数进行详细讲解: merge_sort() 函数- def merge_sort(arr):
2 [5 s3 Y: ?4 c+ \+ l6 I% w - if len(arr) <= 1:' c7 V+ B6 R7 x\" L) X\" u\" R
- return arr' `5 K5 n: h' s. \
-
& ?' b$ {$ Z! U# R - # 将数组分成两个部分$ r' l1 i& \2 P) y$ Z, t V( a
- mid = len(arr) // 2& b& W: R- N v6 w4 n, C2 E
- left_half = arr[:mid]
$ s& W& w6 z- E - right_half = arr[mid:]
* r; R6 |. Z3 {( u( t- X9 m -
: V. J$ D\" b' b4 }' A6 l0 B4 w - # 对左右两部分分别递归调用归并排序
' C; R- U+ v8 p) y! R0 v8 @ - left_half = merge_sort(left_half)
. b/ |) O# g0 |\" T T- U2 w - right_half = merge_sort(right_half)
3 N4 s: G4 s& a @$ d1 W' d# s! l -
+ z6 D\" q, G2 i4 D - # 合并左右两部分
& j, _) P$ ]/ f - return merge(left_half, right_half)
; \+ V2 }4 g7 ?5 ^ - ```4 j( f( H\" @9 s9 v$ i* a! H2 i
- 8 D% a2 `2 J/ k% t @
- 这个函数使用递归的方式对数组进行排序。对于输入的数组,首先判断其长度是否小于等于 1,如果是,则直接返回该数组。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `merge_sort()` 函数。最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `merge_sort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。9 A& o) P: r# Y! q( w9 K1 _
-
复制代码 merge() 函数- def merge(left_half, right_half):3 ?% j/ j2 k) L4 t! [# e9 r$ A% x\" F
- i = j = 0* V8 _& W\" O( V6 l
- merged = []
1 v c% ^ Q$ f8 \ -
/ r( }' F- |\" ^. M; @1 o' O - # 比较左右两部分的元素,将较小的元素添加到 merged 中
8 N\" W4 b) t6 j: @8 T3 d4 ] - while i < len(left_half) and j < len(right_half):% T\" h3 K1 i$ ^# ?
- if left_half[i] < right_half[j]:. Z) d\" U6 {% V9 U/ M- p! m
- merged.append(left_half[i])
+ {8 l. Q; |/ U2 P4 w3 W7 ] - i += 18 G. V E8 X9 q6 H, I$ |: {$ I
- else:
( m\" \1 g7 j# c: H - merged.append(right_half[j])' u; k3 ^5 e& c% A1 {9 J
- j += 12 z3 @# ] I* k. p
-
7 L3 c* u& `' _$ @ - # 将左右两部分中剩余的元素添加到 merged 中
3 U- [. R4 b A; o% h - merged += left_half[i:]
: V5 `$ \- {% P! p - merged += right_half[j:]
% d Z3 Q2 ] o: B+ K8 W -
6 @- N3 G. `0 P2 r$ i - return merged6 x% u N7 a# P! j9 i
- ```
$ P2 F& Z' M7 {% ?. ~0 H6 i! T: n6 M -
\" ` T1 _4 d' t/ [. L8 A - 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 merged 来存储合并后的结果。合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 merged 中。最后,将左右两部分中剩余的元素添加到 merged 中,最终返回 merged。
复制代码 在实现归并排序时,需要注意以下几点:* A2 y( ~. o& ]: ?
+ Z$ p& x3 W$ U1 Q
判断数组长度是否小于等于 1:这一步是递归调用的终止条件,防止出现无限递归的情况。( i+ @8 z8 O8 Y% t+ k6 b Q
1 _. m) e7 M, N
将数组分成两部分:需要使用 Python 的切片操作来实现,将数组分成左右两部分。
- C( Z4 N! L2 t+ T" b f1 e& D2 [" h' N
对左右两部分进行递归调用:将左右两部分作为参数传入 merge_sort() 函数并进行递归调用,直到数组长度小于等于 1。& I3 X. Z! p) l' N$ f2 u0 Y0 _5 T5 u/ c
( f# Y4 c1 C' u# v, E% F% G2 ~合并两个有序数组:使用 merge() 函数将排好序的左右两部分合并成一个有序数组。
' E! D. G6 R$ ^+ V" A$ @6 N' ]! T$ Q0 L
测试
0 ]; v) K) |6 X$ w" {2 @在使用上述代码实现归并排序时,可以通过以下代码测试:- arr = [3, 5, 1, 9, 7, 2, 8, 4, 6]6 i5 V5 R' b& N/ D( a3 F
- print(merge_sort(arr)) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码 这个例子中,将一个无序的数组作为输入,调用 merge_sort() 函数进行排序,并输出排好序的结果。
7 Q) \. U8 a% C" N0 v
7 i/ W# B2 F; A总的来说,这个实现是一种简单而清晰的归并排序实现方式,适合初学者学习和理解。虽然这个实现的时间复杂度为 O(nlogn),但其空间复杂度为 O(n),因为在合并过程中需要额外的空间来存储排好序的元素,因此在处理大规模数据时可能会占用较多的内存。) R& O8 a6 Q1 T5 |
2.2Java实现以下是使用 Java 实现归并排序的代码:
- public class MergeSort {! e9 L* U+ f) X\" O
- public static void main(String[] args) {
- x+ H# Z6 x$ x* S - int[] arr = {3, 5, 1, 9, 7, 2, 8, 4, 6};\" S\" R! N2 k2 I
- mergeSort(arr, 0, arr.length - 1);
5 w* C; r5 c8 S; L\" }& i' s* x2 M( { - System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
8 G* l7 ~% j( c) Y9 b$ L - }
& b. W( B5 Q; r; e m) F - ! E) B/ P; n/ c' ^/ d1 _$ a4 H% z) z
- public static void mergeSort(int[] arr, int left, int right) {4 M4 E$ E7 j5 w8 }* b' ?8 V
- if (left >= right) {\" r( Q5 \) L3 h& g2 F) }5 N( W
- return;
, E; @6 V$ |) M# }5 T8 Z: _& s - }
3 H. H+ k, q5 w# e- A& X, D8 S - * H& O0 l4 F7 `8 _( F& ~
- int mid = (left + right) / 2;& \0 S- L/ _9 d% N
- mergeSort(arr, left, mid);
/ U$ p7 k3 x: U' e+ Q4 ^ - mergeSort(arr, mid + 1, right);
& Y) f+ v4 M$ t! T1 W1 L+ C - merge(arr, left, mid, right);8 s, `* f( H( a! Z- ~
- }
7 p4 z+ d7 G1 B! ]! c - 9 k6 f o2 a n! i7 q
- public static void merge(int[] arr, int left, int mid, int right) {
0 C9 ?- P( Z8 j - int[] temp = new int[right - left + 1];
2 d- b* [* f* z' H) B; j5 H - int i = left, j = mid + 1, k = 0;/ c6 j: G5 w2 m
-
$ ?8 n$ s2 Q s; D, ]( m7 o - while (i <= mid && j <= right) {) l( p, l+ S\" @3 {
- if (arr[i] < arr[j]) {
\" g3 g; ~* ^ y. a) V - temp[k++] = arr[i++];
\" ~* u* x8 \/ y: w/ {# V! G# e - } else {
3 X ~\" N1 X4 Q. O - temp[k++] = arr[j++];. M$ t, [1 X* O( |% C% S
- }
! h& F5 H; m0 q: g- z. q+ a - }
6 t7 B8 m! N- q% y -
& B( N6 z/ n2 \) U - while (i <= mid) {5 U) X6 c# P( ]\" I, u j; {
- temp[k++] = arr[i++];
9 }: I5 v$ y6 z$ w! G. c - }# e. k, b& ^% E: U, Y\" x2 `
- ) t6 j2 A% @7 q2 ?
- while (j <= right) {! v4 [\" T( Z! L1 z5 {0 ~; ~
- temp[k++] = arr[j++];
5 E7 f. z% R5 }; c7 Y! U$ G1 K - }# j: H/ G9 Y; K7 r# `' X' k
-
: `. t* x2 ~2 Z% {9 {) T. j) J - for (int m = 0; m < temp.length; m++) {
! ~' @3 r, W2 j- p$ I+ i# l8 y\" g* X% V - arr[left + m] = temp[m];6 w# r3 C8 u+ K/ D- D4 ?
- }% x1 P# D+ X- m9 x; H: f( n
- }: t/ K A3 f/ p G
- }
复制代码这个实现也使用了两个函数,一个是 mergeSort() 函数,用于进行递归调用,另一个是 merge() 函数,用于合并两个有序数组。 下面对这两个函数进行详细讲解: + |- y" _+ V* ^6 a' m+ H- O. ]+ K
mergeSort() 函数- public static void mergeSort(int[] arr, int left, int right) {% ]1 v* k- s, p/ @# T' E% o# l' |
- if (left >= right) {, Q/ I\" S; c; J1 n\" F% U
- return;
& A7 o3 L( _* y$ R - }: O9 V7 [7 j/ r; _+ B
-
) ~( Q) R' L* Q- Y' u- U* c8 J% E - int mid = (left + right) / 2;$ y. y5 p, U2 Z+ _
- mergeSort(arr, left, mid);$ z) S5 t4 e' R\" }& X\" P2 ~
- mergeSort(arr, mid + 1, right);! A3 @# _9 v5 S5 p' @
- merge(arr, left, mid, right);8 ^, E/ |. L4 l) a7 k
- }
# u+ l6 a j' ?5 Y n4 I\" ^; \, B - * V% @. r3 |% d4 `
-
复制代码 这个函数使用递归的方式对数组进行排序。
% s F' ?0 G8 s8 A
5 l0 i- e3 k* Z' p/ S' w! C! [2 U对于输入的数组和左右下标,首先判断左下标是否大于等于右下标,如果是,则直接返回。否则,将数组分成两个部分,分别对左半部分和右半部分递归调用 `mergeSort()` 函数。
$ d$ k/ }. H, O8 Y7 l, e2 M5 T3 `0 M e/ X
最后,将排好序的左右两部分合并成一个有序数组,并将其作为结果返回。需要注意的是,此处的 `merge()` 函数是在 `mergeSort()` 函数中调用的,因为只有在递归到最底层时才会对单个元素进行排序,而在其他情况下需要将数组分成两部分进行递归调用。
6 ^4 c$ r, v# nmerge() 函数- public static void merge(int[] arr, int left, int mid, int right) {\" m( p9 N\" H9 ?9 l
- int[] temp = new int[right - left + 1];
% y3 d% S% N$ W% c7 T; Q% @ - int i = left, j = mid + 1, k = 0;
* z/ m3 g9 ~# a( Q& a - 8 l: F' v/ F8 Z7 ~' a
- while (i <= mid && j <= right) {' {' N. s9 N; Y7 h8 H' u
- if (arr[i] < arr[j]) {
/ t( Y\" l# V# u+ I\" y* o) V7 | - temp[k++] = arr[i++];3 X( Q6 n% r A4 {' o7 p* J# H
- } else {
$ L6 H [/ U) ]) D5 k - temp[k++] = arr[j++];
; t/ T6 i9 Q( e- e, y( d - }1 G) z* F7 R) t. j8 h
- }
6 k/ w# i. H6 j6 ?. R. G: k1 V# [ -
3 R7 L6 `. K. l2 F M - while (i <= mid) {# S6 V, C4 c* z+ N1 y
- temp[k++] = arr[i++];
- R$ `& n* H5 x\" e - }1 j( \* P a7 g# g' |0 d3 L, j3 }
-
: \- P( g+ y7 T. l. u$ M - while (j <= right) {3 q2 Z1 O4 ?( D- i( Z5 J. v. I7 Z
- temp[k++] = arr[j++];
$ s, O: ~9 A\" I( o9 [' r - }3 V5 A8 e' J) L& ?6 A
-
. K1 k7 d4 ?* t, n# I. d# G - for (int m = 0; m < temp.length; m++) {
/ j7 w% n$ M5 W/ Q- m - arr[left + m] = temp[m];
L, I: X) ]9 Y0 s\" b - }8 A$ V9 H' C2 }# |\" k
- }
# Y4 I- R4 s\" {, w\" r5 y -
复制代码 这个函数用于合并两个有序数组。在函数内部,使用两个指针 i 和 j 分别指向左右两部分的起始位置,以及一个新的数组 temp 来存储合并后的结果。
; D+ U; x* x+ R5 Z
9 i6 Q: ~3 Q( A, t' z% G' S9 V合并的过程中,不断比较左右两部分的元素大小,并将较小的元素加入 temp 中。
# u4 _& b$ e0 L% t8 M3 C0 G2 c( B3 B! x0 I% a. E" h
最后,将左右两部分中剩余的元素添加到 temp 中,最终将 temp 中的元素复制回原数组中。
' _$ D* g2 q+ W \; `/ |: a
2 R# I2 N" j6 Y; V需要注意的是,在复制回原数组时,需要计算出每个元素在原数组中的位置。* B% F+ L+ p4 e0 m
# f/ p# u$ ]& j" s" f这个归并排序的实现是比较基础的,但是足以演示归并排序的算法思想和实现过程。当然,实际应用中可能需要对代码进行一些优化,比如可以对小数组使用插入排序来提高效率,或者使用迭代的方式来避免递归调用带来的额外开销。& w; L. p* N" G/ w0 J5 ]
7 F* h% k; p b, x3 E! V6 ?
0 N! F) N- |% E: q. N/ B$ O4 s4 H: \" H6 B( y6 G5 _
" W* D$ g' o" u9 F3 c, {4 Q2 s& y7 P s: ]2 X/ B; w' E- L5 b% s7 l# o
2 w0 V5 _* q; F- l
+ w& A! ?' X3 K* Z3 v( i |
zan
|