https://visualgo.net/zh
冒泡:大数沉底
冒泡排序比较所有相邻的两个项,如果第一个比第二个大,则交换他们,元素向上移动至正确的顺序,就好像气泡升至表面一样,冒泡排序因此得名
function bubbleSort(array){
const {length} =array
for(let i=0;i<length;i++){
for(let j=0;j<length-1-i;j++){
//到length-1,原因是比较的是arr[j]和arr[j+1],最后一个元素,length-1-i减少循环次数,每次会把最大值放入最后,所有最后可以不去对比
if(array[j]>array[j+1]){
swap(arry,j,j+1)
}
}
}
return array
}
function swap(array,a,b){
const temp=array[a];
array[a]=array[b];
array[b]=temp
//[array[a],array[b]]=[array[b],array[a]]
}
bubbleSort([5,3,2,7,8,1])
选择排序:小数筛选
选择排序算法是一种原址比较排序算法。选择排序大致的思路是找到数据结构中最小值并将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推
function selectionSort(array){
const {length} = array;
let indexMin //最小位置
for(let i=0;i<length-1;i++){ //最后一个不用比
indexMin=i;
for(let i=i; j<length;j++){ //i轮之后,前面已经排序好,就不用在循环,可以从i之后开始
if(array[indexMin]>array[j]){
indexMin=j //改变索引值
}
}
if(i !==indexMin){ //先标记出最小索引位置,然后再互换位置,如果本身就是最小的,就不执行交换
swap(array,i,indexMin);
}
}
return array;
}
插入排序
将待排序的数据分为已排序和未排序,初始时,已排序部分只包含第一个元素,未排序部分包含剩下的元素。从未排序部分取出一个元素,与已排序的元素逐个比较,找到合适的位置插入。
function insertSort(arr){
const {length} = arr;
let temp=0 //存当前一轮对应索引的元素值
for(let i=1;i<length;i++){ //每次往前面对比,所以从第2个开始
let j=i;
temp=arr[i]
while(j>0 && arr[j-1]>temp){ //如果前面的值比临时值大 arr[j-1]>temp
arr[j] = arr[j-1]
j--
}
arr[j] = temp
}
}
归并排序 (火狐浏览器sort使用归并排序,谷歌使用快排)
归并排序是一种分而治之算法。其思想将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
function mergeSort(array){
if(array.length>1){
const {length} =array
const middle=Math.floor(length/2);
const left=mergeSort(array.slice(0,middel))
const right=mergeSort(array.slice(middle,length));
array=merge(left,right)
}
return array;
}
function merge(left,right){
let i=0;
let j=0;
const result=[]
while(i<left.legth && j<right.length){
result.push( left[i] < right[j] ? left[i++] :right[j++] )
}
return result.concat( i<left.length ? left.slice(i) : right.slice(j))
}
mergeSort([5,4,3,2])
快速排序
夸苏排序是一种高效得排序算法,是对冒泡排序得一种改进。其核心思想是通过一次排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的数据要小,然偶在按照此方法对这两部分数据分别进行快速排序,以实现整个序列有序
快速排序的实现步骤:
1.从待排序序列中选一个元素作为基准
2.重新排序数组,将小于基准值元素放在基准值左边,将大于基准值元素放在基准值右边
3.对左、右两边分别进行快速排序
function quickSort(arr){
const {length}=arr
if(legnth<2){
return arr
}
//基准
let base=arr[0]
let minArr=arr.slice(1).filter(item=>item<=base)
let maxArr=arr.slice(1).filter(item=>item>base)
return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
quickSort([3,4,5,2,1])
计数排序
计数排序使用一个用来存储每个元素在原始数组中出现次数的临时数组。在所有元素都计数完成后,临时数组已排好序并可迭代以构建排序后的结果数组。
function countSort(arr){
if(arr.length<2){
return arr;
}
const maxValue=findMax(arr);
//const maxValue=Math.max(...arr)
const counts=new Array(maxValue+1) //构建临时数组
arr.forEach(item=>{
if(!counts[item]){
counts[item]=0
}
counts[item]++
})
let sortedIndex=0;
let newarr=[];
counts.forEach((item,index)=>{
while(item>0){
newarr[sortedIndex++] =index;
item--;
}
})
return newarr;
}
function findMax(arr){
let max=arr[0]
for(let i=1;i<arr.length;i++){
if(arr[i]>max){
max=arr[i]
}
}
return max
}
桶排序
桶排序(也被称为箱排序)也是分布式排序算法,它将元素分为不同的桶(较小的数组),再使用一个简单的排序算法,例如插入排序(用来排序小数组的不错的算法),来对每个桶进行排序。然后将所有的桶合并为结果数组。
function bucketSort(arr,bucketSize=3){
if(arr.length<2){
return arr
}
//创建几个小桶
const buckets=createBucket(arr,bucketSize)
//小桶排序(插入排序算法)合并concat
return sortBucket(buckets)
}
function createBucket(arr,bucketSize){
let minVlaue=Math.min(...arr)
let maxValue=Math.max(...arr)
const bucetCount=Math.floor((maxValue-minValue)/bucketSize)+1
//const buckets=[]
//for(let i=0;i<bucketCount;i++){
// buckets[i]=[]
//}
const buckets=[...Array(bucetCount)].map(()=>[])
for(let i=0;i<arr.length;i++){
const index=Math.floor((arr[i]-minValue)/bucketSize)
buckets[index].push(arr[i])
}
return buckets
}
function sortBucket(arr){
let sortArr=[]
for(let i=0;i<arr.length;i++){
if(arr[i]){
insertSort(arr[i])
sortArr.push(...arr[i])
}
}
return sortArr
}
function insertSort(arr){
const {length}=arr
let temp;
for(let i=0;i<length;i++){
temp=arr[i]
let j=i;
while(j>0&&arr[j-1]>temp){
arr[j]=arr[j-1]
j--
}
arr[j]=temp
}
}
bucketSort([5,4,3,2,6,1,7,10,9,8])
基数排序
const arr=[35,2,26,2,5,8,34,1,56,99,33]
function radixSort(arr){
const base=10
let divider=1
maxVal=Math.max(...arr)
while(divider<=maxVal){
const buckets=[...Array(10)].map(()=>[])
for(let val of arr){
buckets[Math.floor(val/divider)%base].push(val)
}
arr=[].concat(...buckets)
divider*=base
}
}
搜索算法
顺序搜索
顺序或线性搜索是最基本的搜索算法。它的机制是,将每一个数据结构中的元素和我们要找的元素做比较。
function sequentialSearch (array,value){
for(let i=0;i<array.length;i++){
if(value===array[i]){
return i
}
}
return -1
}
二分搜索
function binarySearch(find,arr,start,end){
start=start||0
end=end||arr.length-1
arr=quickSort(arr)
if(start<=end){ //不为【】数组
if(arr[start]===find){
return start
}
if(arr[end]===find){
return end
}
//let mid=(end-start)/2+start
let mid=Math.ceil((end+start)/2)
if(arr[mid]===find){
return mid
}else if(arr[mid]>find){
return binarySearch(find,arr,start,mid-1)
}else{
return binarySearch(find,arr,mid+1,end)
}
}
return -1
}
function quickSort(arr){
const {length} =arr
if(length<2){
return arr
}
//基准
let base=arr[0]
let minArr=arr.slice(1).filter(item=>item<=base)
let maxArr=arr.slice(1).filter(item=>item>base)
return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
binarySearch(5,[5,7,4,2,9])
内插搜索
内插搜索是改良版的二分搜索。二分搜索总是检查mid为自豪上的值,而内插搜索可能会更具要搜索的值检查数组中的不同地方
function insertSearch(find,arr,start,end){
start=start||0
end=end||arr.length-1
arr=quickSort(arr)
if(start<=end){ //不为【】数组
if(arr[start]===find){
return start
}
if(arr[end]===find){
return end
}
let mid=start+Math.fool((find-arr(start))/(arr[end]-arr[start])*(end-start))
if(arr[mid]===find){
return mid
}else if(arr[mid]>find){
return insertSearch(find,arr,start,mid-1)
}else{
return insertSearch(find,arr,mid+1,end)
}
}
return -1
}
function quickSort(arr){
const {length} =arr
if(length<2){
return arr
}
//基准
let base=arr[0]
let minArr=arr.slice(1).filter(item=>item<=base)
let maxArr=arr.slice(1).filter(item=>item>base)
return quickSort(minArr).concat(base).concat(quickSort(maxArr))
}
insertSearch(5,[5,7,4,2,9])
随机算法
迭代数组,从最后一位开始将当前位置和一个随机位置进行交换。这个随机位置比当前位置小。这样,这个算法可以保证随机过的位置不会再被随机一次
function shuffle(array){
for(let i=arr.length-1;i>0;i--){
const randomIndex=Math.floor(Math.random()*(i+1));
swap(array,i ,randomIndex)
}
return array
}
function swap(array,a,b){
const temp=array[a]
array[a]=array[b]
array[b]=temp
}