选择排序
选择排序是一个简单直观的排序方法。首先从未排序序列中走到最大的元素,放到已排序的末尾,重复上述步骤,知道所有元素排序完毕
const arr = [23,2,6,1];
function checkSort (arr) {
if (arr.length <= 1) return arr;
for (let i = 0; i < arr.length; i++){
let index = i;
for (let j = i + 1; j < arr.length; j++){
if (Number(arr[index]) > Number(arr[j])) {
index = j;
}
}
if (index !== i) {
[arr[i], arr[index]] = [arr[index], arr[i]];
}
}
return arr;
}
checkSort(arr); // [1, 2, 6, 23]
插入排序
插入排序算法类似打牌,我们将手里的牌会按照从小到大的顺序排列,单再次拿起一张牌时,会根据牌的大小插入到合适的位置。类似这样的一种排序方式就是插入排序
function insertSort (arr) {
if (arr.length <= 1) return arr;
for (let i = 1; i < arr.length; i++){
for (let j = i - 1; j >= 0; j--){
if (+arr[j] > +arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
} else if (+arr[j + 1] >= +arr[j]) {
break;
}
}
}
return arr;
}
insertSort(arr); // [1, 2, 3, 4, 23, 56]
冒泡排序
冒泡排序就是将相邻的数据进行两两比较,大的放后面,小的放前面。
const sarr = [3,1,5,2,4,90,134,1346];
function maopaoSort (arr) {
if (arr.length <= 1) return arr;
for (let i = 0; i < arr.length; i++){
for (let j = 0; j < arr.length - i - 1; j++){
if (+arr[j] > +arr[j+1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
maopaoSort(arr); // [1, 2, 3, 4, 5, 90, 134, 1346]
希尔排序
希尔排序本质上是一种插入排序,但是对数列进行了等间隔分组处理,在每一组中做插入排序。
希尔排序是按一定的间隔对数列进行分组,然后在每一个分组中做插入排序;随后逐次缩小间隔,在每一个分组中做插入排序,直到间隔等于1,做一次查处片吸塑后结束。
const str = [1,4,6,8,2,6,34,123];
function shellSort (arr) {
if (arr.length <= 1) return arr;
let len = arr.length
for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)){
for (let i = gap; i <len; i++){
let j = i;
let temp = arr[j];
for (; j > 0; j -= gap){
if (+temp >= +arr[j - gap]) {
break;
}
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
return arr;
}
shellSort(str); // [1, 2, 4, 6, 6, 8, 34, 123]
快速排序
在数组中,设置一个基准值(一般为数组的中间一个)。准备两个空数组,遍历该数组,小于基准值的放在一个数组中,大于基准值的放在另一个数组中,使用递归重复该步骤
const arr = [2, 4, 7, 1, 6, 9, 3,35,214];
function quickSort (arr) {
if (arr.length <= 1) return arr;
const middelIndex = Math.floor(arr.length / 2);
const middle = arr.splice(middelIndex, 1)[0];
const left = [];
const right = [];
for (let i = 0; i < arr.length; i++){
if (+arr[i] < +middle) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([middle], quickSort(right))
}
quickSort(arr) // [1, 2, 3, 4, 6, 7, 9, 35, 214]
计数排序
计数排序-顾名思义就是记录下来当前出现的数字出现的次数。
计数排序不是基于比较的排序方法。其核心在于将输入的数据值转化为键存储在额外开辟的数组中。
作为一种线性时间复杂度的排序算法,计数排序要求输入的数据必须是有确定范围的整数。
算法描述
- 找出待排序数组中最大和最小的元素,确定新开辟数组的长度。
- 统计待排序数组中每个值为 i 出现的次数,存入新数组的第 i 项,没出现一次,数组下标对应的值就 + 1
- 数组每一个下标位置的值,代表了数列中对应整数出现的次数。
- 遍历数组,输出数组元素的下标值,元素的值是几,就输出几次。
代码
function countSort(arr){
if(!arr || arr.length<=1) return arr;
const len = arr.length;
// 输出的结果数组
const resArr = new Array(len);
// 计数数组
let countArr;
let min = max = arr[0];
// 统计出现次数
for(let i=0;i<len;i++){
// 若是存在这个值就证明出现过,出现次数+1/若不存在证明是第一次出现就为 1
// countArr[arr[i]] = countArr[arr[i]] ? countArr[arr[i]]+1 : 1;
// 找到最小值
// min = min <= arr[i] ? min : arr[i];
// 找到最大值
max = max >= arr[i] ? max : arr[i];
}
// 确定计数数组的长度
countArr = new Array(max + 1).fill(0);
// 填充统计数组
for(let i=0;i<len;i++){
// 以数组中出现的数字作为填充数组的下标,每出现一次就+1
countArr[arr[i]]++;
}
console.log('countArr', countArr);
// 遍历统计数组,输出结果
let index = 0;
for(let i=0;i<countArr.length;i++){
for(let j=0;j<countArr[i];j++){
// 只有当j有值时才会像结果数组中添加值
// i 是下标,代表了原数组中的值
resArr[index++] = i;
}
}
return resArr;
}
const arr = [1,3,6,8,11,2,5,7,3,23];
const res = countSort(arr);
console.log(res, res.length); // [1, 2, 3, 3, 5,6, 7, 8, 11, 23] 10