目錄
堆的性質
堆的分類
堆的向下調整
堆的建立
堆得向上調整
堆的常用操作
#進入佇列
出佇列
取得隊首元素
TopK 問題
範例
陣列排序
首頁 Java java教程 Java資料結構之堆怎麼建立

Java資料結構之堆怎麼建立

May 15, 2023 pm 08:01 PM
java

堆的性質

堆邏輯上是一棵完全二元樹,堆物理上是保存在陣列中 。

Java資料結構之堆怎麼建立

總結:一顆完全二元樹以層序遍歷方式放入數組中存儲,這種方式的主要用法就是堆的表示。

且如果已知父親(parent) 的下標,

則: 左孩子(left) 下標= 2 * parent 1;

右孩子(right)下標= 2 * parent 2;

已知孩子(不區分左右)(child)下標,則:

雙親(parent) 下標= (child - 1) / 2 ;

堆的分類

大堆:根節點大於左右兩個子節點的完全二元樹(父親節點大於其子節點),叫做大堆,或大根堆,或最大堆。

Java資料結構之堆怎麼建立

小堆:根節點小於左右兩個子節點的完全二元樹叫 小堆(父親節點小於其子節點),或小根堆,或最小堆。

Java資料結構之堆怎麼建立

堆的向下調整

現在有一個數組,邏輯上是完全二元樹,我們透過從根節點開始的向下調整演算法可以把它調整成一個小堆或大堆。向下調整演算法有一個前提:左右子樹必須是一個堆,才能調整。

以小堆為例:

1、先讓左右孩子結點比較,取最小值。

2、用較小的那個孩子結點與父親節點比較,如果孩子結點

3、循環往復,如果孩子結點的下標越界,則表示已經到了最後,就結束。

Java資料結構之堆怎麼建立

程式碼範例:

 //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),因為堆為一棵完全二元樹,滿二叉樹也是一種完全二元樹,我們用滿二叉樹(最壞情況下)來證明。

Java資料結構之堆怎麼建立

堆得向上調整

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

以大堆為例:

Java資料結構之堆怎麼建立

程式碼範例:

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個最大資料

Java資料結構之堆怎麼建立

#程式碼範例:

 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));
    }
登入後複製

結果:

Java資料結構之堆怎麼建立

陣列排序

再者說如果要對一個陣列進行從小到大排序,要藉助大根堆還是小根堆呢?

---->大根堆

Java資料結構之堆怎麼建立

程式碼範例:

  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--;
        }
    }
登入後複製

以上是Java資料結構之堆怎麼建立的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP與Python:核心功能 PHP與Python:核心功能 Apr 13, 2025 am 12:16 AM

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

PHP的影響:網絡開發及以後 PHP的影響:網絡開發及以後 Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

PHP:許多網站的基礎 PHP:許多網站的基礎 Apr 13, 2025 am 12:07 AM

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。

See all articles