java数据结构:堆,PriorityQueue小顶堆,大顶堆翻转(亲手实战)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wxid2798226/article/details/89740479

堆和树

数据结构中有两个概念很相似,比如树的数据结构,还有一种结构叫“堆”,堆是一种特殊的树,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;
    }
}

猜你喜欢

转载自blog.csdn.net/wxid2798226/article/details/89740479