讲到算法,不可避免的会提到排序算法;在排序算法中,冒泡排序、选择排序和插入排序等是最常被问到的几种基本的排序算法。下面用js来实现这几个简单的排序。
1、冒泡排序
概念
从序列的最右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置,重复这一操作,实现所有数字从小到大或从大到小排列的算法即冒泡排序。
步骤
- 外层循环,n长的数组需要比较n趟,每次找到一个最小值
- 内层循环,每一趟之后需要比较的个数减1;
- 从序列的末尾开始比较相邻两个数字的大小;如果比较的数据比左边相邻的数据小,则左移当前比较的数据。
- 直至当前比较数据的位置等于当前比较次数时,则一轮结束。
- 比较完一轮后,继续从末尾开始比较下一轮
代码
// 编写方法,实现冒泡
var arr = [29,45,29,72,51,68,72,97];
var getMaopao = function(arr) {
//外层循环,控制趟数,每一次找到一个最小值
for (var i =0; i< arr.length - 1; i++){
// 内层循环,从右侧开始控制比较的次数,并且判断两个数的大小
for (var j = arr.length; j>= i; j--){
// 如果后面的数小,放到前面(从小到大的冒泡排序)
if (arr[j]< arr[j-1]) {
var temp = arr [j];
arr [j] = arr[j-1];
arr[j-1] = temp;
}
}
}
return arr;
}
console.log('maopao', getMaopao(arr))
也可以是从前到后比较
for (var i = 0; i < arr.length - 1; i++) {
// 内层循环,控制比较的次数,并且判断两个数的大小
for (var j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
2、选择排序
概念
从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换,重复这一操作的算法即选择排序。
步骤
- 循环数组,找到最小值
- 将最小值和最左边的元素进行调换,完成第一轮
- 从第二位开始,循环数组,找到剩下的最小值
- 重复直到最后一轮,依次完成所有数据的排序
代码
var arr = [120,29,45,29,72,51,68,72,97];
var getChoose = function(arr) {
//外层循环,控制趟数,每一次找到一个最小值
for (var i =0; i< arr.length - 1; i++){
// 内层循环,从右侧开始控制比较的次数,并且判断两个数的大小
var min = arr[i];
var minIndex = i;
// 内层循环,每一次找到余下数字的最小值,记录下标
for (var j = i; j< arr.length; j++){
if (arr[j]<min) {
min = arr[j]
minIndex = j
}
}
// 将最小值与第i位交换位置
var temp = arr[i]
arr[i] = arr [minIndex]
arr[minIndex] = temp
}
return arr;
}
console.log('choose', getChoose(arr))
如果不记录下标,在内层循环交换位置也是可以的(每次都把最小值往前交换,类似冒泡),但是这样交换的次数会很多,运行速度会变慢。
3、插入排序
概念
从序列左端开始依次对数据进行排序的算法称为插入排序。(序列中数据分为已排序区和未排序区,依次对每个数据和已排序区比较,进行排序)
步骤
- 假设第一个数字已完成排序,对第二个数字与第一个进行比较
- 如果小于它,则放到它之前,否则之后,完成排序
- 然后第三个数字,与前两个已排序的进行比较,找到小于它的数字,放在此数字之后
- 如此反复,完成整个数组的排序
代码
// 编写方法,实现插入排序
var arr = [120,29,45,29,72,51,68,72,97];
var getChoose = function(arr) {
var newArr = [arr[0]];
//外层循环旧数组,获得未排序区的数字
for (var i =1; i< arr.length; i++){
// 内层循环新数组,将未排序区的数字与已排序区比较
for (var j = 0; j< newArr.length; j++) {
// 当数字小于已排序区的某个数字时,将此数字插入在已排序区的该数字之后,跳出循环
if (arr[i]< newArr[j]) {
newArr.splice(j,0,arr[i])
break;
}
}
}
return newArr;
}
console.log('choose', getChoose(arr))
4、快速排序
概念
快速排序的原理,简单来说就是把一个事情,分成很多小事情来处理,分治的思想。如找到一个基准,将大于它的放到右边,小于它的所有数放到左边,再分别对左右的数组重复此步骤,最后数组将按照从小到大的顺序排列。
步骤
- 找基准(一般是以第一项为基准)
- 遍历数组,小于基准的放在left,大于基准的放在right
- 递归,对left和right内的数组不断重复以上方式,直到最后剩下一位。(有些二分法的意思)
代码
let dat=[5, 8, 10, 3, 2, 18, 17, 9];
var sortedData=function quickSort(data){
//递归出口
if(data.length<=1){
return data;
}
//此处要将基准数从原数组移除,避免上面的data.length判断陷入死循环
let baseData=data.splice(0,1)[0];
let leftData=[],rightData=[];
//此处的data.length和上面不同,移除了基准数,比上面小1
for(let i=0;i<data.length;i++){
if(data[i]>baseData){
rightData.push(data[i]);
}else{
leftData.push(data[i]);
}
}
leftData=quickSort(leftData);
rightData=quickSort(rightData);
return [...leftData, baseData, ...rightData];
}
console.log(sortedData(dat));