程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 堆(Heap)的實現,heap實現

堆(Heap)的實現,heap實現

編輯:C++入門知識

堆(Heap)的實現,heap實現


這次實現了堆,這個堆不是指系統堆棧的堆,是一種數據結構,見下圖

堆的本質就是一個數組(上圖中,紅色的是值,黑色的是下標)簡單的來說就是把一個數組看成是二叉樹,就像上圖

大堆和小堆分別是指根節點比孩子節點的值大或者是小,看了上圖之後就可以發現,父親節點和孩子節點之間下表的關系,parnet=(child-1)/2

利用這個關系就可以實現堆了,堆的基本方法有構造,析構,插入,刪除,像大堆小堆這樣特殊的堆肯定是要有調整函數來保持他們的特性的,所以我還寫了向上調整和向下調整的函數

為了讓大堆和小堆之間切換自如(就是方便維護),我寫了兩個仿函數,建立堆的對象時傳個模版參數就好了

  1 #pragma once
  2 #include<iostream>
  3 #include<vector>
  4 using namespace std;
  5 
  6 template<class T>
  7 struct Less
  8 {
  9     bool  operator()(const T& l,const T& r)
 10     {
 11         return l < r;
 12     }
 13 };
 14 
 15 template<class T>
 16 struct Greater
 17 {
 18     bool operator()(const T& l ,const T& r)
 19     {
 20         return l > r;
 21     }
 22 };
 23 
 24 
 25 
 26 
 27 
 28 template<class T, class Compare = Less<T>>
 29 class Heap
 30 {
 31 public:
 32     Heap()
 33     {
 34 
 35     }
 36     Heap(vector<T> a)
 37         :array(a)
 38     {
 39         for (int i = (array.size() - 2) / 2; i >=0 ; --i)
 40         {
 41             AdjustDown(i);
 42         }
 43     }
 44     Heap(T *a, size_t size)
 45     {
 46         for (int i = 0; i < size; ++i)
 47         {
 48             array.push_back(a[i]);
 49         }
 50         for (int i = (array.size() - 2) / 2; i >= 0; --i)
 51         {
 52             AdjustDown(i);
 53         }
 54     }
 55     ~Heap()
 56     {
 57         
 58     }
 59     void Push(T x)
 60     {
 61         array.push_back(x);
 62         AdjustUp(array.size()-1);
 63     }
 64     void Pop()
 65     {
 66         swap(array.front(), array.back());
 67         array.pop_back();
 68         AdjustDown(0);
 69     }
 70     void AdjustDown(int root)
 71     {
 72         int child = root * 2 + 1;
 73         while (child < array.size())
 74         {
 75             if (child + 1 < array.size() && Compare()(array[child + 1], array[child]))
 76             {
 77                 child++;
 78             }
 79             if (Compare(array[root], array[child]))
 80             {
 81                 swap(array[root], array[child]);
 82                 root = child;
 83                 child = root * 2 + 1;
 84             }
 85             else
 86             {
 87                 break;
 88             }
 89         }
 90     }
 91     void AdjustUp(int child)
 92     {
 93         int parent = (child - 1) / 2;
 94         while (child > 0)
 95         {
 96             if (Compare()(array[child], array[parent]))
 97             {
 98                 swap(array[child], array[parent]);
 99                 child = parent;
100                 parent = (child - 1) / 2;
101             }
102             else
103             {
104                 break;
105             }
106         }
107     }
108     void Print()
109     {
110         for (int i = 0; i < array.size(); ++i)
111         {
112             cout << array[i] << " ";
113         }
114         cout << endl;
115     }
116     int Size()
117     {
118         return array.size();
119     }
120 protected:
121     vector<T> array;
122 };
123 
124 
125 void TestHeap()
126 {
127     Heap<int> hp;
128     int a[10] = { 5,3,6,2,1,7,8,9,4,0 };
129     for (int i = 0; i < 10; ++i)
130     {
131         hp.Push(a[i]);
132     }
133     hp.Print();
134 }

當一個一個push插入的時候我們只需要把這個元素插入到數組的最後,然後順著二叉樹向上調整就可以了(只需要調整這一條線)

刪除頭元素(根節點)的時候,為了不破壞結構,我們選擇先跟處於最後位置的元素交換,之後在末尾刪除掉“根節點”,然後因為最大值(最小值)被換到了根節點,不符合小堆(大堆)的結構要求,只需要順著這條路一直向下調整就可以了

我還寫了一個構造函數接收的參數是一個vector,這是把整個vector調整成大堆(小堆),先找到最後一個元素的父親節點,一直往前向下調整就可以了,因為這個父親節點之前也肯定都是有孩子父親節點

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved