JavaScript实现八大内部排序算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JavaScript实现⼋⼤内部排序算法
注:基数排序中:r是关键字的基数,d是长度,n是关键字的个数
1.插⼊排序
基本思想:在序号i之前的元素(0到i-1)已经排好序,本趟需要找到i对应的元素x (此时即arr[i]) 的正确位置k,在寻找位置k的过程中与序号i-1到0的元素依次进⾏⽐较。
如果x⼩于⽐较元素,则⽐较元素向后移动⼀位;否则,结束移位,将x插⼊当前位置k
1function insertSort(arr) {
2for (let i = 1; i < arr.length; i++) {
3// 将待插⼊元素提取出来
4 let temp = arr[i]
5 let j
6for (j = i - 1; j >= 0; j--) {
7if (arr[j] > temp) {
8// 插⼊元素⼩于⽐较元素,⽐较元素则向后移动⼀位
9 arr[j + 1] = arr[j]
10 } else {
11// 否则,结束移位
12break
13 }
14 }
15//将插⼊元素插⼊正确位置
16 arr[j + 1] = temp
17 }
18return arr
19 }
20 console.log(insertSort([7, 3, 4, 5, 10, 7, 8, 2]))
1.1插⼊排序的优化:⼆分排序
与插⼊排序思想差不多,但是⼆分排序是在插⼊第i个元素时,对前⾯的0~i-1元素进⾏折半,先跟它们中间的元素进⾏⽐较。
如果⼩,那么对前半进⾏折半;如果打,那么对后半进⾏折半。
依次进⾏,直到left>right。
然后再把第i个元素前⼀位与⽬标位置之间的所有元素向后移动⼀位,再将⽬标元素放⼊正确位置上。
1function binarySort(arr) {
2for (let i = 0; i < arr.length; i++) {
3 let temp = arr[i]
4 let left = 0
5 let right = i - 1
6 let mid
7while (left <= right) {
8 mid = Math.floor((left + right) / 2)
9if (arr[mid] > temp) {
10 right = mid - 1
11 } else {
12 left = mid + 1
13 }
14 }
15for (let j = i - 1; j >= left; j--) {
16 arr[j + 1] = arr[j]
17 }
18if (left !== i) {
19 arr[left] = temp
20 }
21 }
22return arr
23 }
24 console.log(binarySort([7, 3, 4, 5, 10, 7, 8, 2]))
2.希尔排序
基本思想:先取⼀个⼩于n的整数d1作为第⼀个增量,把⽂件的全部记录分成d1个组。
所有距离为d1的倍数的记录放在同⼀个组中。
先在各组内进⾏直接插⼊排序;然后,取第⼆个增量d2<d1重复上述的分组和排序,直⾄所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同⼀组中进⾏直接插⼊排序为⽌。
1function shellSort(arr) {
2 let d = arr.length
3while (true) {
4 d = Math.floor(d / 2)
5for (let x = 0; x < d; x++) {
6for (let i = x + d; i < arr.length; i = i + d) {
7 let temp = arr[i]
8 let j
9for (j = i - d; j >= 0 && arr[j] > temp; j = j - d) {
10 arr[j + d] = arr[j]
11 }
12 arr[j + d] = temp
13 }
14 }
15if (d == 1) {
16break
17 }
18 }
19return arr
20 }
21 console.log(shellSort([7, 3, 4, 5, 10, 7, 8, 2]))
3.直接选择排序
基本思想:每次选择待排序的元素中最⼩的值,放置在序列的⾸位
1function directSelectSort(arr) {
2for (let i = 0; i < arr.length; i++) {
3 let min = arr[i]
4 let index = i
5for (let j = i + 1; j < arr.length; j++) {
6if (arr[j] < min) {
7// 找到最⼩值,并标注最⼩值索引,⽅便后续与元素arr[i]交换位置
8 min = arr[j]
9 index = j
10 }
11 }
12 arr[index] = arr[i]
13 arr[i] = min
14 }
15return arr
16 }
17 console.log(directSelectSort([7, 3, 4, 5, 10, 7, 8, 2]))
4.堆排序
堆排序利⽤了⼤根堆(或⼩根堆)堆顶记录的关键字最⼤(或最⼩)这⼀特征,使得在当前⽆序区中选取最⼤(或最⼩)关键字的记录变得
简单
⽤⼤根堆排序的基本思想
①先将初始⽂件R[1..n]建成⼀个⼤根堆,此堆为初始的⽆序区
②再将关键字最⼤的记录R[1](即堆顶)和⽆序区的最后⼀个记录R[n]交换,由此得到新的⽆序区R[1..n-1]和有序区R[n],且满⾜R[1..n-
1].keys≤R[n].key
③由于交换后新的根R[1]可能违反堆性质,故应将当前⽆序区R[1..n-1]调整为堆。
然后再次将R[1..n-1]中关键字最⼤的记录R[1]和该区间的最后⼀个记录R[n-1]交换,由此得到新的⽆序区R[1..n-2]和有序区R[n-1..n],且仍满⾜关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
……
直到⽆序区只有⼀个元素为⽌。
1 let len
2
3function buildMaxHeap(arr) {
4//建⽴⼤根堆
5 len = arr.length
6for (let i = Math.floor(len / 2); i >= 0; i--) {
7 heapify(arr, i)
8 }
9 }
10
11function heapify(arr, i) {
12//堆调整
13 let left = 2 * i + 1,
14 right = 2 * i + 2,
15 largest = i
16
17if (left < len && arr[left] > arr[largest]) {
18 largest = left
19 }
20
21if (right < len && arr[right] > arr[largest]) {
22 largest = right
23 }
24
25if (largest !== i) {
26// 解构赋值,交换变量
27 ;[arr[i], arr[largest]] = [arr[largest], arr[i]]
28 heapify(arr, largest)
29 }
30 }
31
32function heapSort(arr) {
33 buildMaxHeap(arr)
34
35for (let i = arr.length - 1; i > 0; i--) {
36 ;[arr[0], arr[i]] = [arr[i], arr[0]]
37 len--
38 heapify(arr, 0)
39 }
40return arr
41 }
42
43 console.log(heapSort([7, 3, 4, 5, 10, 7, 8, 2]))
5.冒泡排序
基本思想:每次⽐较两相邻的数,当发现它们的排序与排序要求相反时,就将它们互换。
这样⼩的数往下沉,⼤的数往上冒
1function bubbleSort(arr) {
2for (let i = 0; i < arr.length; i++) {
3// 因为每次⽐较时都已经有i个元素沉下去了,所以j<arr.length-1-i
4for (let j = 0; j < arr.length - 1 - i; j++) {
5if (arr[j] > arr[j + 1]) {
6// 这⾥采⽤了解构赋值。
如果⼀般做法,借助临时变量,则辅助空间是O(1)
7 ;[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
8 }
9 }
10 }
11return arr
12 }
13 console.log(bubbleSort([7, 3, 4, 5, 10, 7, 8, 2]))
6.快速排序
基本思想:选择⼀个基准元素(通常选择第⼀个元素),通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的所有元素都⽐基准元素⼩,另外⼀部分的所有元素⼤于或等于基准元素⼤。
同样⽅法依次分割;整个排序过程可以递归进⾏。
1 let quicksort = function(arr) {
2if(arr.length <= 1) return arr;
3
4 let pivot = Math.floor((arr.length -1)/2);
5 let val = arr[pivot], less = [], more = [];
6
7 arr.splice(pivot, 1);
8 arr.forEach(function(e,i,a){
9 e < val ? less.push(e) : more.push(e);
10 });
11
12return (quicksort(less)).concat([val],quicksort(more))
13 }
14 console.log(quicksort([7, 3, 4, 5, 10, 7, 8, 2]))
7.归并排序
基本思想:将待排序序列分为若⼲个⼦序列,每个⼦序列是有序的,然后将有序⼦序列合并为整体有序序列。
1function merge(left, right) {
2 let result = []
3while (left.length > 0 && right.length > 0) {
4if (left[0] < right[0]) {
5/*shift()⽅法⽤于把数组的第⼀个元素从其中删除,并返回第⼀个元素的值。
*/
6 result.push(left.shift())
7 } else {
8 result.push(right.shift())
9 }
10 }
11return result.concat(left).concat(right)
12 }
13function mergeSort(arr) {
14if (arr.length == 1) {
15return arr
16 }
17 let middle = Math.floor(arr.length / 2),
18 left = arr.slice(0, middle),
19 right = arr.slice(middle)
20return merge(mergeSort(left), mergeSort(right))
21 }
22 console.log(mergeSort([7, 3, 4, 5, 10, 7, 8, 2]))
8.基数排序
基本思想:将所有待⽐较元素(正整数)统⼀为同样的数位长度,数位较短的数前⾯补零。
然后,从个位开始,进⾏排序;然后⼗位,进⾏排序;以此进⾏!这样从最低位排序⼀直到最⾼位排序完成以后,数列就变成⼀个有序序列。
基数排序两种⽅法:
MSD 从⾼位开始进⾏排序
LSD 从低位开始进⾏排序
1// LSD Radix Sort
2// helper function to get the last nth digit of a number
3var getDigit = function(num,nth){
4// get last nth digit of a number
5var ret = 0;
6while(nth--){
7 ret = num % 10
8 num = Math.floor((num - ret) / 10)
9 }
10return ret
11 }
12
13// radixSort
14function radixSort(arr){
15var max = Math.floor(Math.log10(Math.max.apply(Math,arr))), 16// get the length of digits of the max value in this array
17 digitBuckets = [],
18 idx = 0;
19
20for(var i = 0;i<max+1;i++){
21
22// rebuild the digit buckets according to this digit
23 digitBuckets = []
24for(var j = 0;j<arr.length;j++){
25var digit = getDigit(arr[j],i+1);
26
27 digitBuckets[digit] = digitBuckets[digit] || [];
28 digitBuckets[digit].push(arr[j]);
29 }
30
31// rebuild the arr according to this digit
32 idx = 0
33for(var t = 0; t< digitBuckets.length;t++){
34if(digitBuckets[t] && digitBuckets[t].length > 0){
35for(j = 0;j<digitBuckets[t].length;j++){
36 arr[idx++] = digitBuckets[t][j];
37 }
38 }
39 }
40 }
41return arr
42 }
43 console.log(radixSort([7, 3, 4, 5, 10, 7, 8, 2]))
注:⽹上有很多javascript实现的基数排序代码时错误的
当搜索⼀些问题时,尽量使⽤英⽂进⾏搜索!。