排序算法
记录一些常见的简单的算法
- 冒泡排序,最简单的算法,从运行时间角度看,性能最差一个,比较相邻项,交换位置O(n2)
function swap(array, i, j) {
[array[j], array[i]] = [array[i], array[j]]
}
const Compare = {
LESS_THAN: -1,
BIGGER_THAN: 1,
EQUAL_THAN: 0
}
function defaultCompareFn(a, b) {
if (a === b) {
return Compare.EQUAL_THAN;
}
return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
}
function modifiedBuddleSort(array,compareFn = defaultCompareFn){
const {length} =array;
for(let i=0;i<length;i++){
for(let j =0;j<length-1-i;j++){
if(compareFn(array[j],array[j+1])===Compare.BIGGER_THAN){
swap(array,j,j+1)
}
}
}
return array;
}
2.选择排序,原址排序,找到最小值放第一位,第二小放第二位,以此类推O(n2)
function selectionSort(array,compareFn = defaultCompareFn){
const {length} =array;
let indexMin;
for(let i=0;i<length-1;i++){
indexMin =i;
for(let j=i;j<length;j++){
if(compareFn(array[indexMin],array[j])===Compare.BIGGER_THAN){
indexMin = j;
}
}
if(i!==indexMin){
swap(array,i,indexMin);
}
}
return array;
}
3.插入排序,每次排一个数组项,以此构建最后排序数组,假定第一项已经排序过,接着和第二项进行比较-,看第二项是否要插入第一项之前,接着和第三项比较,看需要查到哪,以此类推/排序小型数组,这个比选择和冒泡性能好。
function insertionSort(array, compareFn = defaultCompareFn){
const {length}=array;
let temp;
for(let i=1;i<length;i++){
let j =i;
temp = array[i];
while(j>0&&compareFn(array[j-1],temp)=== Compare.BIGGER_THAN){
array[j] = array[j-1];
j--;
}
array[j] = temp;
}
return array;
}
4.计数排序,(整数排序算法),一个数组计算,数字出现过的次数
function countingSort(array) {
if (array.length < 2) {
return array;
}
const maxValue = findMaxValue(array);
const counts = new Array(maxValue + 1);
array.forEach(element => {
console.log(element)
if (!counts[element]) {
counts[element] = 0;
}
counts[element]++;
});
console.log(counts)
let sortedIndex = 0;
counts.forEach((count, i) => {
while (count > 0) {
array[sortedIndex++] = i;
count--;
}
})
return array;
}
function findMaxValue(array) {
let max = array[0];
for (let i = 1; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
}
}
return max;
}
5.归并排序加去重,O(nlog(n)),分而治之算法,将原始数组切分成较小的数组,直到每个小数组只有一个位置,然后再将小的合并成较大数组,直到最后一个排序完毕的大数组。
分治法,递归实现。
function mergeSort(array,compareFn = defaultCompareFn){
if(array.length>1){
const {length} = array;
const middle = Math.floor(length/2);
const left = mergeSort(array.slice(0,middle),compareFn);//划分
const right = mergeSort(array.slice(middle),compareFn);//划分
array = merge(left,right,compareFn)//合并 治
}
return array;
}
function merge(left,right,compareFn){
const res = [];
while(left.length>0&&right.length>0){
if(compareFn(left[0],right[0])===Compare.LESS_THAN){
res.push(left.shift())
}else if(compareFn(left[0], right[0]) === Compare.EQUAL_THAN){
left.shift();
}else{
res.push(right.shift())
}
}
return res.concat(left).concat(right);
}
6.快排也许是最常用得排序算法,O(nlog(n)),性能通常比其他复杂度为O(nlog(n))算法要好,和归并一样,也是分而治之得算法思想。
- 首先选出一个值作为主元(pivot),默认就用数组中间那个值。
- 创建两个指针引用,左边指向数组第一个,右边指向数组最后一个,移动左指针,直到找到比主元大得值,然后移动右指针找到比主元小得值,然后交换它们位置,重复这个过程,直到左指针超过了右指针,这个过程会把比主元小的值都放在左边(主元之前),比主元大的值放在右边(主元之后),这一步叫做划分操作。
- 接着,算法对划分得小数组(较主元小得值组成的子数组,以及较主元大得值组成得子数组)重复之前得两个步骤,直至数组已完全排序。
原址快排如下
function quickSort(array,compareFn = defaultCompareFn){
return quick(array, 0, array.length, compareFn);//左 右起点
}
function quick(array, left, right, compareFn){
let index;
if(array.length>1){
index = partition(array, left, right, compareFn);//排序,交换位置 划分过程
if(left<index-1){//找出相对主元较小得 组项
quick(array, left, index - 1, compareFn);//对较小组继续划分,交换位置 继续分而治之得过程
}
if(index<right){//找出相对主元较大 得组项
quick(array, index, right, compareFn);//同上 对较大组划分
}
}
return array;
}
function partition(array, left, right, compareFn){
let pivot = array[Math.floor((left+right)/2)];//取中间当作主元
let i =left;
let j =right;
while(i<=j){
while (compareFn(array[i], pivot) === Compare.LESS_THAN) {//找到比主元大或相等得
i++;
}
while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) {//找到比主小或相等得
j--;
}
if(i<=j){
swap(array, i, j);
i++;//交换完位置之后,都对应加一减一,继续走查找
j--;
}
}
return i;
}
补充一个去重算法
function mapClearArr(arr) {
let map = new Map();
let newArr = [];
const { length } = arr;
for (let i = 0; i < length; i++) {
let current = arr[i];
if (map.get(current) == null) {
map.set(arr[i], 1);
newArr.push(current);
}
}
return newArr;
}
下面介绍几种搜索算法
1.顺序搜索,顺序或线性是最基本得算法,机制是,将每一个数据结构中得元素和我蛮要找得元素作比较,顺序搜索是最低效得一种算法。
const DOES_NOT_EXIST=-1;
function sequentialSearch(array,value,equalsFn=defaultEquals){
for(let i=0;i<array.length;i++){
if(equalsFn(value,array[i])){
return i;
}
}
return DOES_NOT_EXIST;
}
2.二分搜索,类似数字游戏,想一个数字,我们每回应一个数,那个人都会回应我们是高了还是低了,对了。
这个算法要求数组已排序。
function lesserOrEquals(a,b,compareFn){
const comp = compareFn(a,b);
return comp===Compare.LESS_THAN||comp===Compare,EQUALS;
}
function binarySearch(array,value,compareFn=defaultCompare){
const scrtedArray = quickSort(array);
let low =0;
let high = arr.length-1;
while(lesserOrEquals(low,high,compareFn)){
//左右未重叠
const mid = Math.floor((low+high)/2);
const element = scrtedArray[mid];
if(compareFn(element,value)===Compare.LESS_THAN){
low = mid+1;
}else if(compareFn(element,value)===Compare.BIGGER_THAN){
high = mid-1;
}else{
return mid;
}
}
return DOES_NOT_EXIST;
}
分而治之得版本
function binarySerchRecursive(array,value,low,high,compareFn=defaultCanpare){
if(low<high){
const mid = Math.floor((low+high)/2);
const element = array[mid];
if(compareFn(element,value)===Compare.LESS_THAN){
return binarySerchRecursive(array,value,mid+1,high,compareFn)
}else if(compareFn(elemetn,value)===Compare.BIGGER_THAN){
return binarySerchRecursive(array,value,low,mid-1,compareFn);
}else{
return mid;
}
}
return DOES_NOT_EXIST;
}
function binarySeach(array,value,compareFn=defaultCompare){
const sortedArrar=quickSort(array);
const low = 0;
const high = arr.length-1;
return binarySerchRecursive(array,value,low,high,compareFn)
}
https://ruphi.cn/archives/154/
内插算法和二分算法区别
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。