数据结构--堆

泄露秘密 提交于 2020-03-05 02:48:25

堆,与其说是一种数据结构,不如说是一种排序算法。用堆算法,可以轻松得到一组数据中最大的或最小的元素。

其结构就是完全二叉树的顺序存储方式。即在一个数组中存储一颗完全二叉树。

通常,堆分为"大根堆"和"小根堆",前者的树顶元素是数组中最大的一个,后者是最小的一个。

常用操作:

入堆:元素被加入到堆中,以小根堆为例,新元素首先被放到队列最尾端,然后何其父节点比较,如果小于其父节点,则交换两者。以此类推,一直追溯到树顶元素,或者在半途,它不再小于它的父节点。操作完成。

出堆:出堆操作,就是得到当前队列中最大或最小的元素。对于一个合法的堆结构,其首元素就是所要找的。关键是这个元素取出后,其他元素要填补其移走的空白。和入堆操作相反,出堆操作是从树顶至叶节点的操作。

将一个队列构建成堆:这个操作相对复杂一些,每次都从堆底向堆顶找到其最大或最小的元素,然后分别对起两个子节点作此操作。

 

  1 #include "Array.h"
  2 #include <utility>
  3 #include <algorithm>
  4 template <typename T>
  5 class heap
  6 {
  7 public:
  8     heap(){}
  9     
 10     void push_heap(const T& data)
 11     //入堆
 12     {
 13         if(m_array.empty())
 14         {
 15             m_array.push_back(data);
 16         }
 17         else
 18         {
 19             heapify(data);
 20         }
 21     }
 22 
 23     T pop_heap()
 24     //出堆
 25     {
 26         std::swap(m_array[0], m_array[m_array.size()-1]);
 27         int i = 0;
 28         if(m_array.size()%2 == 1 && m_array.size() > 2 && m_array[m_array.size()-2< m_array[0])
 29         {
 30             std::swap(m_array[0], m_array[m_array.size()-2]);
 31         }
 32         while(i*2+2 < m_array.size()-1)
 33         {
 34             if(m_array[i*2+1< m_array[i*2+2])
 35             {
 36                 std::swap(m_array[i], m_array[i*2+1]);
 37                 i = i*2+1;
 38             }
 39             else if(i*2+2 < m_array.size()-1)
 40             {
 41                 std::swap(m_array[i], m_array[i*2+2]);
 42                 i = i*2+2;
 43             }
 44             
 45 
 46         }
 47     
 48         T tmp = m_array[m_array.size()-1];
 49         m_array.remove(m_array.end()-1);
 50         
 51         return tmp;
 52     }
 53 
 54     template <typename IT>
 55     void insert(IT _First, IT _Last)
 56     //将数组插入堆,并保持堆的合法性
 57     {
 58         for(;_First != _Last; )
 59         {
 60             push_heap(*_First++);
 61         }
 62     }
 63 
 64     template <typename IT>
 65     static void make_heap(IT _First, IT _Last)
 66     //把现有队列创建为堆结构
 67     {
 68         size_t dist = (_Last - _First-1/2;
 69         for(int i = 0; i < dist; i ++)
 70             _make_heap(_First, _Last,i);
 71     }
 72 
 73 private:
 74     void heapify(const T& data)
 75     {
 76         size_t off = m_array.size();
 77         m_array.push_back(data);
 78 
 79         int i = (off-1)/2;
 80 
 81         do
 82         {
 83             if(m_array[i] > m_array[off])
 84             {
 85                 std::swap(m_array[i], m_array[off]);
 86             }
 87             else
 88             {
 89                 break;
 90             }
 91             off = (off-1)/2;
 92             i = (off-1)/2;
 93         }while(off > 0);
 94     }
 95 
 96     template <typename IT>
 97     static void _make_heap(IT _First, IT _Last, int len)
 98     {
 99         int n = _Last - _First;
100         int nLength = (_Last - _First)/2 -1;
101 
102         if(nLength <= 1)
103         {
104             return;
105         }
106 
107         if(nLength%2 == 0)
108         //当堆的长度为偶数时,即完全二叉树上的最后一个叶子节点是其父节点的左孩子,且没有兄弟节点。
109         //则对二叉树中最后一棵子树特殊处理,下面的循环中不再理会它
110         {
111             if(*(_First+nLength) > *(_First+(nLength*2+1)))
112             {
113                 std::swap(*(_First+nLength), *(_First+(nLength*2+1)));
114                 
115             }
116             nLength --;
117         }
118 
119         for(; nLength >= len; nLength --)    
120         {
121             T a = *(_First+(nLength*2+1));
122             T b = *(_First+(nLength*2+2));
123             if(*(_First+nLength) < min(*(_First+(nLength*2+1)), *(_First+(nLength*2+2))))
124             {
125                 continue;
126             }
127             else if(*(_First+(nLength*2+1)) < *(_First+(nLength*2+2)))
128             {
129                 std::swap(*(_First+nLength), *(_First+(nLength*2+1)));
130             }
131             else
132             {
133                 std::swap(*(_First+nLength), *(_First+(nLength*2+2)));
134             }
135         }
136     }
137 
138     Array<T> m_array;
139 };
140 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!