Java中如何實現(xiàn)堆排序

今天就跟大家聊聊有關(guān)Java中如何實現(xiàn)堆排序,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

成都創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的臺山網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

堆排序是一種樹形選擇排序方法,它的特點是:在排序的過程中,將array[0,...,n-1]看成是一顆完全二叉樹的順序存儲結(jié)構(gòu),利用完全二叉樹中雙親節(jié)點和孩子結(jié)點之間的內(nèi)在關(guān)系,在當前無序區(qū)中選擇關(guān)鍵字最大(最?。┑脑亍?/p>

1. 若array[0,...,n-1]表示一顆完全二叉樹的順序存儲模式,則雙親節(jié)點指針和孩子結(jié)點指針之間的內(nèi)在關(guān)系如下:

任意一節(jié)點指針 i:父節(jié)點:i==0 ? null : (i-1)/2

左孩子:2*i + 1

右孩子:2*i + 2

2. 堆的定義:n個關(guān)鍵字序列array[0,...,n-1],當且僅當滿足下列要求:(0 <= i <= (n-1)/2)

① array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 稱為小根堆;

② array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 稱為大根堆;

3. 建立大根堆:

n個節(jié)點的完全二叉樹array[0,...,n-1],最后一個節(jié)點n-1是第(n-1-1)/2個節(jié)點的孩子。對第(n-1-1)/2個節(jié)點為根的子樹調(diào)整,使該子樹稱為堆。

對于大根堆,調(diào)整方法為:若【根節(jié)點的關(guān)鍵字】小于【左右子女中關(guān)鍵字較大者】,則交換。

之后向前依次對各節(jié)點((n-2)/2 - 1)~ 0為根的子樹進行調(diào)整,看該節(jié)點值是否大于其左右子節(jié)點的值,若不是,將左右子節(jié)點中較大值與之交換,交換后可能會破壞下一級堆,于是繼續(xù)采用上述方法構(gòu)建下一級的堆,直到以該節(jié)點為根的子樹構(gòu)成堆為止。

反復利用上述調(diào)整堆的方法建堆,直到根節(jié)點。

4.堆排序:(大根堆)

①將存放在array[0,...,n-1]中的n個元素建成初始堆;

②將堆頂元素與堆底元素進行交換,則序列的最大值即已放到正確的位置;

③但此時堆被破壞,將堆頂元素向下調(diào)整使其繼續(xù)保持大根堆的性質(zhì),再重復第②③步,直到堆中僅剩下一個元素為止。

堆排序算法的性能分析:

空間復雜度:o(1);

時間復雜度:建堆:o(n),每次調(diào)整o(log n),故最好、最壞、平均情況下:o(n*logn);

穩(wěn)定性:不穩(wěn)定

建立大根堆的方法:

//構(gòu)建大根堆:將array看成完全二叉樹的順序存儲結(jié)構(gòu)  private int[] buildMaxHeap(int[] array){    //從最后一個節(jié)點array.length-1的父節(jié)點(array.length-1-1)/2開始,直到根節(jié)點0,反復調(diào)整堆    for(int i=(array.length-2)/2;i>=0;i--){       adjustDownToUp(array, i,array.length);    }    return array;  }    //將元素array[k]自下往上逐步調(diào)整樹形結(jié)構(gòu)  private void adjustDownToUp(int[] array,int k,int length){    int temp = array[k];      for(int i=2*k+1; i<length-1; i=2*i+1){  //i為初始化為節(jié)點k的左孩子,沿節(jié)點較大的子節(jié)點向下調(diào)整      if(i<length && array[i]<array[i+1]){ //取節(jié)點較大的子節(jié)點的下標        i++;  //如果節(jié)點的右孩子>左孩子,則取右孩子節(jié)點的下標      }      if(temp>=array[i]){ //根節(jié)點 >=左右子女中關(guān)鍵字較大者,調(diào)整結(jié)束        break;      }else{  //根節(jié)點 <左右子女中關(guān)鍵字較大者        array[k] = array[i]; //將左右子結(jié)點中較大值array[i]調(diào)整到雙親節(jié)點上        k = i; //【關(guān)鍵】修改k值,以便繼續(xù)向下調(diào)整      }    }    array[k] = temp; //被調(diào)整的結(jié)點的值放人最終位置  }

堆排序:

//堆排序  public int[] heapSort(int[] array){    array = buildMaxHeap(array); //初始建堆,array[0]為第一趟值最大的元素    for(int i=array.length-1;i>1;i--){       int temp = array[0]; //將堆頂元素和堆低元素交換,即得到當前最大元素正確的排序位置      array[0] = array[i];      array[i] = temp;      adjustDownToUp(array, 0,i); //整理,將剩余的元素整理成堆    }    return array;  }

刪除堆頂元素(即序列中的最大值):先將堆的最后一個元素與堆頂元素交換,由于此時堆的性質(zhì)被破壞,需對此時的根節(jié)點進行向下調(diào)整操作。

//刪除堆頂元素操作  public int[] deleteMax(int[] array){    //將堆的最后一個元素與堆頂元素交換,堆底元素值設(shè)為-99999    array[0] = array[array.length-1];    array[array.length-1] = -99999;    //對此時的根節(jié)點進行向下調(diào)整    adjustDownToUp(array, 0, array.length);    return array;  }

對堆的插入操作:先將新節(jié)點放在堆的末端,再對這個新節(jié)點執(zhí)行向上調(diào)整操作。

假設(shè)數(shù)組的最后一個元素array[array.length-1]為空,新插入的結(jié)點初始時放置在此處。

//插入操作:向大根堆array中插入數(shù)據(jù)data  public int[] insertData(int[] array, int data){    array[array.length-1] = data; //將新節(jié)點放在堆的末端    int k = array.length-1; //需要調(diào)整的節(jié)點    int parent = (k-1)/2;  //雙親節(jié)點    while(parent >=0 && data>array[parent]){      array[k] = array[parent]; //雙親節(jié)點下調(diào)      k = parent;      if(parent != 0){        parent = (parent-1)/2; //繼續(xù)向上比較      }else{ //根節(jié)點已調(diào)整完畢,跳出循環(huán)        break;      }    }    array[k] = data; //將插入的結(jié)點放到正確的位置    return array;  }

測試:

public void toString(int[] array){    for(int i:array){      System.out.print(i+" ");    }  }    public static void main(String args[]){    HeapSort hs = new HeapSort();    int[] array = {87,45,78,32,17,65,53,9,122};    System.out.print("構(gòu)建大根堆:");    hs.toString(hs.buildMaxHeap(array));    System.out.print("\n"+"刪除堆頂元素:");    hs.toString(hs.deleteMax(array));    System.out.print("\n"+"插入元素63:");    hs.toString(hs.insertData(array, 63));    System.out.print("\n"+"大根堆排序:");    hs.toString(hs.heapSort(array));    }

看完上述內(nèi)容,你們對Java中如何實現(xiàn)堆排序有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

分享名稱:Java中如何實現(xiàn)堆排序
文章鏈接:http://muchs.cn/article32/ppjspc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、搜索引擎優(yōu)化標簽優(yōu)化、品牌網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、品牌網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司