Java實現堆的封裝,進行插入,調整,刪除堆頂以完成堆排序執行個體__Java

來源:互聯網
上載者:User

簡介

堆對於排序演算法是一個比較常用的資料結構,下面我就使用Java語言來實現這一演算法

首先,我們需要知道堆的資料結構的形式,其實就是一個特殊的二叉樹。但是這個二叉樹有一定的特點,除了是完全二叉樹以外,對於最大堆而言,堆頂元素的值是最大的,而且對於堆的每一個子樹也是一個小一號的最大堆;同樣對於最小堆,性質相反就可以了。

我以最大堆為例:
要實現堆的初始化操作,就是先按照給定的元素建立一棵完全二叉樹,然後從末尾節點進行不斷地調整的過程。調整的原則是:比較要進行放置的當前節點與其父節點的數值的大小,若要進行放置的當前節點的值小於其父節點,那麼當前節點所在位置符合最大堆的定義,要進行放置的當前節點放在此處是比較合適的;如果要進行放置的當前節點的值大於其父節點的值,那說明放在當前節點是不合適的,那麼就需要將當前節點的值與其父節點的值進行交換,然後原父節點變為新的要進行放置的當前節點。迴圈比較;終止條件就是當前節點沒有父節點,但此時的調整也許並沒有結束,我們只需要讓堆頂元素為要插入的值即可。至此,最大堆的插入和調整過程結束。
代碼如下:

public boolean insert(int x){        if(currentSize==MAXSIZE){            System.out.println("Sorry,this heap is full!");            return false;        }        //如果堆不滿的話        currentSize++;        int flag=currentSize-1;        while(flag>0){            int parent=(flag-1)/2;            if(heap[parent]>x){                heap[flag]=x;                return true;            }else{                heap[flag]=heap[parent];                flag=parent;            }        }        heap[0]=x;        return true;    }

siftDown過程:給定一個節點的位置,對其進行調整,使之符合最大堆的定義,這個過程就是我們要實現的過程。調整原則如下:
對於當前節點i而言,其孩子節點的下標滿足左節點為2*i+1,右節點為2*i+2;在進行調整的過程中,只需要比較當前節點與其子節點中最大的節點進行調整即可。具體的代碼邏輯可在代碼中看到:

public void siftDown(int flag){        int want=flag;        int x=heap[flag];        while(want<currentSize){            int lChild=2*want+1;            int rChild=2*want+2;            int MAXChildNumber;            if(lChild>currentSize){  //沒有孩子節點                heap[want]=x;            }else{                   //有兩個孩子節點                if(lChild<currentSize){                    MAXChildNumber=heap[lChild]>heap[rChild]?lChild:rChild;                }else{                    MAXChildNumber=lChild;                }                if(heap[MAXChildNumber]<x){                    heap[want]=x;return;                }else{                    heap[want]=heap[MAXChildNumber];                    want=MAXChildNumber;                }            }        }    }

堆頂元素的刪除,我們對堆的操作基本桑就是為了獲得這個堆的最值,那麼毫無疑問,堆頂元素就是我們要研究的對象。下面是代碼邏輯:

public int deleteTop(){        if(currentSize<0){            System.out.println("Sorry, this heap is empty!");            return -1;        }        int target=heap[0];        int substitute=heap[currentSize-1];        this.currentSize--;        heap[0]=substitute;        siftDown(0);        return target;    }

下面是詳細的代碼

package test.maxHeap;public class MaxHeap {    private int []heap ;    private int currentSize;    private static int MAXSIZE ;    public MaxHeap(int n){        heap=new int[n];        currentSize=0;        MAXSIZE=n;    }    public boolean insert(int x){        if(currentSize==MAXSIZE){            System.out.println("Sorry,this heap is full!");            return false;        }        //如果堆不滿的話        currentSize++;        int flag=currentSize-1;        while(flag>0){            int parent=(flag-1)/2;            if(heap[parent]>x){                heap[flag]=x;                return true;            }else{                heap[flag]=heap[parent];                flag=parent;            }        }        heap[0]=x;        return true;    }    public void siftDown(int flag){        int want=flag;        int x=heap[flag];        while(want<currentSize){            int lChild=2*want+1;            int rChild=2*want+2;            int MAXChildNumber;            if(lChild>currentSize){  //沒有孩子節點                heap[want]=x;            }else{                   //有兩個孩子節點                if(lChild<currentSize){                    MAXChildNumber=heap[lChild]>heap[rChild]?lChild:rChild;                }else{                    MAXChildNumber=lChild;                }                if(heap[MAXChildNumber]<x){                    heap[want]=x;return;                }else{                    heap[want]=heap[MAXChildNumber];                    want=MAXChildNumber;                }            }        }    }    public int deleteTop(){        if(currentSize<0){            System.out.println("Sorry, this heap is empty!");            return -1;        }        int target=heap[0];        int substitute=heap[currentSize-1];        this.currentSize--;        heap[0]=substitute;        siftDown(0);        return target;    }}

好了,編碼已經完成。下面我們就要檢驗一下是否正確吧。

public class MaxHeapTest {    public static void main(String []args){        MaxHeap maxHeap=new MaxHeap(7);        for(int i=1;i<=7;i++){            maxHeap.insert(i);        }        for(int i=0;i<7;i++){            System.out.print(maxHeap.deleteTop()+"   ");        }        System.out.println("\n");    }}

接下來是程式的運行結果:

7   6   5   4   3   2   1   //可見,對於最大堆,刪除堆頂的操作實際上就是完成了對堆的排序任務,也證明了我們的代碼是正確的

總結:
堆的操作很重要,我們更要學會對於堆的應用,這樣的資料結構才能使得程式的運行更加的高效和流暢。對於最小堆,我們只需要在插入方法,sift方法內稍加修改即可(也就是將值的代銷變換關係進行調整)。這樣就同樣能實現最小堆的建立和相關的操作了。
代碼中可能存在不太恰當地地方,希望大家予以批評指正,期待與你們共同進步。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.