日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

排序算法——堆排序

發布時間:2024/4/18 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序算法——堆排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

堆排序

1.基礎概念

  • 二叉樹的概念:
    二叉樹(binary tree)是指樹中節點的 度 不大于2的有序樹. 在二叉樹中除了根節點的每一個節點都僅有一個父節點,所有的節點最多只能有兩個
    孩子節點。

  • 滿二叉樹的概念:
    除最后一層無任何子節點外,每一層上的所有結點都有兩個子結點的二叉樹。
    國內教材定義:
    一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹。也就是說,如果一個二叉樹的層數為K,且結點總數是(2^k) -1 ,則它就是滿二叉樹。
    國外(國際)定義:
    a binary tree T is full if each node is either a leaf or possesses exactly two childnodes.

  • 完全二叉樹:
    對滿二叉樹的結點進行編號, 約定編號從根結點起, 自上而下, 自左而右。則深度為k的, 有n個結點的二叉樹, 當且僅當其每一個結點都與深度為k的滿二叉樹中編號從1至n的結點一一對應時 。

  • 堆的概念:
    堆通常是一個可以被看做一棵完全二叉樹。

  • 大根堆, 就是說這個完全二叉樹中每一棵子樹的根節點都大于他的左右孩子(如果有的話)
  • 小根堆,就是說這個完全二叉樹中每一棵子樹的根節點都小于他的左右孩子(如果有的話)
    • 二叉樹的存儲方式
  • 順序存儲
    (1) 按照完全二叉樹(無論是那種二叉樹)的形式,將二叉樹的數據全部存儲在數組中.
    (2) 順序表中的每個元素除了存儲data,leftchild , rightchild
  • 鏈式存儲 每個節點都有至少三個域(data,* leftchild,* rightchild)
    • 堆僅僅將數據存儲在數組中
  • 如果父節點的下標為i,則左孩子的下標為 2 * i + 1,右孩子的下標為 2 * i + 2
  • 如果孩子的下標為j, 則父節點的下標是: ( j - 1 ) / 2
  • 2.堆的建立過程

    • 將數組中的數據調整成堆時,從最后一棵子樹開始,向根節點一顆顆調整
      每棵子樹的調整都是從其根節點開始向下調整的
    • 一棵子樹的調整過程:
      先用i指向子樹的根節點,j為根節點的左孩子。將i位置的值保存到tmp中, 然后在左右孩子中找到較大的哪一個,j指向較大值,(1)如果較大的哪一個比臨時變量中的值小,則直接退出;(2)如果較大的哪一個比臨時變量中的值大,則將較大的值保存到i位置上,然后i=j,j=2*i+1,直到j越界則退出。退出以后,還需要將tmp的值保存到退出時的i位置上。

    代碼實現

    void OneAdjust(int *arr, int len, int root) {int tmp = arr[root];int i = root;int j = 2 * i + 1;while (j < len){// j+1 < len 成立 則有右孩子// arr[j] < arr[j+1] 左孩子的值小于右孩子if (j + 1 < len && arr[j] < arr[j + 1]) j++;if (arr[j] < tmp) break;arr[i] = arr[j];i = j;j = 2 * i + 1;}arr[i] = tmp; }
    • 將數組調整成堆的過程
      先找到最后一棵子樹的根節點,向根節點遞減,循環調用上面的調整方法。

    代碼實現

    void CreateHeap(int *arr, int len) {int lastRoot = (len - 2) / 2; // lastRoot就是最后一棵子樹的根節點下標for (int i = lastRoot; i >= 0; --i) // 從lastRoot開始,循環到整顆數的根節點,調整{OneAdjust(arr, len, i);} }

    3.堆排序

    • 先將數組中的數據調整成一棵最大堆, 然后將根節點的數據和最后位置的節點交換, 接著除過最后一個位置的數據外,在將剩余的數據調整成
      最大堆。
    • 重復上述過程,直到只剩下一個數據沒有交換。就完成了堆排序。
    // 時間復雜度: O(nlog(n)) // 空間復雜度: O(1) // 穩定性: 不穩定 void HeapSort(int *arr, int len) {CreateHeap(arr, len);for (int i = 0; i < len - 1; ++i){Swap(&arr[0], &arr[len - 1 - i]);OneAdjust(arr, len - i - 1, 0);} }

    總結

    以上是生活随笔為你收集整理的排序算法——堆排序的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。