算法學(xué)習(xí):堆排序

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

  • 算法規(guī)則:
    堆是具有下列性質(zhì)的完全二叉樹:每個(gè)結(jié)點(diǎn)的值都大于或等于其左右孩子結(jié)點(diǎn)的值,稱為大頂堆;或者每個(gè)結(jié)點(diǎn)的值都小于或等于其左右孩子結(jié)點(diǎn)的值,稱為小頂堆。將待排序的序列構(gòu)造成一個(gè)大頂堆。此時(shí),整個(gè)序列的最大值就是堆頂?shù)母?jié)點(diǎn)。將它移走(其實(shí)就是將其與堆數(shù)組的末尾元素交換,此時(shí)末尾元素就是最大值),然后將剩余的n-1個(gè)序列重新構(gòu)造成一個(gè)堆,這樣就會得到n個(gè)元素中的次最大值。如此反復(fù)執(zhí)行,就能得到一個(gè)有序序列了。

  • 代碼實(shí)現(xiàn)(Java版本)

      /** 
       * 堆排序 
       */  
      private static void heapSort(int[] arr) {   
          // 將待排序的序列構(gòu)建成一個(gè)大頂堆  
          for (int i = arr.length / 2; i >= 0; i--){   
              heapAdjust(arr, i, arr.length);   
          }  
        
          // 逐步將每個(gè)最大值的根節(jié)點(diǎn)與末尾元素交換,并且再調(diào)整二叉樹,使其成為大頂堆  
          for (int i = arr.length - 1; i > 0; i--) {   
              swap(arr, 0, i); // 將堆頂記錄和當(dāng)前未經(jīng)排序子序列的最后一個(gè)記錄交換  
              heapAdjust(arr, 0, i); // 交換之后,需要重新檢查堆是否符合大頂堆,不符合則要調(diào)整  
          }  
      }  
    
      /** 
       * 構(gòu)建堆的過程 
       * @param arr 需要排序的數(shù)組 
       * @param i 需要構(gòu)建堆的根節(jié)點(diǎn)的序號 
       * @param n 數(shù)組的長度 
      */  
      private static void heapAdjust(int[] arr, int i, int n) {  
          int child;  
          int father;   
          for (father = arr[i]; leftChild(i) < n; i = child) {  
              child = leftChild(i);  
            
              // 如果左子樹小于右子樹,則需要比較右子樹和父節(jié)點(diǎn)  
              if (child != n - 1 && arr[child] < arr[child + 1]) {  
                  child++; // 序號增1,指向右子樹  
              }  
                
              // 如果父節(jié)點(diǎn)小于孩子結(jié)點(diǎn),則需要交換  
              if (father < arr[child]) {  
                  arr[i] = arr[child];  
              } else {  
                  break; // 大頂堆結(jié)構(gòu)未被破壞,不需要調(diào)整  
              }  
          }  
          arr[i] = father;  
      }  
    
      // 獲取到左孩子結(jié)點(diǎn)  
      private static int leftChild(int i) {  
          return 2 * i + 1;  
      }  
        
      // 交換元素位置  
      private static void swap(int[] arr, int index1, int index2) {  
          int tmp = arr[index1];  
          arr[index1] = arr[index2];  
          arr[index2] = tmp;  
      }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 排序算法是最基本最常用的算法,不同的排序算法在不同的場景或應(yīng)用中會有不同的表現(xiàn),我們需要對各種排序算法熟練才能將它...
    若丶天下閱讀 473評論 0 1
  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,297評論 0 52
  • 概述:排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,819評論 0 15
  • 1. 第一種人:天才且努力的人,他們和平常人不同,極少迷茫,就算人生失意,也能很快恢復(fù),他們注定成為人生贏家。 2...
    空白WYC閱讀 953評論 0 0
  • 女性進(jìn)入青春期,開始月經(jīng)來潮,性器官也開始逐漸發(fā)育完善,這個(gè)時(shí)期會發(fā)現(xiàn)一些之前存在的問題,也有月經(jīng)來潮后出現(xiàn)的新問...
    三葉秋閱讀 10,058評論 2 112

友情鏈接更多精彩內(nèi)容