当前位置:网站首页>堆(優先級隊列)
堆(優先級隊列)
2022-07-02 12:07:00 【菜菜不恰菜】

目錄
🥬堆的性質

總結:一顆完全二叉樹以層序遍曆方式放入數組中存儲,這種方式的主要用法就是堆的錶示。
🥬堆的分類


🥬堆的向下調整
現在有一個數組,邏輯上是完全二叉樹,我們通過從根節點開始的向下調整算法可以把它調整成一個小堆或者大堆。向下調整算法有一個前提:左右子樹必須是一個堆,才能調整。
以小堆為例:
1、先讓左右孩子結點比較,取最小值。
2、用較小的那個孩子結點與父親節點比較,如果孩子結點<父親節點,交換,反之,不交換。
3、循環往複,如果孩子結點的下標越界,則說明已經到了最後,就結束。

代碼示例:
//parent: 每棵樹的根節點
//len: 每棵樹的調整的結束比特置
public void shiftDown(int parent,int len){
int child=parent*2+1; //因為堆是完全二叉樹,沒有左孩子就一定沒有右孩子,所以最起碼是有左孩子的,至少有1個孩子
while(child<len){
if(child+1<len && elem[child]<elem[child+1]){
child++;//兩孩子結點比較取較小值
}
if(elem[child]<elem[parent]){
int tmp=elem[parent];
elem[parent]=elem[child];
elem[child]=tmp;
parent=child;
child=parent*2+1;
}else{
break;
}
}
}🥬堆的建立
public void creatHeap(int[] arr){
for(int i=0;i<arr.length;i++){
elem[i]=arr[i];
useSize++;
}
for(int parent=(useSize-1-1)/2;parent>=0;parent--){//數組下標從0開始
shiftDown(parent,useSize);
}
}建堆的空間複雜度為O(N),因為堆為一棵完全二叉樹,滿二叉樹也是一種完全二叉樹,我們用滿二叉樹(最壞情况下)來證明。

🥬堆得向上調整
現在有一個堆,我們需要在堆的末尾插入數據,再對其進行調整,使其仍然保持堆的結構,這就是向上調整。
以大堆為例:

代碼示例:
public void shiftup(int child){
int parent=(child-1)/2;
while(child>0){
if(elem[child]>elem[parent]){
int tmp=elem[parent];
elem[parent]=elem[child];
elem[child]=tmp;
child=parent;
parent=(child-1)/2;
}else{
break;
}
}
}🥬堆的常用操作
入隊列
往堆裏面加入元素,就是往最後一個比特置加入,然後在進行向上調整。
public boolean isFull(){
return elem.length==useSize;
}
public void offer(int val){
if(isFull()){
elem= Arrays.copyOf(elem,2*elem.length);//擴容
}
elem[useSize++]=val;
shiftup(useSize-1);
}出隊列
把堆裏元素删除,就把堆頂元素和最後一個元素交換,然後向整個數組大小减一,最後向下調整,就删除了棧頂元素。
public boolean isEmpty(){
return useSize==0;
}
public int poll(){
if(isEmpty()){
throw new RuntimeException("優先級隊列為空");
}
int tmp=elem[0];
elem[0]=elem[useSize-1];
elem[useSize-1]=tmp;
useSize--;
shiftDown(0,useSize);
return tmp;
}獲取隊首元素
public int peek() {
if (isEmpty()) {
throw new RuntimeException("優先級隊列為空");
}
return elem[0];
}🥬TopK 問題
給你6個數據,求前3個最大數據。這時候我們用堆怎麼做的?
解題思路:
1、如果求前K個最大的元素,要建一個小根堆。
2、如果求前K個最小的元素,要建一個大根堆。
3、第K大的元素。建一個小堆,堆頂元素就是第K大的元素。
4、第K小的元素。建一個大堆,堆頂元素就是第K大的元素。
舉個例子:求前n個最大數據

代碼示例:
public static int[] topK(int[] array,int k){
//創建一個大小為K的小根堆
PriorityQueue<Integer> minHeap=new PriorityQueue<>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
//遍曆數組中元素,將前k個元素放入隊列中
for(int i=0;i<array.length;i++){
if(minHeap.size()<k){
minHeap.offer(array[i]);
}else{
//從k+1個元素開始,分別和堆頂元素比較
int top=minHeap.peek();
if(array[i]>top){
//先彈出後存入
minHeap.poll();
minHeap.offer(array[i]);
}
}
}
//將堆中元素放入數組中
int[] tmp=new int[k];
for(int i=0;i< tmp.length;i++){
int top=minHeap.poll();
tmp[i]=top;
}
return tmp;
}
public static void main(String[] args) {
int[] array={12,8,23,6,35,22};
int[] tmp=topK(array,3);
System.out.println(Arrays.toString(tmp));
}結果:

數組排序
再者說如果要對一個數組進行從小到大排序,要借助大根堆還是小根堆呢?
---->大根堆

代碼示例:
public void heapSort(){
int end=useSize-1;
while(end>0){
int tmp=elem[0];
elem[0]=elem[end];
elem[end]=tmp;
shiftDown(0,end);//假設這裏向下調整為大根堆
end--;
}
}🥬小結
以上就是今天的內容了,有什麼問題可以在評論區留言

边栏推荐
- Log4j2
- Natural language processing series (II) -- building character level language model using RNN
- Repeat, tile and repeat in pytorch_ The difference between interleave
- How to Visualize Missing Data in R using a Heatmap
- lombok常用注解
- 自然语言处理系列(三)——LSTM
- Full link voltage measurement
- 基于Arduino和ESP8266的Blink代码运行成功(包含错误分析)
- b格高且好看的代码片段分享图片生成
- easyExcel和lombok注解以及swagger常用注解
猜你喜欢
随机推荐
Test shift left and right
通讯录的实现(文件版本)
基于Arduino和ESP8266的连接手机热点实验(成功)
YYGH-BUG-05
BEAUTIFUL GGPLOT VENN DIAGRAM WITH R
(C语言)输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
Leetcode922 sort array by parity II
堆(优先级队列)
动态内存(进阶四)
Leetcode topic [array] -540- single element in an ordered array
Leetcode14 longest public prefix
PyTorch搭建LSTM实现服装分类(FashionMNIST)
Fabric. JS 3 APIs to set canvas width and height
初始JDBC 编程
子线程获取Request
Dynamic memory (advanced 4)
求16以内正整数的阶乘,也就是n的阶层(0=<n<=16)。输入1111退出。
SSH automatically disconnects (pretends to be dead) after a period of no operation
FLESH-DECT(MedIA 2021)——一个material decomposition的观点
MSI announced that its motherboard products will cancel all paper accessories









