本节目标
目录
一 二叉树的顺序存储
1.1 存储方式
使用数组保护二叉树结构,方式即将二叉树用层序遍历方式入数组中
一般只适合表示完全二叉树,因为完全二叉树会有空间的浪费
这种方式的主要用法就是堆的表示
1.2 下标关系
已知双亲(parent)的小标,则
左孩子 (left)下标=2*parent+1
右孩子(right) 下标=2*parent+2
二 堆(heap)
2.1 概念
1.逻辑上是一颗完全二叉树
2.堆物理上是保存在数组中
3.满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆。
4.反之,则是小堆,或者小根堆,或者最小堆
5.堆的基本作用是,快速找集合中的最值
2.2 操作-向下调整
前提:左右子树必须已经是一个堆,才能调整
说明
1.array 代表村塾堆的数组
2.size 代表数组中呗视为堆数据的个数
3.index 代表要调整位置的下标
4.left 代表index左孩子下标
5.right 代表index右孩子的下标
6.min 代表 index的最小值孩子的下标
过程(以小堆为列)
public static void shiftDown(int[] array ,int size,int index){
int left = 2 * index + 1;
while (left < size){
int min = left;
int right = 2 * index + 2;
if (right < size ) {
if (array[right] < array[left]){
min = right;
}
}
if (array[index] <= array[min]){
break;
}
int t = array[index];
array[index] = array[min];
array[min] = t;
index = min;
left = 2 * index + 1;
}
}
2.3 操作-建堆
下面我们给出一个数组,这个数组逻辑上可以看做一棵完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数第一个非叶子结点的子树开始调整,一直一澳洲到根节点的树,就可以调整成堆。
//建堆前
int [] array = { 1,5,3,8,7,6};
//建堆后
int [] array = { 8,7,6,5,1,3};
时间复杂度分析:O(n*log(n))
(72 封私信 / 80 条消息) 堆排序中建堆过程时间复杂度O(n)怎么来的? - 知乎 (zhihu.com)
public static void createHeap(int[] array, int size) {
for (int i = (size - 1 - 1) / 2; i >= 0; i--) {
shiftDown(array,size,i);
}
}
三 堆的应用-优先级队列
3.1 概念
很多应用中,我们通常需要按照有心计对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个列子就是,你在打游戏的时候女朋友来电话了,你就需要先接电话,要不然。。。
在这种情况下,我们的数据结构应提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。
3.2 内部原理
优先级队列的实现方式有很多,但最常见的是使用堆来构建
3.3 操作-入队列
1.首先按尾插方式入数组
2.比较其和其双亲的值的大小,如果双亲的值大,则满足堆的性质,插入结束。
3.否则,交换其和双亲位置的值,重新进行步骤2.3
4.直到根结点
3.4操作-出队列
3.4 返回队首元素
3.5 代码
3.6 代码
3.7 Java 中的优先级队列
错误处理 | 抛出异常 | 返回特殊值 |
入队列 | add(e) | offer(e) |
出队列 | remove() | poll() |
队首元素 | element() | peel() |
四 堆的其他应用-TopK问题
画外音:除非校招,我在面试过程中从不问TopK这个问题,默认大家都知道。
(63条消息) 拜托,面试别再问我TopK了!!!_架构师之路_的博客-CSDN博客
五 面试题
373. 查找和最小的 K 对数字 - 力扣(LeetCode)
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < Math.min(nums1.length, k); i++) {
for (int j = 0; j < Math.min(nums2.length, k); j++) {
ans.add(Arrays.asList(nums1[i], nums2[j]));
}
}
ans.sort(Comparator.comparingInt(x -> (x.get(0) + x.get(1))));
return ans.subList(0, Math.min(ans.size(), k));
}
}