可视化排序
十大经典排序算法
以下是高德纳在他的著作《计算机程序设计艺术》里对算法的特征归纳:
- 输入:一个算法必须有零个或以上输入量。
- 输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。
- 明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地匹配要求或期望,通常要求实际运行结果是确定的。
- 有限性:依据图灵的定义,一个算法是能够被任何图灵完备系统模拟的一串运算,而图灵机只有有限个状态、有限个输入符号和有限个转移函数(指令)。而一些定义更规定算法必须在有限个步骤内完成任务。
- 有效性:又称可行性。能够实现,算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。
- 体育委员两两摸头法(冒泡排序)
- 体育老师一指禅法(选择排序)
- 起扑克牌法(插入排序)
- 强迫症收扑克牌法(基数排序)
- 快速排序
- 归并排序
- 堆排序
冒泡
原理:
N多数字,第1个数字跟第二个比较,if 第1个数字大(或者小),跟第2个交换位置。交换位置后,第2个和第3跟比较,比较后,交换位置,第一轮结束后,最大(最小)的数字会到最后一位。
下一轮,忽略已经排好的数字,继续...
直到所有的数字都排列完成
代码实现:
function arr_sort(arr) {for(let i = 0; i < arr.length - 1; i++) { //9for(let j = 0; j < arr.length - 1 - i; j++) { //9if(arr[j] > arr[j + 1]) {// [ arr[j], arr[j+1] ] = [ arr[j+1], arr[j] ] /*交换元素*/var max = arr[j]; //大数arr[j] = arr[j + 1];//把第2位赋值给第1位arr[j + 1] = max;//第2位得到第1位的值}}}}var arr = [665, 432, 21, 534645, 5345341, 5, 8, 3, 2, ];arr_sort(arr);console.log(arr)
选择排序
原理:
N多个数字
1.从其中找出最小的,和第一位交换位置,
2.从第二位开始找出最小的,和第二位交换位置,第一位已经是最小的了。
.........
代码实现:
function arr_sort(arr) {for(let min = i = 0; i < arr.length - 1; i++) {min = i;//第一位for(let j = i + 1; j < arr.length; j++) {if(arr[min] > arr[j]) {//最小的min = j}}//[arr[i], arr[min]] = [arr[min], arr[i]] //把每轮的第一个和当前轮的最小值交换位置var mins = arr[min];arr[min] = arr[i];arr[i] = mins;}}var arr = [665, 432, 21, 534645, 5345341, 5, 8, 3, 2];arr_sort(arr)console.log(arr)
插入排序
原理:
N多数字
1.第一个数字认为是排序好的,选择第二位的数字,把第二位的数字放到已经排序号的第一位的合适位置(合适位置解释:跟第一位比较,大或是小)。
2.第一二位已经排序好了,看第三位的数字,继续放到已经排序好的第一二为的合适位置...
......
代码:
function arr_sort(arr) {for(let i = 1; i < arr.length; i++) {for(let j = 0; j < i; j++) {if(arr[i] > arr[j]) {//splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。arr.splice(j, 0, arr[i]) //向数组中添加arr[i]arr.splice(i + 1, 1) //删除i+1break}}}}var arr = [665, 432, 21, 534645, 5345341, 5, 8, 3, 2];arr_sort(arr)console.log(arr)
快速排序(理解不透彻,代码搬运)
原理:
N多数字
1.从N多数字中选出一个数字。(基准数字)
2.从新排序,跟基准数字比较,大的小的,分开存放。
3.递归的把大的小的排序。
4.递归到最底部时,数列的大小是零或一,也就是已经排序好了。
代码:
function quickSort(arr) {if(arr.length <= 1) {return arr}let leftArr = [] let rightArr = []for(let i = 1; i < arr.length; i++) {if(arr[i] >= arr[0]) {rightArr.push(arr[i])} else {leftArr.push(arr[i])}}return quickSort(leftArr).concat(arr[0]).concat(quickSort(rightArr))
}var arr = [10, 34, 21, 47, 3, 28]
quickSort(arr)
console.log(arr)
希尔排序(理解不多,效率相对较好)
原理:
在进行插入排序之前
把N多数字分成N组
组内进行插入排序
依次缩减组数再进行排序
待组数足够小
再对所有数字进行一次插入排序
代码:
function shellSort(arr) {var tempvar len = arr.lengthfor (var gap = len >> 1; gap > 0; gap = gap >>=1) {for (var i = gap; i < len; i++) {temp = arr[i]for( j = i - gap; j >=0 && arr[j] > temp; j -= gap) {arr[j + gap] = arr[j]}arr[j + gap] = temp}console.log(arr)}
}var arr = [3, 1, 7, 2, 5, 0, 4, 6]
shellSort(arr)
console.log(arr)
归并排序(完全不懂,待功力增加后,再看)
原理:
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
设定两个指针,最初位置分别为两个已经排序序列的起始位置
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针到达序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
代码
function mergeSort(arr) {var merge = function(left, right) {var result = []while(left.length && right.length) {result.push(left[0] <= right[0] ? left.shift() : right.shift())}return result.concat(left.concat(right))}if(arr.length < 2) return arrvar mid = arr.length >> 1return merge(mergeSort(this.slice(0, mid)), mergeSort(this.slice(mid)))
}