最小堆實現 | JS
阿新 • • 發佈:2021-07-17
堆是一種特殊的完全二叉樹,JS中常用陣列表示堆,左側子節點的位置是2*index+1 ,右側子節點的位置是2*index + 2。
堆可以快速找到最大值和最小值,時間複雜度是O(1),找出第K個最大(最小)元素
如果想要獲取第K個最大的元素,可以構建一個最小堆,並將元素依次插入堆中,當堆的容量超過K,就刪除堆頂,插入結束之後堆頂就是第K個最大元素。
1 class MinHeap { 2 constructor(){ 3 this.heap = []; 4 } 5 swap(i1, i2){ 6 const temp = this.heap[i1];7 this.heap[i1] = this.heap[i2]; 8 this.heap[i2] = temp; 9 } 10 getParentIndex(i){ //獲取父節點的值 11 return (i-1) >> 1; //二進位制右移相當於除以2 12 } 13 getLeftIndex(i) { //獲取左結點 14 return i * 2 + 1; 15 } 16 getRightIndex(i) { //獲取右結點 17 return i * 2 + 2; 18 } 19 20 shiftUp(index){ //需要讓父節點不斷小於它的子節點 21 if(index == 0){ return; } //如果已經是根結點了就不用找了 22 const parentIndex = this.getParentIndex(index); 23 if(this.heap[parentIndex] > this.heap[index]){ 24 this.swap(parentIndex, index); //如果父節點的值大於子節點則進行交換 25 this.shiftUp(parentIndex) 26 } 27 } 28 insert(value){ //插入,新增的方法 29 this.heap.push(value); 30 this.shiftUp(this.heap.length - 1); //shiftUp就是上移操作,接收引數是上移時的下標 31 } 32 shiftDown(index){ //下移節點,直到子節點都大於當前節點的值 33 // 需要獲取它的左右子節點 34 const leftIndex = this.getLeftIndex(index); 35 const RightIndex = this.getRightIndex(index); 36 if(this.heap[leftIndex] < this.heap[index]){ //小頂堆,父節點小於子節點 37 this.swap(leftIndex, index); 38 this.shiftDown(leftIndex); //迭代,直到找到合適的位置 39 } 40 if(this.heap[rightIndex] < this.heap[index]){ //小頂堆,父節點小於子節點 41 this.swap(rightIndex, index); 42 this.shiftDown(rightIndex); //迭代,直到找到合適的位置 43 } 44 } 45 46 pop(){ //下移方法 47 this.heap[0] = this.heap.pop(); // 把陣列的最後一位轉移到頭部,相當於變相刪除堆頂 48 this.shiftDown(0); //傳什麼下標,就對那個進行下移操作 49 } 50 peek(){ //獲取堆頂,返回陣列的頭部 51 return this.heap[0]; 52 } 53 size(){ // 獲取堆的大小 54 return this.heap.length; 55 } 56 } 57 58 const h = new MinHeap(); 59 h.insert(3); 60 h.insert(2); 61 h.insert(1); 62 h.pop();