二叉堆概述
二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
二叉堆一般都通过”数组”来实现,下面是数组实现的最大堆和最小堆的示意图:
二叉堆的实现
本实现以”最大堆”为例子来进行介绍。
1. 添加
假设在最大堆[90,80,70,60,40,30,20,10,50]种添加85,需要执行的步骤如下:
当向最大堆中添加数据时:先将数据加入到最大堆的最后,然后尽可能把这个元素往上挪,直到挪不动!
将85添加到[90,80,70,60,40,30,20,10,50]中后,最大堆变成了[90,85,70,60,80,30,20,10,50,40]。
最大堆的插入代码
protected void filterup(int start) { int c = start; int p = (c-1)/2; T tmp = mHeap.get(c); while(c > 0) { int cmp = mHeap.get(p).compareTo(tmp); if(cmp >= 0) break; else { mHeap.set(c, mHeap.get(p)); c = p; p = (p-1)/2; } } mHeap.set(c, tmp);}public void insert(T data) { int size = mHeap.size(); mHeap.add(data); filterup(size); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
insert(data)的作用:将数据data添加到最大堆中。mHeap是动态数组ArrayList对象。
当堆已满的时候,添加失败;否则data添加到最大堆的末尾。然后通过上调算法重新调整数组,使之重新成为最大堆。
2. 删除
假设从最大堆[90,85,70,60,80,30,20,10,50,40]中删除90,需要执行的步骤如下:
当从最大堆中删除数据时:先删除该数据,然后用最大堆中最后一个的元素插入这个空位;接着,把这个“空位”尽量往上挪,直到剩余的数据变成一个最大堆。
从[90,85,70,60,80,30,20,10,50,40]删除90之后,最大堆变成了[85,80,70,60,40,30,20,10,50]。
注意:考虑从最大堆[90,85,70,60,80,30,20,10,50,40]中删除60,执行的步骤不能单纯的用它的子节点来替换;而必须考虑到”替换后的树仍然要是最大堆”!
二叉堆的删除代码
protected void filterdown(int start, int end) { int c = start; int l = 2*c + 1; T tmp = mHeap.get(c); while(l <= end) { int cmp = mHeap.get(l).compareTo(mHeap.get(l+1)); if(l < end && cmp<0) l++; cmp = tmp.compareTo(mHeap.get(l)); if(cmp >= 0) break; else { mHeap.set(c, mHeap.get(l)); c = l; l = 2*l + 1; } } mHeap.set(c, tmp);}public int remove(T data) { if(mHeap.isEmpty() == true) return -1; int index = mHeap.indexOf(data); if (index==-1) return -1; int size = mHeap.size(); mHeap.set(index, mHeap.get(size-1)); mHeap.remove(size - 1); if (mHeap.size() > 1) filterdown(index, mHeap.size()-1); return 0;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
完整代码
二叉堆(最大堆)的实现
public class MaxHeap<T extends Comparable<T>> { private List<T> mHeap; public MaxHeap() { this.mHeap = new ArrayList<T>(); } protected void filterdown(int start, int end) { int c = start; int l = 2*c + 1; T tmp = mHeap.get(c); while(l <= end) { int cmp = mHeap.get(l).compareTo(mHeap.get(l+1)); if(l < end && cmp<0) l++; cmp = tmp.compareTo(mHeap.get(l)); if(cmp >= 0) break; else { mHeap.set(c, mHeap.get(l)); c = l; l = 2*l + 1; } } mHeap.set(c, tmp); } public int remove(T data) { if(mHeap.isEmpty() == true) return -1; int index = mHeap.indexOf(data); if (index==-1) return -1; int size = mHeap.size(); mHeap.set(index, mHeap.get(size-1)); mHeap.remove(size - 1); if (mHeap.size() > 1) filterdown(index, mHeap.size()-1); return 0; } protected void filterup(int start) { int c = start; int p = (c-1)/2; T tmp = mHeap.get(c); while(c > 0) { int cmp = mHeap.get(p).compareTo(tmp); if(cmp >= 0) break; else { mHeap.set(c, mHeap.get(p)); c = p; p = (p-1)/2; } } mHeap.set(c, tmp); } public void insert(T data) { int size = mHeap.size(); mHeap.add(data); filterup(size); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i=0; i<mHeap.size(); i++) sb.append(mHeap.get(i) +" "); return sb.toString(); } public static void main(String[] args) { int i; int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80}; MaxHeap<Integer> tree=new MaxHeap<Integer>(); System.out.printf("== 依次添加: "); for(i=0; i<a.length; i++) { System.out.printf("%d ", a[i]); tree.insert(a[i]); } System.out.printf("\n== 最 大 堆: %s", tree); i=85; tree.insert(i); System.out.printf("\n== 添加元素: %d", i); System.out.printf("\n== 最 大 堆: %s", tree); i=90; tree.remove(i); System.out.printf("\n== 删除元素: %d", i); System.out.printf("\n== 最 大 堆: %s", tree); System.out.printf("\n"); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
二叉堆(最小堆)的实现文件
public class MinHeap<T extends Comparable<T>> { private List<T> mHeap; public MinHeap() { this.mHeap = new ArrayList<T>(); } protected void filterdown(int start, int end) { int c = start; int l = 2*c + 1; T tmp = mHeap.get(c); while(l <= end) { int cmp = mHeap.get(l).compareTo(mHeap.get(l+1)); if(l < end && cmp>0) l++; cmp = tmp.compareTo(mHeap.get(l)); if(cmp <= 0) break; else { mHeap.set(c, mHeap.get(l)); c = l; l = 2*l + 1; } } mHeap.set(c, tmp); } public int remove(T data) { if(mHeap.isEmpty() == true) return -1; int index = mHeap.indexOf(data); if (index==-1) return -1; int size = mHeap.size(); mHeap.set(index, mHeap.get(size-1)); mHeap.remove(size - 1); if (mHeap.size() > 1) filterdown(index, mHeap.size()-1); return 0; } protected void filterup(int start) { int c = start; int p = (c-1)/2; T tmp = mHeap.get(c); while(c > 0) { int cmp = mHeap.get(p).compareTo(tmp); if(cmp <= 0) break; else { mHeap.set(c, mHeap.get(p)); c = p; p = (p-1)/2; } } mHeap.set(c, tmp); } public void insert(T data) { int size = mHeap.size(); mHeap.add(data); filterup(size); } public String toString() { StringBuilder sb = new StringBuilder(); for (int i=0; i<mHeap.size(); i++) sb.append(mHeap.get(i) +" "); return sb.toString(); } public static void main(String[] args) { int i; int a[] = {80, 40, 30, 60, 90, 70, 10, 50, 20}; MinHeap<Integer> tree=new MinHeap<Integer>(); System.out.printf("== 依次添加: "); for(i=0; i<a.length; i++) { System.out.printf("%d ", a[i]); tree.insert(a[i]); } System.out.printf("\n== 最 小 堆: %s", tree); i=15; tree.insert(i); System.out.printf("\n== 添加元素: %d", i); System.out.printf("\n== 最 小 堆: %s", tree); i=10; tree.remove(i); System.out.printf("\n== 删除元素: %d", i); System.out.printf("\n== 最 小 堆: %s", tree); System.out.printf("\n"); }}