平时不常用,面试会问,做理解记录;还有种一看就懂,不看就忘的错觉。
排序算法归类:
算法 | 思想 | 性能 | 分类 |
---|---|---|---|
冒泡排序 | 时间复杂度O(n^2) 空间复杂度O(1) | 交换排序 | |
快速排序 | 事件复杂度O(nlbn) 空间复杂度O(n) | 交换排序 | |
选择排序 | 时间复杂度O(n^2) 空间复杂度O(1) | 选择排序 | |
堆排序 | 选择排序 | ||
插入排序 | 时间复杂度O(n^2) 空间复杂度O(1) | 插入排序 | |
希尔排序 | 插入排序 |
冒泡排序
基本思想:内部for
循环中j+1
和j
进行比较,可交换则进行值交换,此时置flag
为true,n-1
次循环结束后把最大的值交换到了最后,则下次循环n-2
(因为i++
);将第二大数值、第三大数值…排到后第二、三位…最终完成arr[0]
和arr[0]
的比较,完成排序。
说明:flag
用于提前返回,减少内部for循环
;如果第一次n-1
次循环结束没有发生交换,说明当前数组是排序好的。则无需再循环处理, 直接返回。
// 这是我印象中一直存在的
function BubbleSort(arr){
let len = arr.length;
for(let i=0;i<len-1;i++){
for(let j=i+1;j<len;j++){
if(arr[i]>arr[j]){
[arr[i],arr[j]] = [arr[j],arr[i]]
}
}
}
return arr;
}
// 这是一个变种,优点是如果排序好的话,不在处理。
function BubbleSort(arr){
let len = arr.length;
let flag = true; // 标识是否进行了值交换
for(let i=1;i<len&&flag;i++){ // 根据判断 flag; 如果没有交换过值,则当前数组是排序好的,
flag = false;
for(let j=0;j<len-i;j++){ // 内存循环依次把最大的值交换到最后
if(arr[j]>arr[j+1]){
flag = true;
[arr[j],arr[j+1]] = [arr[j+1],arr[j]];
}
}
}
return arr;
}
快速排序
快速排序是一种二叉树结构的交换排序算法。
递归
思想:
- 选取一个元素作为基准,比这个数小的放左边,比这个数大的放右边。
- 左边的数再选取一个元素作为基准,重复上述一步骤。
- 右边的数再选取一个元素作为基准,重复上述一步骤。
说明:
以temp(arr[low])
为基准元素,第一个while
循环查找比temp
小的值,j
最小为i
;如果存在这个值,给当前i
位置赋值,这是第一个小于基准值temp
的值,放到了左边;第二个while
循环查找比temp
大或相等的值,i
最大为j
;如果这个值存在,给当前的位置j
赋值,即把比temp
大的值放到了右边; 继续循环条件i<j
;
整个while(i<j)
循环结束后,基准值temp
左边是比它小的,右边是比它大的;i
的位置即是基准值。
function QuickSort(arr,low=0,high=arr.length-1){
let i = low,j = high;
let temp = arr[low];
while(i<j){ // 依次循环结束标识,i>=j
while(i<j&&temp<=arr[j]){ // 找到比temp 小的值,j最小为i
j--;
}
if(i<j){ // j 不等于i ,找到了比temp 小的值,进行值交换
arr[i] = arr[j]; // i 的位置则放置为更小的值
i++;
}
while(i<j&&arr[i]<temp){ // 找temp 大或相等的值,i最大为 j
i++;
}
if(i<j){ // i 不等于j ,找到了比temp大的值,进行值交换
arr[j] = arr[i];
j--;
}
}
arr[i] = temp;
if(low<i) QuickSort(arr,low,i-1);
if(i<high) QuickSort(arr,j+1,high);
return arr;
}
选择排序
思想:
-
假设
minIndex = i
下标值为最小值,则从j = i+1
起其他位置找比它小的值,记录下标值minIndex
。 -
minIndex != i
时,有最小值,进行交换。 -
直到循环结束
按最从小到大排列:
function SelectSort(arr){
let minIndex=0,
len = arr.length;
for(let i=0;i<len-1;i++){
minIndex = i; // 默认最小值的下标值为 i ,找比它小的值得下标
for(let j=i+1;j<len;j++){
if(arr[minIndex]>arr[j]){ // 找到比i 位置小的值,记录下标值
minIndex = j;
}
}
if(minIndex!=i){ // 最小值小标不等于i 时,进行交换
[arr[i],arr[minIndex]] = [arr[minIndex],arr[i]];
}
}
}
插入排序
思想:
- 假设
arr[i]
是最小的,判断arr[i+1]
是不是更小,则进行交换; - 已经排好两个,进行下次循环
i++
,此时i=1
;需要查找的是arr[0]、arr[1]、arr[2]
,将arr[2]
交换到合适的位置; ...
function InsertSort(arr){
let len = arr.length;
for(let i=0;i<len-1;i++){
let j= i;
temp = arr[i+1];
while(j>-1 && temp<arr[j]){
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
return arr;
}
希尔排序
在分组中实现的插入排序。把待排数据分为若干小组,在各小组内实现插入排序,减少分组继续排序。
堆排序
将待排序的数据元素构成一个完全二叉树结构,