世界就像一个巨大的图书馆,我们读着别人,做着自己,等待被读。 :

ES6的JavaScript数据结构实现之二叉堆和堆排序

目的:ES6标准下的JS数据结构的一些实现代码。(作为记录和启发)

内容:二叉堆和堆排序。(未完成,待继续)

所有源码在我的Github上(如果觉得不错记得给星鼓励我哦):ES6的JavaScript数据结构实现之二叉堆和堆排序

一、基础数据结构

1、二叉堆(最小堆和最大堆;插入值(保持最小堆或最大堆结构);找到最大值或者最小值;移除最小堆的最小值(堆的根节点))

基本概念:二叉堆是一种特殊的二叉树,其有两个特性:结构特性和堆特性。结构特性是指它是一颗完全的二叉树(树的每一层都有左侧和右侧子节点(除了最后一层的叶节点),并且最后一层的叶节点尽可能都是左侧子节点)。堆特性是指二叉堆不是最小堆就是最大堆(最小堆可以快速导出树的最小值,最大堆可以快速导出树的最大值),所有的节点都大于等于(最大堆)或者小于等于(最小堆)每个它的子节点。

1.1 最小堆

  1 const Compare = {
  2   LESS_THAN: -1,
  3   BIGGER_THAN: 1,
  4   EQUALS: 0
  5 };
  6 
  7 function defaultCompare(a, b) {
  8   if (a === b) {
  9     return Compare.EQUALS;
 10   }
 11   return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
 12 }
 13 
 14 function swap(array, a, b) {
 15   /* const temp = array[a];
 16   array[a] = array[b];
 17   array[b] = temp; */
 18   [array[a], array[b]] = [array[b], array[a]];
 19 }
 20 function reverseCompare(compareFn) {
 21   return (a, b) => compareFn(b, a);
 22 }
 23 class MinHeap {
 24   constructor(compareFn = defaultCompare) {
 25     this.compareFn = compareFn;
 26     this.heap = [];
 27   }
 28   getLeftIndex(index) {
 29     return 2 * index + 1;
 30   }
 31   getRightIndex(index) {
 32     return 2 * index + 2;
 33   }
 34   getParentIndex(index) {
 35     if (index === 0) {
 36       return undefined;
 37     }
 38     return Math.floor((index - 1) / 2);
 39   }
 40 
 41   size() {
 42     return this.heap.length;
 43   }
 44 
 45   isEmpty() {
 46     return this.size() <= 0;
 47   }
 48 
 49   clear() {
 50     this.heap = [];
 51   }
 52   findMinimum() {
 53     return this.isEmpty() ? undefined : this.heap[0];
 54   }
 55   insert(value) {
 56     if(value != null) {
 57       this.heap.push(value);
 58       const index = this.heap.length - 1;
 59       this.siftUp(index);
 60       return true; 
 61     }
 62     return false;
 63   }
 64   siftUp(index) {
 65     let parent = this.getParentIndex(index);
 66     while (
 67       index > 0 
 68       && this.compareFn(this.heap[parent], this.heap[index]) === Compare.BIGGER_THAN 
 69       ) {
 70       swap (this.heap, parent, index );
 71       index = parent;
 72       parent = this.getParentIndex(index);
 73     }
 74   }
 75   extract() {
 76     if (this.isEmpty()) {
 77       return undefined;
 78     }
 79     if (this.size() == 1) {
 80       return this.heap.shift();
 81     }
 82     const removedValue = this.heap[0];
 83     this.heap[0] = this.heap.pop();
 84     this.siftDown(0);
 85     return removedValue;
 86   }
 87   siftDown(index) {
 88     let element = index;
 89     const left = this.getLeftIndex(index);
 90     const right = this.getRightIndex(index);
 91     const size = this.size();
 92     if (
 93       left < size 
 94       && this.compareFn(this.heap[element], this.heap[left]) === Compare.BIGGER_THAN
 95       ) {
 96       element = left;
 97     } else if (
 98       right < size
 99       && this.compareFn(this.heap[element], this.heap[right] === Compare.BIGGER_THAN)
100       ) {
101       element = right;
102     }
103     if(index !== element) {
104       swap(this.heap, index, element);
105       this.siftDown(element); 
106     }
107   }
108   heapify(array) {
109     if (array) {
110       this.heap = array;
111     }
112     const maxIndex = Math.floor(this.size() / 2) - 1;
113     for (let i = 0; i <= maxIndex; i++) {
114       this.siftDown(i);
115     }
116     return this.heap;
117   }
118 
119   getAsArray() {
120     return this.heap;
121   }
122 
123 
124 }
125 
126 const heap = new MinHeap();
127 heap.insert(2);
128 heap.insert(3);
129 heap.insert(4);
130 heap.insert(5);
131 console.log(heap);
132 heap.insert(1);
133 console.log(heap);
134 console.log(heap.findMinimum());
135 heap.clear();
136 const heap1 = new MinHeap();
137 for (let i = 1; i < 10; i++) {
138   heap.insert(i);
139 }
140 console.log(heap);
141 console.log(heap.extract());
142 console.log(heap);
MinHeap

 

1.2 最大堆

把最小堆中的比较函数修改为相反的就行了,即把最小堆中的所有大于的比较换成小于的比较。

1 class MaxHeap extends MinHeap {
2   constructor(compareFn = defaultCompare) {
3     super(compareFn);
4     this.compareFn = compareFn;
5     this.compareFn = reverseCompare(compareFn);
6   }
MaxHeap

 

二、简单应用

1、堆排序

思路:用数组创建一个最大堆;最大的值放置堆的最后一个位置;将堆的大小减一,每次执行第二个步骤直至堆的大小为1。(这样就得到升序(从最小到最大)的数组,若要数组的降序排列,则我们用最小堆。) 

 1 function heapify(array, index, heapSize, compareFn) {
 2   let largest = index;
 3   const left = (2 * index) + 1;
 4   const right = (2 * index) + 2;
 5   if (left < heapSize && compareFn(array[left], array[index]) > 0) {
 6     largest = left;
 7   }
 8   if (right < heapSize && compareFn(array[right], array[largest]) > 0) {
 9     largest = right;
10   }
11   if (largest !== index) {
12     swap(array, index, largest);
13     heapify(array, largest, heapSize, compareFn);
14   }
15 }
16 
17 function buildMaxHeap(array, compareFn) {
18   for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) {
19     heapify(array, i, array.length, compareFn);
20   }
21   return array;
22 }
23 
24 function heapSort(array = [], compareFn = defaultCompare) {
25   let heapSize = array.length;
26   buildMaxHeap(array, compareFn);
27   while (heapSize > 1) {
28     swap(array, 0, --heapSize);
29     heapify(array, 0, heapSize, compareFn);
30   }
31   return array;
32 }
33 
34 const heapSort1 = new heapSort();
35 const array = [7, 6, 3, 5, 4, 1, 2];
36 
37 console.log('Before sorting: ', array);
38 console.log('After sorting: ', heapSort(array));
HeapSort

 

posted @ 2019-10-28 17:51  Secret_Wu  阅读(682)  评论(0编辑  收藏  举报