您的位置:首页 > 编程语言

STL堆算法性能分析与优化方法(GCC4.4.2 stl_heap.h源代码分析与改进方案)

2009-11-28 17:03 771 查看
堆是常用的数据结构,经常用于实现优先队列中,huffman编码中的就用到了优先队列。

本质上就是用数组实现的完全二叉树保证父节点的关键码都大于或者等于其子节点的关键码(最大堆,反过来是最小堆),下图是一个最大堆示意。

代码

1 /**
2 * ==============================================================================
3 *
4 * \file makeheap_perf.cc
5 *
6 * \author chenghuige@gmail.com
7 *
8 * \date 2009-11-28 12:14:41.518985
9 *
10 * Description: 测试建立最大堆(注意这里仅仅测试最大堆,最小堆类似)
11 *
12 * 1.stl算法效率(gcc 4.4.2)
13 * 2.我修改后的算法效率及正确性(加入shift down函数)
14 * 我对原算法做了最小的修改,注意如果用最小堆,你还需要改
15 * 相应的带有防函数typname __Compare 模板参数的函数。
16 * g++ -O3 -o makeheap_perf makeheap_perf.cc -lgtest -I$BOOST_ROOT
17 *
18 * ==============================================================================
19 */
20
21 #include <iostream>
22 #include <algorithm>
23 #include <vector>
24 #include <gtest/gtest.h> //using google test
25 #include <boost/progress.hpp> //using boost timer
26 #include <ctime> // std::time
27 //using boost random
28 #include <boost/random/linear_congruential.hpp>
29 #include <boost/random/uniform_int.hpp>
30 #include <boost/random/uniform_real.hpp>
31 #include <boost/random/variate_generator.hpp>
32 #ifdef BOOST_NO_STDC_NAMESPACE
33 namespace std {
34 using ::time;
35 }
36 #endif
37 typedef boost::minstd_rand base_generator_type;
38 using namespace std;
39
40 //two global vector, we will use them as heap holder
41 vector<double> vec;
42 vector<double> vec1;
43 vector<double> vec2;
44 const int VecSize = 1024 *1024;
45 const int LoopTimes = 400;
46
47 //以0-1的随机浮点数填充
48 void init_vec() {
49 vec.resize(VecSize);
50 vec1.resize(VecSize);
51 vec2.resize(VecSize);
52
53
54 base_generator_type generator(42u);
55 boost::uniform_real<> uni_dist(0,1);
56 boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist);
57
58 for (int i = 0; i < VecSize; i++) {
59 vec[i] = uni();
60 }
61
62 }
63 //----------------------------------改写后的shift down 和建堆操作
64 //shift down 操作,将__first + __holeIndex位置的元素
65 //(其值为__value如果原来不是就相当于先赋值为__value)
66 //向下shift down,最远到达__first + len - 1位置
67 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
68 void shift_down(_RandomAccessIterator __first, _Distance __holeIndex,
69 _Distance __len, _Tp __value)
70 {
71 _Distance __secondChild = 2 * __holeIndex + 2; //右子节点index
72
73 while (__secondChild < __len) {
74 //执行后secondChild代表两个子节点中较大的节点
75 if ( *(__first + __secondChild) < *(__first + (__secondChild - 1)) )
76 __secondChild--;
77
78 //如果比子节点小
79 if ( __value < *(__first + __secondChild)) {
80 *(__first + __holeIndex) = *(__first + __secondChild);
81 __holeIndex = __secondChild; //继续shift down
82 __secondChild = 2 * __holeIndex+ 2;
83 }
84 else
85 break;
86 }
87
88 //最后一层可能存在只有左子节点情况
89 if (__secondChild == __len) {
90 __secondChild--;
91 if ( __value < *(__first + __secondChild)) {
92 *(__first + __holeIndex) = *(__first + __secondChild);
93 __holeIndex = __secondChild;
94 }
95 }
96
97 //将__value赋值到最后确定的位置
98 *(__first + __holeIndex) = __value;
99 }
100
101
102 template<typename _RandomAccessIterator>
103 void my_make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
104 {
105 typedef typename iterator_traits<_RandomAccessIterator>::value_type
106 _ValueType;
107 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
108 _DistanceType;
109
110 if (__last - __first < 2)
111 return;
112
113 const _DistanceType __len = __last - __first;
114 _DistanceType __parent = (__len - 2) / 2;
115 while (true)
116 {
117 shift_down(__first, __parent, __len,
118 _ValueType(*(__first + __parent)));
119 if (__parent == 0)
120 return;
121 __parent--;
122 }
123 }
124
125 //-------------改写后的删除操作
126 template<typename _RandomAccessIterator, typename _Tp>
127 inline void
128 __my_pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
129 _RandomAccessIterator __result, _Tp __value)
130 {
131 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
132 _Distance;
133 *__result = *__first;
134 shift_down(__first, _Distance(0), _Distance(__last - __first),
135 __value);
136 }
137
138 template<typename _RandomAccessIterator>
139 inline void
140 my_pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
141 {
142 typedef typename iterator_traits<_RandomAccessIterator>::value_type
143 _ValueType;
144
145 __my_pop_heap(__first, __last - 1, __last - 1,
146 _ValueType(*(__last - 1)));
147 }
148
149
150 //stl 自带的make_heap,以及pop_heap函数的性能测试,对vec1操作
151 void stl_make_heap() {
152 boost::progress_timer timer;
153 for (int i = 0; i < LoopTimes; i++) {
154 copy(vec.begin(), vec.end(), vec1.begin());
155 //建堆
156 make_heap(vec1.begin(), vec1.end());
157 ////逐次删除所有的堆中元素
158 //for (int j = 0; j < VecSize; j++) {
159 // pop_heap(vec1.begin(), vec1.end() - j);
160 //}
161
162 }
163 }
164
165 //修改后的my_make_heap,以及pop_heap函数测试,对vec2操作
166 void my_make_heap() {
167 boost::progress_timer timer;
168 for (int i = 0; i < LoopTimes; i++) {
169 copy(vec.begin(), vec.end(), vec2.begin());
170 //建堆
171 my_make_heap(vec2.begin(), vec2.end());
172 ////逐次删除所有的堆中元素
173 //for (int j = 0; j < VecSize; j++) {
174 // pop_heap(vec2.begin(), vec2.end() - j);
175 //}
176
177 }
178 }
179
180 //测试my_make_heap是否正确的建堆,及删除堆元素是否正确
181 void test_equal_vec() {
182 copy(vec.begin(), vec.end(), vec2.begin());
183 my_make_heap(vec2.begin(), vec2.end());
184 EXPECT_EQ(1, std::__is_heap(vec2.begin(), vec2.end()));
185 //测试删除堆元素操作是否正确
186 //int j;
187 //for (j = 0; j < VecSize/2 + 5; j++) {
188 // pop_heap(vec2.begin(), vec2.end() - j);
189 //}
190
191 //EXPECT_EQ(1, std::__is_heap(vec2.begin(), vec2.end()-j));
192 }
193
194 TEST(stl_make_heap, perf)
195 {
196 stl_make_heap();
197 }
198
199 TEST(my_make_heap, perf)
200 {
201 my_make_heap();
202 }
203
204 TEST(make_heap, func)
205 {
206 test_equal_vec();
207 }
208
209
210
211 int main(int argc, char *argv[])
212 {
213 init_vec();
214
215 testing::InitGoogleTest(&argc, argv);
216 return RUN_ALL_TESTS();
217 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: