最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 堆排序?qū)嵗?大頂堆、小頂堆)

 更新時(shí)間:2017年12月04日 10:17:09   作者:Sun_Ru  
下面小編就為大家分享一篇Java 堆排序?qū)嵗?大頂堆、小頂堆),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧

堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。堆積是一個(gè)近似完全二叉樹的結(jié)構(gòu),并同時(shí)滿足堆積的性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。

堆排序的平均時(shí)間復(fù)雜度為Ο(nlogn) 。

算法步驟:

1. 創(chuàng)建一個(gè)堆H[0..n-1]

2. 把堆首(最大值)和堆尾互換

3. 把堆的尺寸縮小1,并調(diào)用shift_down(0),目的是把新的數(shù)組頂端數(shù)據(jù)調(diào)整到相應(yīng)位置

4. 重復(fù)步驟2,直到堆的尺寸為1

堆:

堆實(shí)際上是一棵完全二叉樹,其任何一非葉節(jié)點(diǎn)滿足性質(zhì): Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2] 即任何一非葉節(jié)點(diǎn)的關(guān)鍵字不大于或者不小于其左右孩子節(jié)點(diǎn)的關(guān)鍵字。 堆分為大頂堆和小頂堆,滿足Key[i]>=Key[2i+1]&&key>=key[2i+2]稱為大頂堆,滿足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]稱為小頂堆。由上述性質(zhì)可知大頂堆的堆頂?shù)年P(guān)鍵字肯定是所有關(guān)鍵字中最大的,小頂堆的堆頂?shù)年P(guān)鍵字是所有關(guān)鍵字中最小的。

堆排序思想:

利用大頂堆(小頂堆)堆頂記錄的是最大關(guān)鍵字(最小關(guān)鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。 其基本思想為(大頂堆): 1)將初始待排序關(guān)鍵字序列(R1,R2….Rn)構(gòu)建成大頂堆,此堆為初始的無序區(qū); 2)將堆頂元素R[1]與最后一個(gè)元素R[n]交換,此時(shí)得到新的無序區(qū)(R1,R2,……Rn-1)和新的有序區(qū)(Rn),且滿足R[1,2...n-1]<=R[n]; 3)由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對當(dāng)前無序區(qū)(R1,R2,……Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個(gè)元素交換,得到新的無序區(qū)(R1,R2….Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過程直到有序區(qū)的元素個(gè)數(shù)為n-1,則整個(gè)排序過程完成。 操作過程如下: 1)初始化堆:將R[1..n]構(gòu)造為堆; 2)將當(dāng)前無序區(qū)的堆頂元素R[1]同該區(qū)間的最后一個(gè)記錄交換,然后將新的無序區(qū)調(diào)整為新的堆。 因此對于堆排序,最重要的兩個(gè)操作就是構(gòu)造初始堆和調(diào)整堆,其實(shí)構(gòu)造初始堆事實(shí)上也是調(diào)整堆的過程,只不過構(gòu)造初始堆是對所有的非葉節(jié)點(diǎn)都進(jìn)行調(diào)整。

一個(gè)圖示實(shí)例

給定一個(gè)整形數(shù)組a[]={16,7,3,20,17,8},對其進(jìn)行堆排序。 首先根據(jù)該數(shù)組元素構(gòu)建一個(gè)完全二叉樹,得到

然后需要構(gòu)造初始堆,則從最后一個(gè)非葉節(jié)點(diǎn)開始調(diào)整,調(diào)整過程如下:

20和16交換后導(dǎo)致16不滿足堆的性質(zhì),因此需重新調(diào)整

這樣就得到了初始堆。

先進(jìn)行一次調(diào)整時(shí)其成為大頂堆,

即每次調(diào)整都是從父節(jié)點(diǎn)、左孩子節(jié)點(diǎn)、右孩子節(jié)點(diǎn)三者中選擇最大者跟父節(jié)點(diǎn)進(jìn)行交換(交換之后可能造成被交換的孩子節(jié)點(diǎn)不滿足堆的性質(zhì),因此每次交換之后要重新對被交換的孩子節(jié)點(diǎn)進(jìn)行調(diào)整)。有了初始堆之后就可以進(jìn)行排序了。

此時(shí)3位于堆頂不滿堆的性質(zhì),則需調(diào)整繼續(xù)調(diào)整

這樣整個(gè)區(qū)間便已經(jīng)有序了。從上述過程可知,堆排序其實(shí)也是一種選擇排序,是一種樹形選擇排序。只不過直接選擇排序中,為了從R[1...n]中選擇最大記錄,需比較n-1次,然后從R[1...n-2]中選擇最大記錄需比較n-2次。事實(shí)上這n-2次比較中有很多已經(jīng)在前面的n-1次比較中已經(jīng)做過,而樹形選擇排序恰好利用樹形的特點(diǎn)保存了部分前面的比較結(jié)果,因此可以減少比較次數(shù)。對于n個(gè)關(guān)鍵字序列,最壞情況下每個(gè)節(jié)點(diǎn)需比較log2(n)次,因此其最壞情況下時(shí)間復(fù)雜度為nlogn。堆排序?yàn)椴环€(wěn)定排序,不適合記錄較少的排序。 上面描述了這么多,簡而言之,堆排序的基本做法是:首先,用原始數(shù)據(jù)構(gòu)建成一個(gè)大(小)堆作為原始無序區(qū),然后,每次取出堆頂元素,放入有序區(qū)。由于堆頂元素被取出來了,我們用堆中最后一個(gè)元素放入堆頂,如此,堆的性質(zhì)就被破壞了。我們需要重新對堆進(jìn)行調(diào)整,如此繼續(xù)N次,那么無序區(qū)的N個(gè)元素都被放入有序區(qū)了,也就完成了排序過程。
(建堆是自底向上)

實(shí)際應(yīng)用:

實(shí)際中我們進(jìn)行堆排序是為了取得一定條件下的最大值或最小值,例如:需要在100個(gè)數(shù)中找到10個(gè)最大值,因此我們定義一個(gè)大小為10的堆,把100中的前十個(gè)數(shù)據(jù)建立成小頂堆(堆頂最?。?,然后從100個(gè)數(shù)據(jù)中的第11個(gè)數(shù)據(jù)開始與堆頂比較,若堆頂小于當(dāng)前數(shù)據(jù),則把堆頂彈出,把當(dāng)前數(shù)據(jù)壓入堆頂,然后把數(shù)據(jù)從堆頂下移到一定位置即可,

代碼:

public class Test0 {
	static int[] arr;//堆數(shù)組,有效數(shù)組
	 public Test0(int m){
		arr= new int[m];
	}
	
	 static int m=0;
	static int size=0;//用來標(biāo)記堆中有效的數(shù)據(jù)
	public void addToSmall(int v){
		//int[] a = {16,4,5,9,1,10,11,12,13,14,15,2,3,6,7,8,111,222,333,555,66,67,54};
		//堆的大小為10
		//arr = new int[10];
		if(size<arr.length){
			arr[size]=v;
			add_sort(size);
			//add_sort1(size);
			size++;
		}else{
			arr[0]=v;
			add_sort1(0);								
		}

		
	}
	public void printSmall(){
		for(int i=0;i<size;i++){
			System.out.println(arr[i]);
		}
	}
	public void del(){ 
		size--;
		arr[0]=arr[9];
		add_sort1(0);
	}
	public void Small(int index){
		if(m<arr.length){
			add_sort(index);
			m++;
		}else{
			add_sort1(index);
			m++;
		}
	}
	public void add_sort( int index){//小頂堆,建堆
		/*
	  * 父節(jié)點(diǎn)坐標(biāo):index
	  * 左孩子節(jié)點(diǎn):index*2
	  * 右孩子節(jié)點(diǎn):index*2+1
	  *若數(shù)組中最后一個(gè)為奇數(shù)則為 左孩子
	  *若數(shù)組中最后一個(gè)為偶數(shù)則為 右孩子
	      若孩子節(jié)點(diǎn)比父節(jié)點(diǎn)的值大,則進(jìn)行值交換,若右孩子比左孩子大則進(jìn)行值交換
		 * 
		 */
			int par;
			if(index!=0){
				if(index%2==0){
					par=(index-1)/2;
					if(arr[index]<arr[par]){
						swap(arr,index,par);
						add_sort(par);
					}
					if(arr[index]>arr[par*2]){
						swap(arr,index,par*2);
					if(arr[index]<arr[par]){
						swap(arr,index,par);
					}
					add_sort(par);
					}
					
				}else{
					par=index/2;
					if(arr[index]<arr[par]){
						swap(arr,index,par);
						add_sort(par);
					}
					if(arr[index]<arr[par*2+1]){
						swap(arr, index, par*2+1);
					if(arr[index]<arr[par]){
						swap(arr,index,par);
					}
					add_sort(par);
					}
				}
	
			}
		
		
	}
	public void add_sort1(int index){//調(diào)整小頂堆
		/*調(diào)整自頂向下
		 * 只要孩子節(jié)點(diǎn)比父節(jié)點(diǎn)的值大,就進(jìn)行值交換,
		 */
		int left=index*2;
		int right=index*2+1;
		int max=0;
		if(left<10&&arr[left]<arr[index]){
			max=left;
		}else{
			max=index;
		}
		if(right<10&&arr[right]<arr[max]){
			max=right;
		}
		if(max!=index){
			swap(arr,max,index);
			add_sort1(max);
		}
	}

}

測試代碼:
package 大頂堆;

import java.util.Scanner;

public class Main_test0 {
	public static void main(String args[]){
		Scanner scan = new Scanner(System.in);
		System.out.println("(小頂堆)請輸入堆大?。?);
		int m=scan.nextInt();
		Test0 test = new Test0(m);
		int[] a = {16,4,5,9,1,10,11,12,13,14,15,2,3,6,7,8};
		for(int i=0;i<a.length;i++){
			test.addToSmall(a[i]);
		}
		test.printSmall();				
		test.del();
		test.printSmall();	
	
		scan.close();
	}
}

以上這篇Java 堆排序?qū)嵗?大頂堆、小頂堆)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java8新特性:lambda表達(dá)式總結(jié)

    Java8新特性:lambda表達(dá)式總結(jié)

    這篇文章主要介紹了Java8新特性:lambda表達(dá)式總結(jié),本文總結(jié)了多種語法格式和使用方法,包含了函數(shù)式接口和內(nèi)置的四大核心函數(shù)式接口的用法實(shí)例,需要的朋友可以參考下
    2021-06-06
  • 全面了解JAVA_BaseDAO數(shù)據(jù)處理類

    全面了解JAVA_BaseDAO數(shù)據(jù)處理類

    下面小編就為大家?guī)硪黄媪私釰AVA_BaseDAO數(shù)據(jù)處理類。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • java 類加載機(jī)制和反射詳解及實(shí)例代碼

    java 類加載機(jī)制和反射詳解及實(shí)例代碼

    這篇文章主要介紹了java 類加載機(jī)制和反射詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • java中實(shí)體類和JSON對象之間相互轉(zhuǎn)化

    java中實(shí)體類和JSON對象之間相互轉(zhuǎn)化

    Java中關(guān)于Json格式轉(zhuǎn)化Object,Map,Collection類型和String類型之間的轉(zhuǎn)化在我們實(shí)際項(xiàng)目中應(yīng)用的很是普遍和廣泛。最近工作的過程中也是經(jīng)常有,因此,自己封裝了一個(gè)類分享給大家。
    2015-05-05
  • spring循環(huán)依賴策略解析

    spring循環(huán)依賴策略解析

    這篇文章主要為大家詳細(xì)介紹了spring循環(huán)依賴策略,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • SpringBoot Admin的簡單使用的方法步驟

    SpringBoot Admin的簡單使用的方法步驟

    本文主要介紹了SpringBoot Admin的簡單使用的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java中類的定義和初始化示例詳解

    Java中類的定義和初始化示例詳解

    這篇文章主要給大家介紹了關(guān)于Java中類的定義和初始化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java編程中字節(jié)流轉(zhuǎn)換成字符流的實(shí)現(xiàn)方法

    java編程中字節(jié)流轉(zhuǎn)換成字符流的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava編程中字節(jié)流轉(zhuǎn)換成字符流的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • ResponseBodyAdvice的使用原理源碼解析

    ResponseBodyAdvice的使用原理源碼解析

    這篇文章主要為大家介紹了ResponseBodyAdvice的使用原理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • java實(shí)現(xiàn)從網(wǎng)絡(luò)下載多個(gè)文件

    java實(shí)現(xiàn)從網(wǎng)絡(luò)下載多個(gè)文件

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)從網(wǎng)絡(luò)下載多個(gè)文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07

最新評論

五峰| 乌恰县| 北辰区| 岐山县| 仁寿县| 禄劝| 买车| 游戏| 巨鹿县| 鄂托克旗| 浦城县| 富阳市| 东辽县| 榆社县| 和静县| 营山县| 光山县| 新泰市| 安平县| 隆尧县| 毕节市| 旌德县| 彰化市| 德令哈市| 鄯善县| 苍溪县| 依安县| 边坝县| 宁都县| 区。| 丹寨县| 舟山市| 海晏县| 清丰县| 庆城县| 百色市| 迁西县| 全州县| 洛南县| 中山市| 杭锦旗|