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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

堆的原理及实现

發布時間:2025/4/5 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 堆的原理及实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1 堆的原理
    • 2 堆的實現
      • 2.1 堆的創建
      • 2.2 向堆中插入新元素
      • 2.3 堆頂元素出堆

1 堆的原理

先看一下堆長什么樣:

最大堆的特點:

  • 每個結點最多可以有2個子結點。
  • 根結點的鍵值是所有堆結點值中的最大者,且每個結點的值都比其孩子的值大。
  • 除了根結點沒有兄弟結點,最后一個左子結點可以沒有兄弟結點,其他結點必須有兄弟結點。
  • 看一下如下幾個符不符合最大堆的定義:

    (A、B不是,C是最大堆。)

    看一下堆的特點:

    • 堆是你見過的最有個性的樹!它是用數組表示的樹!

    對于i子結點:

    • i的左子結點為:2 * i + 1
    • i的右子結點為:2 * i + 2
    • i的父結點:(i - 1) / 2

    2 堆的實現

    2.1 堆的創建

    在數組中快速創建堆:




    算法實現如下:

    堆數據結構的定義:

    #define DEFAULT_CAPCITY 128typedef struct _Heap{int *arr; //存儲堆元素的數組int size; //當前已存儲的元素個數int capacity; //當前存儲的容量 }Heap;

    建最大堆:

    bool initHeap(Heap &heap, int *orginal, int size); static void buildHeap(Heap &heap); static void adjustDown(Heap &heap, int index);/*初始化堆*/ bool initHeap(Heap &heap, int *orginal, int size){int capacity = DEFAULT_CAPCITY>size? DEFAULT_CAPCITY:size;heap.arr = new int[capacity];if(!heap.arr) return false;heap.capacity = capacity;heap.size = 0;//如果存在原始數據則構建堆if(size>0){memcpy(heap.arr, orginal, size*sizeof(int));heap.size = size;buildHeap(heap);}else {heap.size = 0;}return true; }/*將當前的節點和子節點調整成最大堆*/ void adjustDown(Heap &heap, int index) { int cur=heap.arr[index];//當前待調整的節點int parent,child;/*判斷否存在大于當前節點子節點,如果不存在 ,則堆本身是平衡的,不需要調整;如果存在,則將最大的子節點與之交換,交換后,如果這個子節點還有子節點,則要繼續按照同樣的步驟對這個子節點進行調整*/for(parent=index; (parent*2+1)<heap.size; parent=child){child=parent*2+1;//取兩個子節點中的最大的節點if(((child+1)<heap.size)&&(heap.arr[child]<heap.arr[child+1])){child++;}//判斷最大的節點是否大于當前的父節點if(cur>=heap.arr[child]){//不大于,則不需要調整,跳出循環break;}else {//大于當前的父節點,進行交換,然后從子節點位置繼續向下調整heap.arr[parent]=heap.arr[child];heap.arr[child]=cur;}} }/* 從最后一個父節點(size/2-1 的位置)逐個往前調整所有父節點 (直到根節點),確保每一個父節點都是一個最大堆,最后整體上形成一個最大堆 */ void buildHeap(Heap &heap){int i;for(i=heap.size/2-1; i>=0; i--){adjustDown(heap, i);} }

    2.2 向堆中插入新元素




    代碼實現:

    /*將當前的節點和父節點調整成最大堆*/ void adjustUp(Heap &heap, int index) {if(index<0 || index >= heap.size){//大于堆的最大值直接 returnreturn;}while(index>0){int temp = heap.arr[index];int parent = (index - 1) / 2;if(parent >= 0){//如果索引沒有出界就執行想要的操作if(temp > heap.arr[parent]){heap.arr[index] = heap.arr[parent];heap.arr[parent] = temp;index = parent;}else {//如果已經比父親小 直接結束循環break;}}else {//越界結束循環break;}} }/*最大堆尾部插入節點,同時保證最大堆的特性*/ bool insert(Heap &heap, int value) {if (heap.size == heap.capacity) {fprintf(stderr, "棧空間耗盡!\n");return false;}int index = heap.size;heap.arr[heap.size++] = value;adjustUp(heap, index);return true; }

    這樣的話我們就可以有另一種創建堆的方式:

    /*初始化堆*/ bool initHeap(Heap &heap, int *orginal, int size) {int capacity = DEFAULT_CAPCITY>size ? DEFAULT_CAPCITY : size;heap.arr = new int[capacity];if (!heap.arr) return false;heap.capacity = capacity;heap.size = 0;//如果存在原始數據則構建堆if(size > 0){/*方式一: 直接調整所有元素memcpy(heap.arr, orginal, size*sizeof(int));heap.size = size;//建堆buildHeap(heap);*///方式二: 一次插入一個for(int i=0; i<size; i++){insert(heap, orginal[i]);}}return true; }

    2.3 堆頂元素出堆

    如果我們將堆頂的元素刪除,那么頂部有一個空的節點,怎么處理?

    當插入節點的時候,我們將新的值插入數組的尾部?,F在我們來做相反的事情:我們取出數組中的最后一個元素,將它放到堆的頂部,然后再修復堆屬性。

    /* 刪除優先隊列中最大的節點,并獲得節點的值*/ bool pop(Heap& heap, int &value) {if (!heap || (heap->size==0)) return false;value = heap.arr[0];pq.arr[0] = heap.arr[--heap.size];//heap.arr[0] = heap.arr[heap.size-1];//heap.size--;adjustDown(heap, 0);// 向下執行堆調整return true; }

    參考資料:

  • C/C++從入門到精通-高級程序員之路【奇牛學院】
  • 總結

    以上是生活随笔為你收集整理的堆的原理及实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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