码迷,mamicode.com
首页 > 其他好文 > 详细

关于heap的两三事

时间:2014-06-17 23:41:18      阅读:368      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   http   tar   

以下code 来源于 啊哈磊大神~ =-=

你可以百度  --- 啊哈磊 ---

都是 关于heap的一些操作...

 

向下调整:->

bubuko.com,布布扣
 1 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整 
 2 {
 3     int t,flag=0;//flag用来标记是否需要继续向下调整
 4     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
 5     while( i*2<=n && flag==0 )
 6     {       
 7         //首先判断他和他左儿子的关系,并用t记录值较小的结点编号
 8         if( h[ i] > h[ i*2] )
 9             t=i*2;
10         else
11             t=i;
12         //如果他有右儿子的情况下,再对右儿子进行讨论
13         if(i*2+1 <= n)
14         {
15             //如果右儿子的值更小,更新较小的结点编号 
16             if(h[ t] > h[ i*2+1])
17                 t=i*2+1;
18         }
19         //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的 
20         if(t!=i)
21         {
22             swap(t,i);//交换它们,注意swap函数需要自己来写
23             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
24         }
25         else
26             flag=1;//则否说明当前的父结点已经比两个子结点都要小了,不需要在进行调整了
27     }
28 }
View Code

 

向上调整:->

bubuko.com,布布扣
 1 void siftup(int i) //传入一个需要向上调整的结点编号i
 2 {
 3     int flag=0; //用来标记是否需要继续向上调整
 4     if(i==1)  return; //如果是堆顶,就返回,不需要调整了   
 5     //不在堆顶 并且 当前结点i的值比父结点小的时候继续向上调整
 6     while(i!=1 && flag==0)
 7     {
 8         //判断是否比父结点的小
 9         if(h[ i]<h[ i/2])
10             swap(i,i/2);//交换他和他爸爸的位置
11         else
12             flag=1;//表示已经不需要调整了,当前结点的值比父结点的值要大
13         i=i/2; //这句话很重要,更新编号i为它父结点的编号,从而便于下一次继续向上调整 
14     }
15 }
View Code

的确 很 易懂

 

两种方式对元素 进行堆排序:->

bubuko.com,布布扣
 1 #include <stdio.h>
 2 int h[ 101];//用来存放堆的数组
 3 int n;//用来存储堆中元素的个数,也就是堆的大小
 4 
 5 
 6 //交换函数,用来交换堆中的两个元素的值
 7 void swap(int x,int y)
 8 {
 9     int t;
10     t=h[ x];
11     h[ x]=h[ y];
12     h[ y]=t;
13 }
14 
15 
16 //向下调整函数
17 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整
18 {
19     int t,flag=0;//flag用来标记是否需要继续向下调整
20     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
21     while( i*2<=n && flag==0 )
22     {        
23         //首先判断他和他左儿子的关系,并用t记录值较小的结点编号
24         if( h[ i] > h[ i*2] )
25             t=i*2;
26         else
27             t=i;
28         //如果他有右儿子的情况下,再对右儿子进行讨论
29         if(i*2+1 <= n)
30         {
31             //如果右儿子的值更小,更新较小的结点编号  
32             if(h[ t] > h[ i*2+1])
33                 t=i*2+1;
34         }
35         //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的  
36         if(t!=i)
37         {
38             swap(t,i);//交换它们,注意swap函数需要自己来写
39             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
40         }
41         else
42             flag=1;//则否说明当前的父结点已经比两个子结点都要小了,不需要在进行调整了
43     }
44 }
45 
46 
47 //建立堆的函数
48 void creat()
49 {
50     int i;
51     //从最后一个非叶结点到第1个结点依次进行向上调整
52     for(i=n/2;i>=1;i--)
53     {
54         siftdown(i);
55     }  
56 }
57 
58 
59 //删除最大的元素
60 int deletemax()
61 {
62     int t;
63     t=h[ 1];//用一个临时变量记录堆顶点的值
64     h[ 1]=h[ n];//将堆得最后一个点赋值到堆顶
65     n--;//堆的元素减少1
66     siftdown(1);//向下调整
67     return t;//返回之前记录的堆得顶点的最大值
68 }
69 
70 
71 int main()
72 {
73     int i,num;
74     //读入数的个数
75     scanf("%d",&num);
76 
77 
78     for(i=1;i<=num;i++)
79         scanf("%d",&h[ i]);
80     n=num;   
81 
82     //建堆
83     creat();
84 
85     //删除顶部元素,连续删除n次,其实夜就是从大到小把数输出来
86     for(i=1;i<=num;i++)
87         printf("%d ",deletemax());
88     getchar();
89     getchar();
90     return 0;
91 }
View Code
bubuko.com,布布扣
 1 #include <stdio.h>
 2 int h[ 101];//用来存放堆的数组
 3 int n;//用来存储堆中元素的个数,也就是堆的大小
 4 
 5 
 6 //交换函数,用来交换堆中的两个元素的值
 7 void swap(int x,int y)
 8 {
 9     int t;
10     t=h[ x];
11     h[ x]=h[ y];
12     h[ y]=t;
13 }
14 
15 
16 //向下调整函数
17 void siftdown(int i) //传入一个需要向下调整的结点编号i,这里传入1,即从堆的顶点开始向下调整
18 {
19     int t,flag=0;//flag用来标记是否需要继续向下调整
20     //当i结点有儿子的时候(其实是至少有左儿子的情况下)并且有需要继续调整的时候循环窒执行
21     while( i*2<=n && flag==0 )
22     {        
23         //首先判断他和他左儿子的关系,并用t记录值较大的结点编号
24         if( h[ i] < h[ i*2] )
25             t=i*2;
26         else
27             t=i;
28         //如果他有右儿子的情况下,再对右儿子进行讨论
29         if(i*2+1 <= n)
30         {
31             //如果右儿子的值更大,更新较小的结点编号  
32             if(h[ t] < h[ i*2+1])
33                 t=i*2+1;
34         }
35         //如果发现最大的结点编号不是自己,说明子结点中有比父结点更大的  
36         if(t!=i)
37         {
38             swap(t,i);//交换它们,注意swap函数需要自己来写
39             i=t;//更新i为刚才与它交换的儿子结点的编号,便于接下来继续向下调整
40         }
41         else
42             flag=1;//则否说明当前的父结点已经比两个子结点都要大了,不需要在进行调整了
43     }
44 }
45 
46 
47 //建立堆的函数
48 void creat()
49 {
50     int i;
51     //从最后一个非叶结点到第1个结点依次进行向上调整
52     for(i=n/2;i>=1;i--)
53     {
54         siftdown(i);
55     }  
56 }
57 
58 
59 //堆排序
60 void heapsort()
61 {
62         while(n>1)
63     {
64                 swap(1,n);
65         n--;
66         siftdown(1);
67     }
68 }
69 
70 
71 int main()
72 {
73     int i,num;
74     //读入n个数
75     scanf("%d",&num);
76 
77 
78     for(i=1;i<=num;i++)
79         scanf("%d",&h[ i]);
80     n=num;   
81 
82 
83     //建堆
84     creat();
85 
86 
87     //堆排序
88     heapsort();
89 
90 
91     //输出
92     for(i=1;i<=num;i++)
93         printf("%d ",h[ i]);
94 
95 
96     getchar();
97     getchar();
98     return 0;
99 }
View Code

 

真正理解一个东西  你可以将它以很简单的方式 讲解出来~

 

 

 

 

 

 

 

 

 

 

 

关于heap的两三事,布布扣,bubuko.com

关于heap的两三事

标签:style   class   blog   code   http   tar   

原文地址:http://www.cnblogs.com/radical/p/3793594.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!