JS算法——基础算法

排序搜索算法

排序算法

冒泡排序

冒泡排序是比较所有相邻的两个项,如果第一个比第二个大,就交换他们,这是整个排序中时间复杂度最大的一个O(n²)

function swap(array,a,b){
    const temp = array[a]
    array[a] = array[b]
    array[b] = temp
    //或者采用ES6
    [arrat[a],array[b]]=[array[b],array[a]]
}

function bubbleSort(array){
    const {length} = array
    for(let i = 0;i<length;i++){
        for(let j = 0;j<length-1-i;j++){
            if(array[j]>array[j+1]){
                swap(array,j,j+1)
            }
        }
    }
    return array
}
选择排序

找到结构中的最小值放在前面,然后继续找第二小的,继续排序,同样的,时间复杂度也是O(n²)

//如果出现swap则是使用冒泡排序上的swap函数
function selectSort(array){
    const {length} = array
    let indexMin
    for(let i = 0;i<length-1;i++){
        indexMin = i
        for(let j = 0;j<length;j++){
            if(array[indexMin]>array[j]){
                indexMin = j
            }
        }
        if(i!==indexMin){
            swap(array,i,indexMin)
        }
    }
    return array
}
插入排序

假定第一项已经排序了,接着跟第二项进行比较是放在原位还是放在第一项前?然后以此类推

function insertionSort(array){
    const {length} = array
    let temp
    for(let i = 1;i<length;i++){
        let j = i
        temp = array[i]
        while(j>0&&array[j-1]>temp){
            array[j] = array[j-1]
            j--
        }
        array[j] = temp
    }
    return array
}
归并排序

将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后一个排序完毕,该排序的时间复杂度是O(nlog(n))

//此函数用于接收两个数组作为参数,并将它们归并到一个大的数组中,完成排序
function merge(left,right){
    let i = 0
    let j = 0 
    const result = []
    while(i<left.length&&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)
}


function mergeSort(array){
    if(array.length>1){
        const{length} = array
        const middle = Math.floor(length/2)
        const left = mergeSort(array.slice(0,middle))
        const right = mergeSort(array.slice(middle,length))
        array = merge(left,right)
    }
    return array
}
快速排序

时间复杂度为O(nlog(n)),这个算法比较复杂,全过程在于:

  1. 首先从数组中选择一个值作为主元,也就是数组中间的值
  2. 创建两个指针,左边一个指针指向数组第一个值,右边一个指针指向数组最后一个值。移动左指针直到我们找到第一个比主元大的值,接着移动右指针直到找到比主元小的值,然后交换他们,重复这个过程,直到左指针超过右指针,这个过程使得比主元小的值都排在主元之前,比主元大的都排在主元之后欧,这一步叫划分
  3. 算法对划分后的小数组重复之前的步骤,直到排序完成
function quickSort(array){
    return quick(array,0,array.length-1)
}
function quick(array,left,right){
    let index
    if(array.length>1){
        index = partition(array,left,right)
        if(left<index-1){
            quick(array,left,index-1)
        }
        if(index<right){
            quick(array,index,right)
        }
    }
    return array
}

function partition(array,left,right){
    //首先设置一个主元
    const pivot = array[Math.floor((right+left)/2)]
    let i =  left
    let j = right
    //只要指针没有相互交错,就开始移动left指针,直到找到一个比主元大的元素,right指针是找到比主元小的
    while(i<=j){
        while(array[i]<pivot){
            i++
        }
        while(array[j]<pivot){
        j++
    }
    //当左指针指向的元素比主元大且右指针指向的元素比主元小,并且左指针指引没有右指针索引大时,就就换他们位置,然后重新回到前面继续重复
     if(i<=j){
        swap(array,i,j)
        i++
        j--
    }
   
    }
    return i
}
计数排序

这是分布式排序的一种,是使用已组织好的辅助数据结构,进行合并得到排序好的数组,时间复杂度为O(n+k)k为临时计数数组的大小

function findMaxValue(array){
    let max = array[0]
    for(let i = 0;i<array.length;i++){
        if (array[i]>max){
            array[i] = max
        }
    }
    return max
}
function countingSort(array){
    if(array.length<2){
        return array
    }
    //首先要找到数组的最大值
    const MaxValue = findMaxValue(array)
    
    const counts = new Array(maxValue+1)
    //先把每个非0的计数位置全部置0,然后迭代数组,在相应的位置计数
    array.forEach(element=>{
        if(!counts[element]){
            counts[element] = 0
        }
        counts[element]++
    })
    let sortedIndex = 0
    counts.forEach((count,i)=>{
        while(count>0){
            array[sortedIndex++] = i
            count--
        }
    })
    return array
}

分布式算法还有 桶排序 基数排序的算法方式

搜索算法

顺序搜索

这是最基础也是效率最低的搜索算法,将数据结构中每一个元素和我们要找的元素比较

const DOES_NOT_EXIST = -1

function sequentialSearch(array,value){
    for(let i = 0:i<array.length;i++){
        if(array[i] = value){
            return array[i]
        }
    }
    return DOES_NOT_EXIST
}
二分查找

这个算法要求的是数据结构已经被排序好了,于是会有以下步骤:

  1. 选择数组中间的值
  2. 如果选中的值是待搜索值,那么就算找到了
  3. 如果待搜索值比选中的小,就返回步骤1并在选中的值左边的子数组中寻找
  4. 如果带搜索的值比选中值大,则返回步骤1并在选中值右边的子数组中寻找

function binarySearch(){
    const sortedArray = quickSort(array)
    let low = 0
    let high = sortedArray.length-1
    while(low<high){
        const mid = Math.floor((low+high)/2)
        const element = sortedArray[mid]
        if(element<value){
            low = mid+1
        }else if(element>value){
            high = mid -1
        }else{
            return mid
        }
    }
    return -1
}

内插搜索

这是改良版本的二分搜索,二分搜索总是检查mid位置上的值,而内插搜索可能会根据要搜索的值检查数组中的不同地方

随机算法

Fisher-Yates算法
迭代数组,从最后一位开始并将当前位置和一个随机位置进行交换,这个随机位置比当前位置小,这样算法可以保证随机过的位置不会再被随机一次

function shuffle(array){
    for(let i = array.length-1;i>0;i--){
        const randomIndex = Math.floor(Math.random()*(i+1))
        swap(array,i,randomIndex)
    }
    return array
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值