Skip to content

Commit 65d6779

Browse files
sort
1 parent 39d6a23 commit 65d6779

File tree

3 files changed

+111
-1
lines changed

3 files changed

+111
-1
lines changed

Note/sort/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const bubbleSort = require('./bubbleSort.js');
22
const selectSort = require('./selectSort.js');
33
const insertSort = require('./insertSort.js');
44
const quickSort = require('./quickSort.js');
5+
const mergeSort = require('./mergeSort.js');
56

67

78
function randomNums(len=1, min=0, max=1) {
@@ -17,3 +18,4 @@ console.log(bubbleSort([...nums]));
1718
console.log(selectSort([...nums]));
1819
console.log(insertSort([...nums]));
1920
console.log(quickSort([...nums]));
21+
console.log(mergeSort([...nums]));

Note/sort/mergeSort.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
function mergeSort(nums) {
2+
3+
if (!nums || nums.length <= 1) return nums;
4+
// 治, 有序合并数组
5+
function merge(left1, right1, left2, right2) {
6+
// 定义临时数组, 存放合并后的结果
7+
const tmpArray = [];
8+
// 定义两个游标, 分别从区间取值
9+
let i = left1;
10+
let j = left2;
11+
12+
// 合并有序数组
13+
while(i<=right1 && j <= right2) {
14+
// 遍历两个有序区间内的元素, 哪个小, 将哪个放在临时数组中, 同时移动该区间内的游标, 继续判断, 直至一方或双方同时完成
15+
tmpArray.push(nums[i] < nums[j] ? nums[i++] : nums[j++]);
16+
}
17+
// 若合并后有区间有元素残留
18+
while(i <= right1) {
19+
tmpArray.push(nums[i++]);
20+
}
21+
while(j <= right2) {
22+
tmpArray.push(nums[j++]);
23+
}
24+
25+
// 将数组中的数据, 填充至原数组中
26+
for(let i=0; i<tmpArray.length; i++) {
27+
nums[left1+i] = tmpArray[i];
28+
}
29+
}
30+
// 分, 递归拆分数组,
31+
function recursive(nums, left, right) {
32+
if (left>=right) return;
33+
const mid = Math.floor((right-left)/2+left);
34+
recursive(nums, left, mid);
35+
recursive(nums, mid+1,right);
36+
merge(left, mid, mid+1, right);
37+
}
38+
39+
recursive(nums, 0, nums.length-1);
40+
return nums;
41+
}
42+
43+
44+
module.exports = mergeSort;
45+
46+
47+
48+
49+

Note/sort/sort.md

+60-1
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,68 @@
140140
```
141141
* 代码分析
142142
* 空间复杂度: 未使用额外空间,空间复杂度 O(1)
143-
*
143+
* 时间复杂度:
144+
* 最好:元素均匀分享,此时相当于不断二分数组,O(n*logn)
145+
* 最坏:所有元素均处于基数另一侧,此时相当于插入排序,O(n<sup>2</sup>)
146+
* 平均:O(n*logn)
144147

145148
#### 归并排序
149+
* 基本思想
150+
* 递归拆分数组,直至拆分到每个区间仅有单个元素
151+
* 此时可认为每个区间均有序
152+
* 再有序合并拆分后的区间内元素(合并有序数组)
153+
* 将合并后的数组,重置到源数组中
154+
* 代码示例
155+
156+
```js
157+
function mergeSort(nums) {
158+
159+
if (!nums || nums.length <= 1) return nums;
160+
// 治, 有序合并数组
161+
function merge(left1, right1, left2, right2) {
162+
// 定义临时数组, 存放合并后的结果
163+
const tmpArray = [];
164+
// 定义两个游标, 分别从区间取值
165+
let i = left1;
166+
let j = left2;
167+
168+
// 合并有序数组
169+
while(i<=right1 && j <= right2) {
170+
// 遍历两个有序区间内的元素, 哪个小, 将哪个放在临时数组中, 同时移动该区间内的游标, 继续判断, 直至一方或双方同时完成
171+
tmpArray.push(nums[i] < nums[j] ? nums[i++] : nums[j++]);
172+
}
173+
// 若合并后有区间有元素残留
174+
while(i <= right1) {
175+
tmpArray.push(nums[i++]);
176+
}
177+
while(j <= right2) {
178+
tmpArray.push(nums[j++]);
179+
}
180+
181+
// 将数组中的数据, 填充至原数组中
182+
for(let i=0; i<tmpArray.length; i++) {
183+
nums[left1+i] = tmpArray[i];
184+
}
185+
}
186+
// 分, 递归拆分数组,
187+
function recursive(nums, left, right) {
188+
if (left>=right) return;
189+
const mid = Math.floor((right-left)/2+left);
190+
recursive(nums, left, mid);
191+
recursive(nums, mid+1,right);
192+
merge(left, mid, mid+1, right);
193+
}
194+
195+
recursive(nums, 0, nums.length-1);
196+
return nums;
197+
}
198+
199+
```
200+
* 代码分析
201+
* 空间复复杂度:需要与原数组相同的控件大小作为临时存储,故 O(n)
202+
* 时间复杂度
203+
* 不管最好最坏,归并排序均为二分至底,然后有序合并,所以其时间复杂度为 O(n * log n)
204+
* 注意:归并排序本质上不是数组原地排序,而是将排序结果中的数据存至另一个数组中去了,本示例代码中,将排序结果赋值到待排序数组中,才使得原数组被改变。
146205

147206
#### 计数排序
148207

0 commit comments

Comments
 (0)