大根堆,小根堆,堆排序
大根堆,小根堆,堆排序
大根堆: 根节点value不小于子节点的value,满足这条性质的二叉树即为大根堆。
小根堆:根节点value不大于子节点的value,满足这条性质的二叉树即为小根堆。
从大根堆的定义可知:在大根堆里要得到最大值只需o(1)的时间。所以很明显,大根堆可以求最大值和维护前k小的数。注意是前k小的数,不是前k大的数,因为当前要插入到堆里的数可以直接和堆里最大值考虑,如果比堆里最大的都还要小,那就那这个值放到堆里,这样就维护了前k小的数。
如果k很大的话,要划分为很多个堆。小根堆和大根堆相反。
堆的操作主要有:
bool isEmpty(int *a); // 判断堆是否为空
bool isFull(int *a); //判断堆是否为满
int top(int *a);// 返回堆顶元素
void pop(int *a);//删除堆顶元素
pop是删除堆顶元素,直接把最后面那个元素的值赋给堆顶,同时元素个数减一,然后是调整堆。
void push(int *a,int);//插入元素
push之前要判断空间是否为满,直接把value放到堆最后,然后是调整堆。
代码:
View Code
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6
7 #define maxSize 200008<<2
8 int heap[maxSize];
9
10 bool isEmpty( int * a);
11 bool isFull( int * a);
12 int top( int * a);
13 void pop( int * a);
14 void push( int *a, int );
15
16 template <typename T>
17 void Swap( T& a, T& b)
18 {
19 T tmp = a; a = b; b = tmp;
20 }
21
22 // 判空
23 bool isEmpty( int * a){
24 return a[ 0 ]<= 0 ? true : false ;
25 }
26 //
27 bool isFull( int * a){
28 return a[ 0 ]+ 1 >=maxSize? true : false ;
29 }
30
31 int top( int * a){
32 if (isEmpty(a) ) {
33 puts( " since for the heap is empty, the operation is illegel! " );
34 exit( 0 );
35 }
36 return heap[ 1 ];
37 };
38
39 // 调整堆,自上往下
40 void adjust( int * a ) {
41 int i = 1 ;
42 while ( i <= a[ 0 ] ){
43 if ((i<< 1 | 1 ) <= a[ 0 ] ) // 存在左右子树。
44 {
45 if (a[i<< 1 ] > a[i] && a[i<< 1 ]>a[i<< 1 | 1 ]){
46 Swap(a[i<< 1 ], a[i]); i <<= 1 ;
47 } else if (a[i<< 1 | 1 ] > a[i]) {
48 Swap(a[i<< 1 | 1 ], a[i]);
49 i = i<< 1 | 1 ;
50 } else break ;
51
52 } else if ( (i<< 1 ) <= a[ 0 ] ) { // 只存在左子树
53 if (a[i<< 1 ] > a[i]){
54 Swap(a[i<< 1 ], a[i]); i <<= 1 ;
55 } else break ;
56
57 } else break ;
58 }
59 }
60
61 void pop( int * a){
62 if (isEmpty(a) ) {
63 fprintf(stderr, " the heap is empty! " );
64 exit( 0 );
65 }
66 a[ 1 ] = a[a[ 0 ]-- ];
67 adjust(a);
68 }
69
70 void outPut( int * a){
71 puts( " ***********************************\n " );
72 if (isEmpty(a) ) puts( " the heap is empty! " );
73 else
74 {
75 for ( int i= 1 ; i<=a[ 0 ]; ++ i)
76 printf( " %d %d\n " , i, a[i]);
77 }
78 puts( " ***********************************\n " );
79 }
80
81 void push( int *a, int value){
82 if (isFull(a) ) {
83 fprintf(stderr, " the heap is full!\n " );
84 return ;
85 }
86 a[++a[ 0 ] ] = value;
87 int i = a[ 0 ]; // 调整堆,自下而上
88 while (i > 1 && a[i] > a[i/ 2 ]) {
89 Swap(a[i], a[i/ 2 ]); i >>= 1 ;
90 }
91 };
92
93 int main()
94 {
95 heap[ 0 ] = 0 ; // 记录元素个数;
96 printf( " push five intgers: " );
97 for ( int i= 0 , tmp; i< 5 ; ++ i ) {
98 scanf ( " %d " , & tmp);
99 push(heap, tmp); // 插入元素
100 }
101 outPut(heap); // 输出堆
102
103 int maxx = top(heap); // 取出堆的最大值
104 printf( " the maxx in current tree is %d \n " , maxx);
105
106 // 删除堆顶(最大值)
107 printf( " delete tha top node.\n " );
108 pop(heap);
109 outPut(heap);
110
111 printf( " 输入一个元素进行插入操作: " );
112 int tmp; scanf( " %d " , & tmp);
113 push(heap, tmp);
114 outPut(heap);
115
116 printf( " clear the heap.\n " );
117 while (! isEmpty(heap) ) pop(heap);
118 printf( " the size of the heap is %d\n " , heap[ 0 ]);
119
120 system( " pause " );
121 };
堆排序: 向大根堆中插入和删除元素的时间都是0(logn),根据这两个操作的时间,可以知道堆排序的时间复杂度为n*log(n). 堆排序思路: 在待排序的元素中建立大根堆,每次都把最大的取出来,这样就完成了排序。未完,待续。。。。
分类: 数据结构
标签: 数据结构 , 大根堆 , 小根堆 , 堆排序
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息