JS数据结构——二叉堆、堆排序

二叉堆

结构特性:这是一种特殊的二叉树,他是一个完全的二叉树,树的每一层都有左右子树,并且最后一层的叶节点尽可能都是左子树

堆特性:二叉堆不是最小堆就是最大堆。最小堆允许快速找到树的最小值,最大堆允许找到树的最大值。所有节点都大于等于(最大堆)或者小于等于(最小堆)每个他的子树

二叉树的数组表示

1.正常的情况下,数组可以通过节点指针的方式表示

2.也可以通过数组的方式表示节点,一般情况下:

  • 它的左侧子节点的位置是2*index+1
  • 它的右侧子节点的位置是2*index+2
  • 它的父节点位置是index/2
getLeftIndex(index){
    return 2*index +1
}
getRightIndex(index){
    return 2*index +2
}
getParentIndex(index){
    if(inedx ==0){
        return underfined
    }
    return Math.floor((inedx-1)/2)
}

向堆中插入值

创建最小堆

整个过程为:将值插入堆的底部叶节点,然后再执行上移shifUp操作,将值和他的父节点进行交换,直到父节点小于这个插入的值

class MinHeap{
    this.heap=[]
}
//添加并上移的操作
insert(index){
    if(value !=null){
        this.heap.push(value)
        this.siftUp(this.heap.length-1)
        return true
    }
    return false
}
//上移具体过程
如果插入的值比父元素大,就交换位置
shifUp(index){
    let parent = this.getParentIndex(index)
    while(
    index >0 && this.heap[parent]>this.heap[index]
    ){
        swap(this.heap,parent,index)
        index = parent
        parent = this.getParentIndex(index)
    }
}

function swap(array,a,b){
    const temp = array[b]
    array[a] = array[b]
    array[b] = temp
    //或者
    const swap = (array,a,b)=>[array[a],array[b]]=[array[b],array[a]]
}
在堆中找到最小值或者最大值

在堆中,最小的值总是位于数组的第一个位置(堆的根节点

size(){
    return this.heap.length
}
isEmpty(){
    return this.heap.length ===0
}
findMin(){
    return this.isEmpty()?undefined : this.heap[0]
}
导出堆中的最小值或最大值

移除最大值或最小值表示的是要移除堆数组中的第一个元素,在移除了之后将堆的最后一个元素移动到根部并执行下移siftDown操作开始交换元素一直到堆正常

extract(){
    if(this.isEmpty()){
        return underfined
}
if(this.size()===1){
    return this.heap.shift()
 }
 const removedValue = this.heap.shift()
 this.siftDown(0)
 return reovedValue
}
//具体的下移操作
siftDown(index){
    let element = index
    //找到当前值的左右子树
    const left = this.getLeftIndex(index)
    const right = this.getRightIndex(index)
    //计算当前堆的长度
    const size = this.size()
    //如果当前元素比左侧节点大,则交换位置
    if(left<size && this.heap[element]>this.heap[right]){
        element = left
    }
    if(right<size && this.heap[element]>this.heap[right]){
        element = right
    }
    if(index !== element){
        swap(this.heap,index,element)
        this.siftDown(element)
    }
}

创建最大堆

最大堆算法跟最小堆类似,只不过把所有大于换成小于即可

堆排序算法

  1. 用数组创建一个最大堆用于源数据
  2. 在创建最大堆之后,最大的值会被储存在堆的第一个位置,然后把这个值替换成堆的最后一个值,并将堆的大小-1
  3. 将堆的根节点下移并重复步骤2直到堆的大小为1

如果想要升序的话 就是最大堆,想要降序就是最小堆

function heapSort(array,compareFn){
    let heapSize = array.length
    //步骤1
    buildMaxHeap(array,compareFn)
    while(heapSize>1){
        swap(array,0,--heapSize)
        heapify(array,0,heapSize,compareFn)
    }
    return array
}


function buildMaxHeap(array,compareFn){
    for(let i = Math.floor(array.length/2);i>=0;i-=1){
        heapify(array,i,array.length,compareFn)
    }
    return array
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值