抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

堆的定义

堆在逻辑上是一种完全二叉树,物理结构上是一维数组,按照根节点大小分为最大堆和最小堆,如下图。
最小堆:所有节点的左右孩子节点都大于或者等于父节点
最大堆:所有节点的左右孩子节点都小于或者等于父节点

补充:完全二叉树的性质
如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(0<=i<=n)有(注意i的取值)
1.如果i=0,则节点是二叉树的根,无双亲,如果i>0,则其双亲节点为[i/2],向下取整
2.如果2i+1>n那么节点i没有左孩子,否则其左孩子为2i+1
3.如果2i+2>n那么节点没有右孩子,否则右孩子为2i+2

堆的特性

  1. 堆是弱序的,所以遍历堆是很难的,基本堆都不支持遍历。
  2. 堆一般都是用来实现优先级队列,由它实现的优先级队列的插入和删除的时间复杂度都是O(logn)。

堆的操作

插入

把插入的节点放在数组尾部,然后向上筛选。

upload successful

移除

把根节点移除,然后向下筛选。

  1. 移走根

  2. 把最后一个节点移动到根的位置

  3. 一直向下筛选这个节点,直到它在一个大于它的节点之下,小于它的节点之上为止。

代码示例

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
package com.czj.example01;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

/**
* 创建在 2020/4/30 23:17
*/
public class Heap<T extends Comparable<? super T>>{


private final Object[] items;

private Comparator comparable;

private int currentIndex = 0;
private static final int DEFAULT_CAPACITY = 10;
public Heap(){
this(DEFAULT_CAPACITY);
}

public Heap(int capacity){
this(capacity,null);
}

public Heap(int capacity,Comparator comparable){
this.items = new Object[capacity];
this.comparable = comparable;
}

/**
* 添加元素,成功返回true,否则返回false
* @author czj
* @date 2020/4/30 23:29
* @param [item]
* @return boolean
*/
public boolean add(T item){
//堆已满返回false
if (isFull()){
return false;
}
items[currentIndex] = item;
adjustUp();
currentIndex++;
return true;
}

public boolean isFull(){
return items.length == currentIndex;
}

public boolean isEmpty(){
return items.length==0;
}
/**
* @author czj
* 将新增的元素向上调整到合适的位置
* @date 2020/4/30 23:33
* @param []
* @return void
*/
public void adjustUp(){
T temp=null;
T item=null;
T parentItem=null;
int parentIdx = (currentIndex-1)/2;
int nowIdx=currentIndex;
int num = -1;
while (nowIdx>0){
item = (T) items[nowIdx];
parentItem = (T) items[parentIdx];
if (comparable==null){
num = item.compareTo(parentItem);
}else {
num = comparable.compare(item,parentItem);
}
if (num<0){
break;
}
items[nowIdx]=parentItem;
items[parentIdx]=item;
nowIdx=parentIdx;
parentIdx=(nowIdx-1)/2;
}
}

/**
* @author czj
* 向下调整
* @date 2020/5/2 15:31
* @param []
* @return void
*/
public void adjustDown(){
T item = (T) items[0];
int bigIdx=0,index=0;
int leftIdx=0,rightIdx=0;
T leftItem=null,rightItem=null;
int num=0;
while (index<currentIndex/2){
leftIdx = 2*index+1;
rightIdx = leftIdx+1;
if (rightIdx<currentIndex) {
leftItem = (T) items[leftIdx];
rightItem = (T) items[rightIdx];
if (comparable == null) {
bigIdx = leftItem.compareTo(rightItem)>=0?leftIdx:rightIdx;
} else {
bigIdx = comparable.compare(leftItem, rightItem)>=0?leftIdx:rightIdx;
}
}else {
bigIdx = leftIdx;
}
items[index]=items[bigIdx];
index=bigIdx;
}
items[index]=item;
}

public T remove(){
if (isEmpty()){
return null;
}
T item = (T) items[0];
items[0]=items[--currentIndex];
adjustDown();
return item;
}

public int size(){
return items.length;
}
}