排序方法
稳定:排序之后相同大小的数字位置不会调换
方法 | 思路 | 时间复杂度 | 是否稳定 |
---|---|---|---|
冒泡排序 | 从开始或结束位置开始对比,如果值比他大或小就交换走,一遍确定一个位置 | O(n2) | 是 |
快速排序 | 一开始取一个数,把比他小的放在左边,大的放在右边,然后再把左边的区分,一直到排完,然后排右边,一直到最后 | O(nlogn) | 否 |
选择排序 | 循环一遍找到一个最大的或者最小的放到第一个位置 | O(n2) | 否 |
插入排序 | 将未排序的数组中的数据判断,一个个的插入已排序的数组 | O(n2) | 是 |
希尔(shell)排序 | 先将整个待排序的序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录”基本有序“时,再对全体记录进行依次直接插入排序 | O(n3/2) | 否(每一段插入排序稳定,整体不一定) |
归并排序 | 归并算法的原理是将所有的元素拆成相邻的一对一对的,然后两两排序,再将相邻的一对元素再合并排序,如此循环最后只剩下两组最大的已经排好的有序数组合并 | O(nlogn) | 是 |
- 冒泡排序
从开始或结束位置开始对比,如果值比他大或小就交换走,一遍确定一个位置
let arr = [1,2,3,6,7,9,0,9,8,7,8,9,6,5,4,3,2,6,7,5,3,3,5];
let maopao = function(arr = []){
// 避免影响到原数组
arr = JSON.parse(JSON.stringify(arr));
let length = arr.length;
for(let i = 0; i < length; i++){
for(let j = i+1; j < length; j++){
console.log(arr[i],arr[j])
if(arr[i] > arr[j]){
let str = arr[i];
arr[i] = arr[j];
arr[j] = str;
}
}
}
return arr;
}
maopao(arr);
- 快速排序
一开始取一个数,把比他小的放在左边,大的放在右边,然后再把左边的区分,一直到排完,然后排右边,一直到最后
let arr = [1,2,3,6,7,9,0,9,8,7,8,9,6,5,4,3,2,6,7,5,3,3,5];
let quickSort = function(arr){
arr = JSON.parse(JSON.stringify(arr));
let length = arr .length;
if(length == 0) return arr ;
let nowMiddle = arr .splice(Math.floor(length/2),1)[0];
let left = [];
let right = [];
for(let i=0; i<length-1;i++){
if(arr [i]<nowMiddle ){
left.push(arr [i]);
} else {
right.push(arr [i]);
}
}
return quickSort(left).concat([nowMiddle],quickSort(right));
}
quickSort(arr);
- 选择排序
循环一遍找到一个最大的或者最小的放到第一个位置
let arr = [1,2,3,6,7,9,0,9,8,7,8,9,6,5,4,3,2,6,7,5,3,3,5];
let chooseSort = function(arr = []){
arr = JSON.parse(JSON.stringify(arr));
let length = arr.length;
if(length == 0) return arr;
// 最后一个不需要对比了
for(let i = 0; i<length-1; i++){
let nowIndex = i;
// 记录下标的方式比直接调换值更好一些
for(let j = i+1; j<length; j++){
if(arr[nowIndex] > arr[j]){
nowIndex = j;
}
}
if(nowIndex !=i){
let nowSmall = arr[nowIndex];
arr[nowIndex] = arr[i];
arr[i] = nowSmall;
}
}
return arr;
}
chooseSort(arr);
- 插入排序
将未排序的数组中的数据判断,一个个的插入已排序的数组
// 查找应该插入到哪个位置
let searchInsertIndex = function(arr,item){
let left = 0;
let right = arr.length -1;
while(left <= right){
let middle = Math.floor((left + right)/2);
if(arr[middle] == item){
// 这时候已经找到一个相同的数据了,已经可以确定位置在middle,但是还不能插入到middle后面,因为不知道当前数组是不是没有重复的数据,现在需要解决一下重复的数据
if(arr[middle+1] > item){
return middle;
} else {
left = left + 2;
}
} else if(arr[middle] < item){
if(arr[middle+1] > item){
return middle;
} else if(arr[right] <= item){
return right;
}
left = middle+1;
} else if(arr[middle] > item){
if(arr[middle-1] < item){
return middle - 1;
} else if(arr[left] > item){
return left - 1;
}
right = middle-1;
}
}
}
let arr = [1,2,3,6,7,9,0,9,8,7,8,9,6,5,4,3,2,6,7,5,3,3,5];
// 需要额外的空间
let insertSort = function(){
let extraArr = [];
let length = arr.length;
for(let i=0; i<length; i++){
let item = arr[i];
let extraLength = extraArr.length;
// 在数据长度大于4的时候就使用二分法查询插入
// 在插入的时候需要判断一下需要插入到哪个位置
// 根据二分法找到具体的插入位置
let index = searchInsertIndex(extraArr,item);
extraArr.splice(index+1,0,item);
}
return extraArr;
}
insertSort(arr);
…待续