1. 什么叫做排序?
2.常见的排序算法 (要背)
注: 这里有 马士兵老师的宋词记忆法 (恩老: nlog2n, 恩一三: n^1.3)

3.如何写算法程序
3.1 由简单到复杂
3.1.1 验证一步走一步
3.1.2 多打印中间内容
3.2 先局部后整体
3.2.1 没思路时先细分
3.3 先粗糙后精细
3.3.1 变量更名
3.3.2 语句合并
3.3.3 边界处理
4. 算法讲解
4.1 选择排序
4.1.1 最简单但是最没用的排序算法
将数组第一位和数组第二位进行对比,哪个比较小,将坐标记录下来,再将第二位和第三位进行对比,比较大小,更改坐标记录,重复操作,知道数组遍历完,将做小的数放在数组最前面。之后再去掉第一位,遍历之后的数组数字,重复以上操作。
4.1.2 写法
const arr = [5, 3, 6, 8, 7, 9];const select = () => {for(let i = 0; i<arr.length - 1; i++){//记录当前坐标let minPos = i;//比较当前坐标 minPos 与 minPos + 1 的大小,如果前者较大,则更改坐标。for(let j = i + 1; j<arr.length;j++) {if(arr[j] < arr[minPos]) minPos = j;}//将数组内容交换let temp = arr[i];arr[i] = arr[minPos];arr[minPos] = tmp;}}// 优化代码//设置做大数据坐标,最小数据坐标//将较大的数放在后面,将较小的数放在前面const better = () => {let left = 0;let right = arr.length - 1;while(left < right) {let minPos = left;let maxPos = right;for(let i = left; i <= right; i++) {if(arr[ i ] < arr[minPos]) {minPos = i;}if(arr[ i ] > arr[maxPos]) {maxPos = i;}}let minTemp = arr[minPos]arr[minPos] = arr[left];arr[left] = minTemp;if(left == maxPos) {minPos = maxPos;}let maxTemp = arr[maxPos]arr[maxPos] = arr[right];arr[right] = maxTemp;left++;right--;}return arr}
4.1.3 大O分析
const arr = [5, 3, 6, 8, 7, 9]; //初始化,不计入算法时间const select = () => {// 执行 n 次 执行 n-1 次 执行 n 次for(let i = 0; i<arr.length - 1; i++){//执行 n 次let minPos = i;// 执行 n 次 执行 n^2 次 执行 n^2 次for(let j = i + 1; j<arr.length;j++) {//当 j = i+1时 执行 n-1 次// n^2if(arr[j] < arr[minPos]) minPos = j;}// 执行 n 次let temp = arr[i];arr[i] = arr[minPos];arr[minPos] = tmp;}}
4.2 冒泡排序
4.2.1 介绍
将数字[0]与数组[1]比较,如果[0]比较大,将两者交换位置,再将[1]和[2]比较,如果[1]比较大,两者交换位置,循环,知道不能交换为止。
4.2.2 写法
function sort(arr){for(let i = arr.length - 1; i > 0; i--) {//循环,每次交换位置,则去掉最后一个数据for(let j = 0; j<i; j++) {//找到最大值,并将最大值放到数组的最后if(a[j] > a[j+1]) {//交换数组数据let temp = a[j]a[j] = a[j+1]a[j+1] = a[j]}}}}
4.3 插入排序
4.3.1 插入排序
对于基本有序的数组最好用
从数组[1]开始和数组[0]比较大小,如果[1]比较大,交换位置,然后从[2]开始,和[1]比较大小,同理,之后循环, dddd
4.3.2 图例
4.3.3 写法
function sort(arr) {//i 是当前坐标for(i = 1; i < arr.length; i++){//当前坐标 - ifor(let j = i; j > 0; j--) {//将当前坐标 与 坐标之前的比较,如果较小则交换位置if(arr[j] < arr[j-1]) {swap(arr, j, j-1);}}}return arr}function swap(arr, i, j) {let temp = arr[i]arr[i] = arr[j]arr[j] = arr[i]}
简单排序算法总结:
冒泡:基本不用,太慢
选择: 基本不用,不稳
插入: 样本小且基本有序的时候效率比较高
5、希尔排序
5.1 介绍
改进的插入排序
在排序的时候需要加入间隔,比如说 gap = 4, 则相隔4个数,选择一个数,将这些数用插入排序排列,
在往后挪移一位在排序,后面同理,排完之后,大致小的数都在数组的前面,大致大的数都在数组后面
之后,缩小间隔为2,在进行上述排序,直到间隔为1排序完成
5.2 图解
5.3 写法
let arr = [5, 3, 6, 8, 7, 9];//希尔排序function sort(arr) {//采用knuth序列let h = 1;while(h < arr.length / 3) {h = h * 3 + 1}for(let gap = h; gap > 0; gap = (gap-1)/3) {Insert(arr, gap)}return arr}//插入排序function Insert(arr, gap) {//i 是当前坐标for(i = gap; i < arr.length; i++){//当前坐标 - ifor(let j = i; j > gap-1; j -= gap) {if(arr[j] < arr[j-gap]) {swap(arr, j, j-gap);}}}return arr}function swap(arr, i, j) {let temp = arr[i]arr[i] = arr[j]arr[j] = arr[i]}
6. 归并排序(merge sort)
6.1 递归
6.2 介绍
将数组分为两个子数组,如果子数组不是有序的,则将子数组在分为两个数组,同上,排到数组就两数或者只有一个数为止,之后再合并成两个数组。设置三个指针,i 为第一个数组头, j 为第二个数组头, k 为新数组头,将arr[i] 和 arr[j] 比较,如果前者较小,则把前者放在arr2[0]里,在比较 arr[i+1] 和 arr[j],那个小就把那个推到 arr2 里去,如此重复
6.3 写法
//两个子数组已经排好序let arr = [1,4,7,8,3,6,9]function sort(arr) {merge(arr)}function merge(arr) {//第二个子数组的开头let mid = arr.length / 2//定义指针let i = 0;let j = mid + 1;let k = 0;let temp = [];while(i <= mid && j <= arr.length) {//当数组相同时,取前面子数组的数据,为了稳定性if(arr[i] <= arr[j]) {temp[k++] = arr[i++];}else {temp[k++] = arr[j++];//j++;//k++;}}//当一个子数组遍历完了,另一个还没遍历完时while(i <= mid) {temp[k++] = arr[i++];}while(j <= arr.length) {temp[k++] = arr[j++]}return temp;}
//优化function sort(arr, left, right) {if(left == right) return;//分成两半let mid = left + (right-left)/2;//左边排序sort(arr,left,mid);//右边排序sort(arr,mid+1,right);merge(arr,left,mid+1,right)}//leftPtr 左子数组头//rightPtr 右子数组头//rightBound 右数组边界function merge(arr, leftPtr, rightPtr, rightBound) {let mid = rightPtr - 1;//定义指针let i = leftPtr;let j = rightPtr;let k = 0;let temp = [];while(i <= mid && j <= rightBound) {//当数组相同时,取前面子数组的数据,为了稳定性if(arr[i] <= arr[j]) {temp[k++] = arr[i++];}else {temp[k++] = arr[j++];//j++;//k++;}}//当一个子数组遍历完了,另一个还没遍历完时while(i <= rightPtr) {temp[k++] = arr[i++];}while(j <= rightBound) {temp[k++] = arr[j++]}return temp;}
6.4 java对象排序
6.4.1 介绍
7 快速排序
7.1 介绍
寻找一个数作为轴,比这个轴小的排前面,比这个轴高的排后面,之后将轴两边进行分区,左子区和右子区,之后再对左右两个分区进行相应的规则排序。
7.2 图例
7.3 算法
let arr = [7,3,2,6,8,1,9,5,4,10]function partition(arr, leftBound, rightBound){//一般来说,轴都是最后一个数let pivot = arr[rightBound];let left = 0;let right = rightBound-1;//两边同时和轴比较,直到左边找到比轴大的数,右边找到比轴小的数,那么将这两个数的位置交换//并将轴的位置放到 left + 1while(left <= right) {while(left <= right && arr[left] < pivot) left++;while(left <= right && arr[right] > pivot) right--;if(left < right) {swap(arr, left, right);}}swap(arr, left, rightBound);return left;}function sort(arr, left, right) {if(arr.length ===0 && left > right) return;//获取到轴的位置let mid = partition(arr, left, right);//再排序轴左边和轴右边sort(arr, left, mid-1);sort(arr, mid+1, right);}
7.4 双轴快排
7.4.1 介绍
找两个数作为轴,把数组分成三个区域,比第一个数小的放左边,比第二个数大的放右边,在两个数中间的放中间。
8. 计数排序
8.1 介绍
非比较排序 桶思想的一种 用于取值范围比较小,但是量大
比如 某大型企业数万名员工年龄排序
如何快速得知高考名次
取一个新的数组进行计数,这个数组的大小则是可以取值的范围
当我们读到0的时候,我们给0坐标的数组+1 同理,每个数出现了多少次,再以这个数作为一个下标值,把他记录下来
8.2 写法
function sort(arr) {let result = [];let count = [];for(let i = 0; i< arr.length; i++){//以该数组为下表的值++,来获取计数数组count[arr[i]]++;}//来还原排序数组for(let i=0,j=0; i<count.length;i++) {while(count[i]-- > 0) {result[j++] = i;}}return result;}
//优化//使用累加数组,来记录每个数最后的一个的坐标function sort(arr) {let result = [];let count = [];for(let i = 0; i< arr.length; i++){//以该数组为下表的值++,来获取计数数组count[arr[i]]++;}//累加数组for(let i = 1; i<count.length; i++) {count[i] = count[i-1] + count[i];}//倒叙筛选,迭代排列for(let i = arr.length-1; i > 0;i--) {result[--count[arr[i]]] = arr[i]}return result;}
9. 基数排序
9.1 介绍
- 非比较排序
- 桶思想的一种
- 多关键字排序
- 按最长的数来排,比如说四位数,就排4次,不足四位的,前面补0
- 举例,全是三位数的排序,首先先排个位数,再排十位数,再排百位数
9.2 写法
//算出每个位上的数,放入一个累加数组中,然后计数排序
10. 桶排序
10.1 图例
之后再在每个桶中单独排序,再把整个桶的数组对外输出。
11. 大数据解题思路



