BWAPI
|
00001 #pragma once 00002 #include <vector> 00003 #include <map> 00004 #include <utility> 00005 00006 // Hacked from BWTA's Heap implementation 00007 // Mininmum value on top 00008 template<class _Tp, class _Val> 00009 class MinHeap 00010 { 00011 private: 00018 std::vector< std::pair<_Tp, _Val> > data; 00019 std::map< _Tp, int> obj_to_pos; // maps to position in data 00020 00026 int percolate_up(int index); 00027 00033 int percolate_down(int index); 00034 00035 public: 00036 MinHeap() {} 00037 MinHeap( std::pair< _Tp, _Val > x); 00038 ~MinHeap() {} 00039 00044 void push(std::pair< _Tp, _Val > x); 00045 00046 void pop(); 00047 00048 const std::pair< _Tp, _Val >& top() const; 00049 00057 bool set( _Tp& x, _Val& v); 00058 00064 // const _Val& get(_Tp& x) const; 00065 00066 // bool contains(_Tp& x) const; 00067 00068 bool empty() const; 00069 00070 int size() const; 00071 00072 // void clear(); 00073 00074 // bool erase(_Tp& x); 00075 00076 }; 00077 00078 template <class _Tp, class _Val> 00079 MinHeap<_Tp, _Val>::MinHeap( std::pair< _Tp, _Val > x) 00080 { 00081 data.push_back(x); 00082 obj_to_pos.insert(std::make_pair(x.first, 0)); 00083 } 00084 00085 template <class _Tp, class _Val> 00086 bool MinHeap<_Tp, _Val>::set(_Tp& x, _Val& v) 00087 { 00088 std::map<_Tp, int>::iterator it = obj_to_pos.find(x); 00089 if (it == obj_to_pos.end()) 00090 { 00091 push(std::make_pair(x, v)); 00092 return true; 00093 } 00094 int index = it->second; 00095 data[index].second = v; 00096 index = percolate_up(index); 00097 if (index >= 0 && index < (int)data.size()) 00098 { 00099 percolate_down(index); // if only we knew where to go (up/down) 00100 // normally for A*, we only go up when we set, and "up" when we push 00101 return true; 00102 } 00103 return false; 00104 } 00105 00106 template <class _Tp, class _Val> 00107 void MinHeap<_Tp, _Val>::push(std::pair< _Tp, _Val > x) 00108 { 00109 int index = data.size(); 00110 if (obj_to_pos.insert(std::make_pair(x.first, index)).second) 00111 { 00112 data.push_back(x); 00113 percolate_up(index); 00114 } 00115 } 00116 00117 template <class _Tp, class _Val> 00118 int MinHeap<_Tp, _Val>::percolate_up(int index) 00119 { 00120 if (index < 0 || index >= (int)data.size()) 00121 return -1; 00122 unsigned int parent = (index - 1) / 2; 00123 while (index > 0 && data[parent].second > data[index].second) 00124 { 00125 std::pair<_Tp, _Val> temp = data[parent]; 00126 data[parent] = data[index]; 00127 data[index] = temp; 00128 obj_to_pos.find(data[index].first)->second = index; 00129 index = parent; 00130 parent = (index - 1) / 2; 00131 } 00132 return index; 00133 } 00134 00135 template <class _Tp, class _Val> 00136 int MinHeap<_Tp, _Val>::percolate_down(int index) 00137 { 00138 if (index < 0 || index >= (int)data.size()) 00139 return -1; 00140 unsigned int lchild = index*2 + 1; 00141 unsigned int rchild = index*2 + 2; 00142 while ((data.size()>lchild && data[index].second>data[lchild].second) || 00143 (data.size()>rchild && data[index].second>data[rchild].second)) 00144 { 00145 unsigned int dest = lchild; 00146 if (data.size()>rchild && data[rchild].second<data[lchild].second) 00147 dest = rchild; 00148 std::pair< _Tp, _Val > temp = data[dest]; 00149 data[dest] = data[index]; 00150 data[index] = temp; 00151 obj_to_pos.find(data[index].first)->second = index; 00152 index = dest; 00153 lchild = index*2 + 1; 00154 rchild = index*2 + 2; 00155 } 00156 obj_to_pos.find(data[index].first)->second = index; 00157 return index; 00158 } 00159 00160 template <class _Tp, class _Val> 00161 bool MinHeap<_Tp, _Val>::empty() const 00162 { 00163 return data.empty(); 00164 } 00165 00166 template <class _Tp, class _Val> 00167 const std::pair<_Tp, _Val>& MinHeap<_Tp, _Val>::top() const 00168 { 00169 return data.front(); 00170 } 00171 00172 template <class _Tp, class _Val> 00173 int MinHeap<_Tp, _Val>::size() const 00174 { 00175 return data.size(); 00176 } 00177 00178 template <class _Tp, class _Val> 00179 void MinHeap<_Tp, _Val>::pop() 00180 { 00181 if (data.empty()) 00182 return; 00183 obj_to_pos.erase(data.front().first); 00184 data.front() = data.back(); 00185 data.pop_back(); 00186 if (data.empty()) 00187 return; 00188 std::map<_Tp, int>::iterator it = obj_to_pos.find(data.front().first); 00189 if (it != obj_to_pos.end()) 00190 { 00191 it->second = 0; 00192 percolate_down(0); 00193 } 00194 }