堆和树
数据结构中有两个概念很相似,比如树的数据结构,还有一种结构叫“堆”,堆是一种特殊的树,min heap是小顶堆;max heap是大顶堆
树和堆主要区别
- 树分左右,堆一般不分左右
- 用途不同,堆主要用于优先队列;而树的用途更加广泛
堆=完全二叉树+排序的规则
堆和树有什么区别?堆为什么要叫堆,不叫树呢?
如下用小顶堆(比起一般的数组)速度提升了5倍!!!排名从击败5%上升到击败70%!!!
class KthLargest {
//小顶堆
PriorityQueue<Integer> pq;
int k;
public KthLargest(int k, int[] nums) {
this.k = k;
pq = new PriorityQueue<>(k);
for (int i=0; i<nums.length; i++) {
this.add(nums[i]);
}
}
public int add(int val) {
if (pq.size() < k) {
pq.add(val);
} else {
if (val > pq.peek()) {
pq.poll();
pq.add(val);
}
}
return pq.peek();
}
}
/**
class KthLargest_Backup {
//这个版本的很慢,beats 6%,因为每次都排序了,所以要试试小顶堆
List<Integer> list = new ArrayList<>();
int k;
public KthLargest(int k, int[] nums) {
this.k = k;
for (int i=0; i<nums.length; i++) {
list.add(nums[i]);
}
Collections.sort(list);
}
public int add(int val) {
int pos=0; //后续考虑换成二分查找法
for (int i=0; i<list.size(); i++) {
if (val > list.get(i)) pos++;
else break;
}
list.add(pos, val);
//for (int i=0; i<list.size(); i++) System.out.println(list.get(i));
return list.get(list.size()-k);
}
}
**/
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/
PriorityQueue天生是小顶堆,那么如果我要大顶堆怎么办?
// 默认实现了一个最小堆。
Queue<Integer> priorityQueue = new PriorityQueue<>();
// 实现最大堆
Queue<ListNode> priorityQueue = new PriorityQueue<ListNode>(
lists.size(),
new Comparator<ListNode>(){
@Override
public int compare(ListNode o1, ListNode o2) { return o1.val-o2.val; }
}
);
手动翻转大顶堆
package com.zzz.life;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@SpringBootApplication
public class LifeApplication {
public static void main(String[] args) {
//SpringApplication.run(LifeApplication.class, args);
System.out.println("begin...");
Node root = new Node(1);
root.left = new Node(3);
root.right = new Node(4);
root.left.left = new Node(5);
root.left.right = new Node(7);
root.right.left = new Node(2);
root.right.right = new Node(6);
root.left.left.left = new Node(8);
root.left.left.right = new Node(0);
LifeApplication app = new LifeApplication();
List<Integer> traversal = app.postorderTranversal(root);
for (Integer item: traversal) {
System.out.print(item+" ");
}
System.out.println("遍历完成");
List<List<Integer>> level = app.levelOrder(root);
for (List<Integer> item: level) {
System.out.println(item);
}
List<Node> trunk = app.trunkNodes(root);
for (Node item: trunk) {
System.out.print(item.val + " : ");
}
System.out.println("最终----------");
app.shiftDD(root);
List<List<Integer>> level2 = app.levelOrder(root);
for (List<Integer> item: level2) {
System.out.println(item);
}
}
public void shiftDD(Node root) {
//将这个完全二叉树变为大顶堆
if (root == null) return ;
//找到这树中最后一个非叶子节点
List<Node> ret = trunkNodes(root);
for (int i=0; i< ret.size(); i++) {
Node tmp = ret.get(i);
int cur = tmp.val;
int left = tmp.left!=null? tmp.left.val:-1;
int right = tmp.right!=null? tmp.right.val:-1;
int maxchild = left > right? left: right;
//执行交换
if (maxchild > cur) {
if (maxchild == left) {
tmp.val ^= tmp.left.val;
tmp.left.val ^= tmp.val;
tmp.val ^= tmp.left.val;
} else {
tmp.val ^= tmp.right.val;
tmp.right.val ^= tmp.val;
tmp.val ^= tmp.right.val;
}
}
//整理子树
shiftDD(tmp.left);
shiftDD(tmp.right);
}
}
public List<Integer> preorderTranversal(Node root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
list.add(root.val);
list.addAll(preorderTranversal(root.left));
list.addAll(preorderTranversal(root.right));
return list;
}
public List<Integer> postorderTranversal(Node root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
list.addAll(postorderTranversal(root.left));
list.addAll(postorderTranversal(root.right));
list.add(root.val);
return list;
}
public List<Node> trunkNodes(Node root) {
List<Node> list = new ArrayList<>();
if (root == null) return list;
LinkedList<Node> current = new LinkedList<>();
current.add(root);
boolean hasNext = true;
while (hasNext) {
int size = current.size();
for (int i=0; i<size; i++) {
Node tmp = current.removeFirst();
list.add(tmp);
if (tmp.left != null && (tmp.left.left!=null && tmp.left.right!=null)) current.addLast(tmp.left);
if (tmp.right != null && (tmp.right.left!=null && tmp.right.right!=null)) current.addLast(tmp.right);
}
if (current.size()==0) hasNext=false;
}
Collections.reverse(list);
return list;
}
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
boolean hasNext = false;
if (root != null) hasNext =true;
LinkedList<Node> current = new LinkedList<>();
current.add(root);
while (hasNext) {
int size = current.size();
List<Integer> list = new ArrayList<>();
for (int i=0; i<size; i++) {
Node tmp = current.removeFirst();
list.add(tmp.val);
if (tmp.left != null) current.addLast(tmp.left);
if (tmp.right != null) current.addLast(tmp.right);
}
lists.add(list);
if (current.size()==0) hasNext=false;
}
return lists;
}
}
class Node {
int val;
Node left;
Node right;
Node(int val) {
this.val = val;
}
}