二叉堆
结构特性:这是一种特殊的二叉树,他是一个完全的二叉树,树的每一层都有左右子树,并且最后一层的叶节点尽可能都是左子树
堆特性:二叉堆不是最小堆就是最大堆。最小堆允许快速找到树的最小值,最大堆允许找到树的最大值。所有节点都大于等于(最大堆)或者小于等于(最小堆)每个他的子树
二叉树的数组表示
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
如果想要升序的话 就是最大堆,想要降序就是最小堆
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
}