一天两个,这周学完
我似乎不太能够写出分而治之 、递归 、二叉树 的实现,能够理解,但是写不出来。
归并排序(分而治之、递归)
快排(递归)
希尔排序(未知)(理解不了)
堆排序(二叉树,递归)(理解不了)
https://www.runoob.com/w3cnote/ten-sorting-algorithm.html
冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢”浮”到数列的顶端。
算法步骤:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 function bubbleSort (arr: number [] ) { let count = arr.length; while (count >= 0 ) { for (let i = 1 ; i < count; i++) { if (arr[i] < arr[i - 1 ]) { const temp = arr[i]; arr[i] = arr[i - 1 ]; arr[i - 1 ] = temp; } } count--; } return arr; } let arr = [];let i = 100 _000;while (i > 0 ) { arr.push(i); i--; } function bubbleSort2 (arr ) { var len = arr.length; for (var i = 0 ; i < len - 1 ; i++) { for (var j = 0 ; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1 ]) { var temp = arr[j + 1 ]; arr[j + 1 ] = arr[j]; arr[j] = temp; } } } return arr; } console .time("bubbleSort" );console .log(bubbleSort(arr)); console .timeEnd("bubbleSort" );console .time("bubbleSort2" );console .log(bubbleSort2(arr)); console .timeEnd("bubbleSort2" );
选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
算法步骤:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 function selectionSort (arr: number [] ) { let len = arr.length; for (let i = 0 ; i < len - 1 ; i++) { let min = arr[i]; let minI = i; for (let j = i + 1 ; j < len; j++) { if (arr[j] < min) { minI = j; min = arr[j]; } } arr[minI] = arr[i]; arr[i] = min; } return arr; } let arr = [];let i = 100 _000;while (i > 0 ) { arr.push(i); i--; } function selectionSort2 (arr ) { var len = arr.length; var minIndex, temp; for (var i = 0 ; i < len - 1 ; i++) { minIndex = i; for (var j = i + 1 ; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } return arr; } console .time("selectionSort" );console .log(selectionSort(arr)); console .timeEnd("selectionSort" );console .time("selectionSort2" );console .log(selectionSort2(arr)); console .timeEnd("selectionSort2" );
插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。
平均插入排序算法的时间复杂度为 O(n²)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小(eg:量级小于千),那么插入排序是一个不错的选择
算法步骤:
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素
与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function insertionSort (arr: number [] ) { let preI: number , current: number ; for (let i = 1 ; i < arr.length; i++) { current = arr[i]; preI = i - 1 ; while (preI >= 0 && arr[preI] > current) { arr[preI + 1 ] = arr[preI]; preI--; } arr[preI + 1 ] = current; } return arr; } let arr = [];let i = 10 ;while (i > 0 ) { arr.push(i); i--; } console .log(insertionSort(arr));
希尔排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function shellSort (arr: number [] ) { let len = arr.length, temp: number , gap = 1 ; while (gap < len / 3 ) { gap = gap * 3 + 1 ; } for (gap; gap > 0 ; gap = Math .floor(gap / 3 )) { for (let i = gap; i < len; i++) { temp = arr[i]; let j = i - gap; for (; j >= 0 && arr[j] > temp; j -= gap) { arr[j + gap] = arr[j]; } arr[j + gap] = temp; } } return arr; } console .log(shellSort([5 ,4 ,1 ,2 ,3 ,21 ,3 ,54 ,6 ,78 ,23 ,4 ,6 ,2 ,34 ,345 ,345 ,1 ,35 ,457 ,345 ,5 ,543 ,423 ,45 ,1 ,221 ,1 ,3 ,]))
归并排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function merge (left: number [], right: number [] ) { let res = []; while (left.length && right.length) { if (left[0 ] <= right[0 ]) { res.push(left.shift()); } else { res.push(right.shift()); } } while (left.length) { res.push(left.shift()); } while (right.length) { res.push(right.shift()); } return res; } function mergeSort (arr: number [] ) { let len = arr.length; if (len < 2 ) { return arr; } let middle = Math .floor(len / 2 ), left = arr.slice(0 , middle), right = arr.slice(middle); return merge(mergeSort(left), mergeSort(right)); }
快速排序 不行,我能够理解快排,但是完全没有办法实现快排 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function swap (arr: number [], i: number , j: number ) { let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } function partition (arr: number [], left: number , right: number ) { let pivot = left; let index = pivot + 1 ; for (let i = index; i <= right; i++) { if (arr[i] < arr[pivot]) { swap(arr, i, index); index++; } } swap(arr, pivot, index - 1 ); return index - 1 ; } function quickSort (arr: number [], left?: number , right?: number ) { let len = arr.length; let partitionIndex: number ; left = typeof left != "number" ? 0 : left; right = typeof right != "number" ? len - 1 : right; if (left < right) { partitionIndex = partition(arr, left, right); console .log(partitionIndex) quickSort(arr, left, partitionIndex - 1 ); quickSort(arr, partitionIndex + 1 , right); } return arr; } const arr = quickSort([5 , 4 , 1 , 2 , 3 ]);
堆排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 let len: number ; function swap (arr: number [], i: number , j: number ) { let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } function heapify (arr: number [], i: number ) { let left = 2 * i + 1 , right = 2 * i + 2 , largest = i; if (left < len && arr[left] > arr[largest]) { largest = left; } if (right < len && arr[right] > arr[largest]) { largest = right; } if (largest != i) { swap(arr, i, largest); heapify(arr, largest); } } function buildMaxHeap (arr: number [] ) { len = arr.length; for (let i = Math .floor(len / 2 ); i >= 0 ; i--) { heapify(arr, i); } } function heapSort (arr: number [] ) { buildMaxHeap(arr); for (let i = arr.length - 1 ; i > 0 ; i--) { swap(arr, 0 , i); len--; heapify(arr, 0 ); } return arr; }
计数排序 计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
算法步骤
找出待排序的数组中最大和最小的元素
统计数组中每个值为i的元素出现的次数,存入数组C的第i项
对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function countingSort (arr: number [] ) { let min = arr[0 ], max = arr[0 ]; for (let i = 0 ; i < arr.length; i++) { const num = arr[i]; if (num < min) { min = num; } else if (num > max) { max = num; } } const array = new Array (max - min + 1 ); for (let i = 0 ; i < arr.length; i++) { const num = arr[i]; array[num - min] = array[num - min] ? array[num - min] + 1 : 1 ; } arr = []; for (let i = 0 ; i < array.length; i++) { const num = array[i]; for (let j = 0 ; j < num; j++) { arr.push(i + min); } } return arr; } let arr = [];let i = 100 ;while (i > 0 ) { arr.push(i); i--; } console .time("countingSort" );console .log(countingSort(arr));console .timeEnd("countingSort" );
桶排序 桶排序是计数排序的升级版,计数排序适用于紧凑型的数据进行排序,当数据间隔大了之后就会出现空间浪费的问题。
它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:
在额外空间充足的情况下,尽量增大桶的数量
使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 function bucketSort (arr: number [], bucketSize = 5 ) { let min = arr[0 ]; let max = arr[0 ]; for (let i = 0 ; i < arr.length; i++) { const e = arr[i]; if (e < min) { min = e; } else if (e > max) { max = e; } } const bucketCount = Math .floor((max - min) / bucketSize) + 1 ; let buckets = new Array (bucketCount); for (let i = 0 ; i < buckets.length; i++) { buckets[i] = []; } for (let i = 0 ; i < arr.length; i++) { buckets[Math .floor((arr[i] - min) / bucketSize)].push(arr[i]); } arr.length = 0 ; for (let i = 0 ; i < buckets.length; i++) { insertionSort(buckets[i]); for (var j = 0 ; j < buckets[i].length; j++) { arr.push(buckets[i][j]); } } return arr; } let arr = [];let i = 100 _000;while (i > 0 ) { arr.push(i); i--; } console .time("a" );console .log(bucketSort(arr));console .timeEnd("a" );
基数排序 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 function getMaxLen (arr: number [] ) { let maxLen = 0 ; for (let i = 0 ; i < arr.length; i++) { const num = arr[i]; if (num.toString().length > maxLen) maxLen = num.toString().length; } return maxLen; } function radixSort (arr: number [] ) { const maxDigit = getMaxLen(arr); for (let i = 0 ; i < maxDigit; i++) { const arrays: number [][] = []; for (let j = 0 ; j < arr.length; j++) { const numS = arr[j].toString(); const n = Number (numS[numS.length - i - 1 ]) || 0 ; if (arrays[n] === undefined ) arrays[n] = []; arrays[n].push(arr[j]); } arr = []; for (let j = 0 ; j < arrays.length; j++) { const array = arrays[j] || []; for (let k = 0 ; k < array.length; k++) { const num = array[k]; arr.push(num); } } console .log(arr); } return arr; } console .log( radixSort([3 , 44 , 38 , 5 , 47 , 15 , 36 , 26 , 27 , 2 , 46 , 4 , 19 , 50 , 48 ]) );