選擇排序(直接選擇排序、堆排序)——Java

來源:互聯網
上載者:User

標籤:堆排序   選擇排序   java   演算法   資料結構   

選擇排序思想:每趟從待排序的記錄序列中選擇關鍵字最小的記錄放置到已排序表的最前位置,直到全部排完。關鍵問題:在剩餘的待排序記錄序列中找到最小關鍵碼記錄。方法:–直接選擇排序–堆排序
(1)簡單的選擇排序  1、基本思想:在要排序的一組數中,選出最小的一個數與第一個位置的數交換;然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後一個數比較為止。    2、執行個體實現代碼:
public static void main(String[] args){int[] nums={57,68,59,52};sort(nums);}public static void sort(int[] nums){for (int i = 0; i < nums.length; i++){int min=nums[i];int n=i;//最小數的索引for (int j = i+1; j < nums.length; j++){if (nums[j]<min){//找出最小數min=nums[j];n=j;}}nums[n]=nums[i];nums[i]=min;}}

(2)堆排序1.定義n個關鍵字序列Kl,K2,…,Kn稱為(Heap),若且唯若該序列滿足如下性質(簡稱為堆性質):(1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n/2),當然,這是小根堆,大根堆則換成>=號。//k(i)相當於二叉樹的非葉子結點,K(2i)則是左子節點,k(2i+1)是右子節點若將此序列所儲存的向量R[1..n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉子結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。【例】關鍵字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分別滿足堆性質(1)和(2),故它們均是堆,其對應的完全二叉樹分別如小根堆樣本和大根堆樣本所示。大根堆和小根堆:根結點(亦稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。根結點(亦稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。注意:①堆中任一子樹亦是堆。②以上討論的堆實際上是二元堆積(Binary Heap),類似地可定義k叉堆。堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。(1)用大根堆排序的基本思想① 先將初始檔案R[1..n]建成一個大根堆,此堆為初始的無序區② 再將關鍵字最大的記錄R[1](即堆頂)和無序區的最後一個記錄R[n]交換,由此得到新的無序區R[1..n-1]和有序區R[n],且滿足R[1..n-1].keys≤R[n].key③由於交換後新的根R[1]可能違反堆性質,故應將當前無序區R[1..n-1]調整為堆。然後再次將R[1..n-1]中關鍵字最大的記錄R[1]和該區間的最後一個記錄R[n-1]交換,由此得到新的無序區R[1..n-2]和有序區R[n-1..n],且仍滿足關係R[1..n-2].keys≤R[n-1..n].keys,同樣要將R[1..n-2]調整為堆。……直到無序區只有一個元素為止。(2)大根堆排序演算法的基本操作:①建堆,建堆是不斷調整堆的過程,從len/2處開始調整,一直到第一個節點,此處len是堆中元素的個數。建堆的過程是線性過程,從len/2到0處一直調用調整堆的過程,相當於o(h1)+o(h2)…+o(hlen/2) 其中h表示節點的深度,len/2表示節點的個數,這是一個求和的過程,結果是線性O(n)。②調整堆:調整堆在構建堆的過程中會用到,而且在堆排序過程中也會用到。利用的思想是比較節點i和它的孩子節點left(i),right(i),選出三者最大(或者最小)者,如果最大(小)值不是節點i而是它的一個孩子節點,那邊互動節點i和該節點,然後再調用調整堆過程,這是一個遞迴的過程。調整堆的過程時間複雜度與堆的深度有關係,是lgn的操作,因為是沿著深度方向進行調整的。③堆排序:堆排序是利用上面的兩個過程來進行的。首先是根據元素構建堆。然後將堆的根節點取出(一般是與最後一個節點進行交換),將前面len-1個節點繼續進行堆調整的過程,然後再將根節點取出,這樣一直到所有節點都取出。堆排序過程的時間複雜度是O(nlgn)。因為建堆的時間複雜度是O(n)(調用一次);調整堆的時間複雜度是lgn,調用了n-1次,所以堆排序的時間複雜度是O(nlgn)

2、執行個體

初始序列:46,79,56,38,40,84

  建堆:

   交換,從堆中踢出最大數



3、代碼實現:
public static void main(String[] args){int[] nums={46,79,56,38,40,84};int len=nums.length;//迴圈建堆for (int i = 0; i < nums.length-1; i++){//建堆buildMaxHeap(nums,len-1-i);//交換堆頂和最後一個元素swap(nums,0,len-1-i);System.out.println(Arrays.toString(nums));}}/** * 對nums數組中0到lastIndex建大頂堆 */public static void buildMaxHeap(int[] nums,int lastIndex){//從lastIndex處節點(最後一個節點)的父節點開始for (int i = (lastIndex-1)/2; i >=0; i--){//k儲存正在判斷的節點int k=i;//如果當前K節點的子節點存在while (k*2+1<=lastIndex){//k節點的左節點的索引int binggerIndex=2*k+1;//如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在if (binggerIndex<lastIndex){//如果右子節點的值較大if (nums[binggerIndex]<nums[binggerIndex+1]){binggerIndex++;}}//如果K節點的值小於其較大的子節點的值if (nums[k]<nums[binggerIndex]){//交換他們swap(nums, k, binggerIndex);//將biggerIndex賦予K,開始While迴圈的下一次,重新保證k節點的值大於其左右子節點的值k=binggerIndex;}else{break;}}}}public static void swap(int[] nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}



著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

選擇排序(直接選擇排序、堆排序)——Java

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.