- 二叉树的顺序存储
1.1堆的表示:使用数组保存二叉树结构,二叉树用层序遍历方式放入数组中。(一般只适合表示完全二叉树,因为非完全二叉树会有空间的浪费。)(下图是一个完全二叉树)
1.2.下标关系
left = 2 * parent +1
right = 2 * parent +2
parent = (child - 1)/2
2.堆(heap)
2.1概念:
堆逻辑上是一棵完全二叉树
堆物理上是保存在数组中
满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆
反之,则是小堆,或者小根堆,或者最小堆(示例如下)
堆的基本作用是,快速找集合中的最值
2.2向下调整操作
public static void shiftDown(int[] array,int size,int index) {
while (true) {
//1.判断是否为叶子节点
int left = index * 2 + 1;
if(left >= size) {
return;
}
//2.找左右孩子中最小的孩子
int min = left;
int right = left + 1;
if(right < size && array[right] < array[left]) {
min = right;
}
//判断小孩子和 index 位置的值的大小
if(array[index] <= array[min]) {
return;
}
//3.交换
int t = array[min];
array[min] = array[index];
array[index] = t;
//4.继续比较
index = min;
}
}
时间复杂度为O(log(n))
2.3建堆操作如下:
public static void createHeap(int[] array,int size) {
for (int i = (size -1 - 1) / 2; i >= 0 ; i--) {
shiftDown(array,size,i);
}
}
3.堆的应用——优先级队列
3.1入队列操作
public void adjustUp(int[] array,int size,int index) {
while (true) {
//1.判断 index 是不是树的根
if(index == 0) {
break;
}
//2.跟父节点比较 大于父节点的值 退出
int parent = (index - 1) / 2;
if(array[parent] <= array[index]) {
break;
}
//交换父节点和index的值
int t = array[parent];
array[parent] = array[index];
array[index] = t;
//3.把父节点视为孩子继续比价
index = parent;
//4.到顶,退出
}
}
3.2 java中的优先级队列
PriorityQueue implements Queue
抛出异常 | 返回特殊值 |
---|---|
add(e) | offer(e) |
remove() | poll() |
element() | peek() |
分别为入队列、出队列、队首元素的操作。
程序代码:
public class PriorityQueueDemo {
public static void main(String[] args) {
MyPriorityQueue queue = new MyPriorityQueue();
queue.add(3);
queue.add(5);
queue.add(2);
queue.add(7);
System.out.println(queue.remove());
}
}
public class MyPriorityQueue {
private Integer[] array;
private int size;
public MyPriorityQueue() {
array = new Integer[100];
size = 0;
}
public Integer element() {
if(size == 0) {
throw new RuntimeException("空");
}
return array[0];
}
public Integer remove() {
if(size == 0) {
throw new RuntimeException("空");
}
int e = array[0];
array[0] = array[size - 1];
size--;
adjustDown(0);
return e;
}
public void add(Integer e) {
array[size] = e;
size++;
adjustUp(size-1);
}
public void adjustUp (int index) {
while (true) {
//1.判断 index 是不是树的根
if(index == 0) {
break;
}
//2.跟父节点比较 大于父节点的值 退出
int parent = (index - 1) / 2;
if(array[parent] <= array[index]) {
break;
}
//交换父节点和index的值
int t = array[parent];
array[parent] = array[index];
array[index] = t;
//3.把父节点视为孩子继续比价
index = parent;
//4.到顶,退出
}
}
private void adjustDown(int index) {
while (true) {
int left = index * 2 + 1;
if(left >= size) {
return;
}
int right = left + 1;
int min = left;
if(right < size && array[right] < array[left]) {
min = right;
}
if(array[index] <= array[min]) {
return;
}
int t = array[index];
array[index] = array[min];
array[min] = t;
index = min;
}
}
}
总之还是要多练习的呀!!!