HeapSort堆排序

/*

  • @Author: sumBorn
  • @Date: 2022-03-01 21:45:51
  • @Description:

空間復(fù)雜度O(NlogN)
時(shí)間復(fù)雜度O(1)
不穩(wěn)定排序

堆的基本思想:

  • 和樹的區(qū)別 http://m.itdecent.cn/p/6b526aa481b1
  • shiftUp():對(duì)于最大堆來說,如果某個(gè)節(jié)點(diǎn)比自己父節(jié)點(diǎn)大,就要往上移,和父節(jié)點(diǎn)交換位置
  • shiftDown()<堆化>:對(duì)于最大堆來說,如果某個(gè)節(jié)點(diǎn)比自己父節(jié)點(diǎn)小,就要往下移,和子節(jié)點(diǎn)交換位置、
  • 兩者都是一個(gè)遞歸的過程,所以時(shí)間復(fù)雜度是O(logN)

基本步驟:

  1. 對(duì)序列進(jìn)行原地建堆
  2. 重復(fù)以下流程,直到元素個(gè)數(shù)為1
  • 交換堆頂元素與堆尾元素
  • 堆的元素?cái)?shù)量減1
  • 堆0位置的元素進(jìn)行siftdown操作

例子:
0:{50,21,80,43,38,14}
1:{80,43,50,21,38,14}
2:{50,43,14,21,38,80}
3:{43,38,14,21,50,80}
4:{38,21,14,43,50,80}
...

*/

/**

  • @description: 遞歸實(shí)現(xiàn) 看著更棒

  • @param {*}

  • @return {*}
    */
    public class Solution
    {
    public void HeapSort(int[] arr)
    {
    int endIndex = arr.Length - 1;
    int beginIndex = (endIndex - 1) / 2;//shiftdown第一次判斷有子節(jié)點(diǎn)的那個(gè)父節(jié)點(diǎn),所有的葉子節(jié)點(diǎn)都沒有子節(jié)點(diǎn)根本不需要進(jìn)行操作,只有有子節(jié)點(diǎn)的節(jié)點(diǎn)才需要進(jìn)行操作,所以找到第一個(gè)有葉子節(jié)點(diǎn)的節(jié)點(diǎn)
    for (int i = beginIndex; i >= 0; i--)
    {
    this.Shiftdown(i, arr, endIndex); //需要shiftdown的索引元素,整個(gè)數(shù)組,這個(gè)元素可以down到最低的位置,也就是數(shù)組的最末尾
    }

     for (int i = endIndex; i >= 0; i--)
     {
         this.Swap(i, 0, arr);
         this.Shiftdown(0, arr, i - 1);//交換完 down可以的最低位置少了一位
     }
    

    }

    public void Shiftdown(int index, int[] arr, int limitIndex)
    {
    int leftIndex = index * 2 + 1;
    int rightIndex = leftIndex + 1;
    int maxIndex = leftIndex;//先默認(rèn)左節(jié)點(diǎn)比右節(jié)點(diǎn)大

     if (leftIndex > limitIndex)
         return;
    
     if (leftIndex < limitIndex && arr[leftIndex] < arr[rightIndex])
         maxIndex = rightIndex;
    
     if (arr[maxIndex] > arr[index])
     {
         this.Swap(maxIndex, index, arr);
         this.Shiftdown(maxIndex, arr, limitIndex);
     }
    

    }

    public void Swap(int i, int j, int[] arr)
    {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
    }
    }

/**

  • @description: 正常實(shí)現(xiàn)

  • @param {*}

  • @return {*}
    */
    public class Solution
    {
    public void HeapSort(int[] arr)
    {
    for (int i = arr.Length / 2 - 1; i >= 0; i--)
    {
    this.Shiftdown(i, arr, arr.Length - 1);
    }

     for (int i = arr.Length - 1; i >= 0; i--)
     {
         this.Swap(i, 0, arr);
         this.Shiftdown(0, arr, i - 1);// 從根節(jié)點(diǎn)向下調(diào)整,每次取出一個(gè)數(shù)值,集合長(zhǎng)度逐漸減小
     }
    

    }

    public void Swap(int i, int j, int[] arr)
    {
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
    }

    public void Shiftdown(int index, int[] arr, int limitIndex)
    {
    int node = arr[index];
    while (index <= limitIndex)
    {
    int leftIndex = 2 * index + 1;
    int rightIndex = 2 * index + 2;
    if (leftIndex > limitIndex)
    {
    //左右節(jié)點(diǎn)都沒有
    break;
    }
    else if (rightIndex > limitIndex)
    {
    //左節(jié)點(diǎn)在,右節(jié)點(diǎn)沒了
    int left = arr[leftIndex];
    if (left > node)
    {
    arr[index] = left;
    index = leftIndex;
    }
    else
    {
    break;
    }
    }
    else
    {
    //左右節(jié)點(diǎn)都在
    int left = arr[leftIndex];
    int right = arr[rightIndex];
    int maxIndex = left >= right ? leftIndex : rightIndex;
    int max = arr[maxIndex];
    if (max < node)
    {
    break;
    }
    else
    {
    //和較大值交換
    arr[index] = max;
    index = maxIndex;
    }
    }
    }
    arr[index] = node;
    }

    public void ShiftUp(int index, int[] arr)
    {
    int node = arr[index];
    while (index > 0)
    {
    int parentIndex = (int)((index - 1) / 2);
    int parent = arr[parentIndex];

         if (parent > node) break;
    
         arr[index] = parent;
         index = parentIndex;
     }
     arr[index] = node;
    

    }
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • HeapSort 轉(zhuǎn)載自:鏈接:http://m.itdecent.cn/p/719b0de606a7 ...
    須臾之北閱讀 4,152評(píng)論 0 1
  • package basic_class_01; import java.util.Arrays; ``` * 左神...
    楓葉憶閱讀 573評(píng)論 0 1
  • 還想看更多文章的朋友可以訪問我的個(gè)人博客 一些基礎(chǔ)知識(shí) 學(xué)習(xí)堆排序,總要了解堆的數(shù)據(jù)結(jié)構(gòu)吧,了解堆又需要了解二叉樹...
    我是才子閱讀 523評(píng)論 0 0
  • 堆的定義 堆是一種特殊的數(shù)據(jù)結(jié)構(gòu),可以形象化的看成一顆完全二叉樹,一般內(nèi)部的存儲(chǔ)結(jié)構(gòu)為數(shù)組;堆中的某個(gè)節(jié)點(diǎn)總是不大...
    yandaren閱讀 2,847評(píng)論 0 5
  • 一、算法的分類 1、概念 將雜亂無章的數(shù)據(jù)元素,通過一定的方法按關(guān)鍵字順序排列的過程叫做排序。 2、分類 非線性時(shí)...
    Java資訊庫(kù)閱讀 2,004評(píng)論 0 14

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