关于heap的两三事

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

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

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

向下调整:->

 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 }

向上调整:->

 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 }

的确 很 易懂

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

 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 }

 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 }

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

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

时间: 2024-11-05 12:31:25

关于heap的两三事的相关文章

通用的最小堆(最大堆)D-ary Heap

听说有一种最小(大)堆,不限于是完全二叉树,而是完全D叉树,名为D-ary Heap(http://en.wikipedia.org/wiki/D-ary_heap).D可以是1,2,3,4,100,对于优先队列该有的功能都没有问题. 动手写一个D-ary Heap,应该不难.简单起见,不考虑像STL一样通过template传入Comp类,下面的实现要求T类型重载了operator <和operator >. template<class T> class DaryHeap { s

ZOJ - 2243 - Binary Search Heap Construction

先上题目: Binary Search Heap Construction Time Limit: 5 Seconds      Memory Limit: 32768 KB Read the statement of problem G for the definitions concerning trees. In the following we define the basic terminology of heaps. A heap is a tree whose internal n

[Java Basics] Stack, Heap, Constructor

Good about Java: friendly syntax, memory management[GC can collect unreferenced memory resources], object-oriented features, portability. Stack Stores method invocations, local variables(include object reference, but the object itself is still stored

二叉堆(binary heap)

堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权.堆即为解决此类问题设计的一种数据结构. 本文地址:http://www.cnblogs.com/archimedes/p/binary-heap.html,转载请注明源地址. 逻辑定义 n个

Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法

java.lang.OutOfMemoryError: Java heap space 的解决方法 关键字: tomcat outofmemoryerror permgen space java heap space 最近在熟悉一个开发了有几年的项目,需要把数据库从mysql移植到oracle,首先把jdbc的连接指向mysql,打包放到tomcat里面,可以跑起来,没有问题,可是当把jdbc连接指向oracle的时候,tomcat就连续抛java.lang.OutOfMemoryError的错

poj1258 Agri-Net (prim+heap)

题目链接:poj1258 Agri-Net 这题我上个月做过,是个大水题,今天看见有人用prim+heap做的,就学习了下. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #include<vector> 6 #include<set> 7 #define CLR(a,b) memset((a),(b),sizeof((

heap&amp;stack的区别

1. heap (堆)是一个可动态申请的内存空间,一般所有创建的对象和数组都放在这里.stack (栈)是一个先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量.stack (栈)的空间小,但速度比较快, 存放对象的引用,通过栈中的地址索引可以找到堆中的对象. 2. stack的空间由操作系统自动分配和释放, heap的空间是手动申请和释放的,heap常用new关键字来分配. stack空间有限,heap的空间是很大的自由区. 在Java中, 若只是声明一个对象,则先在栈内存中为其分

C语言错误: CRT detected that the application wrote to memory after end of heap buffer

CRT detected that the application wrote to memory after end of heap buffer 多是中间对其进行了一些操作,在程序结束处,释放内存的时候,引起错误: HEAP CORRUPTION DETECTED:after Normal block(#***) at 0x****.CRT detected that application wrote memory after end of heap buffer. 错误原因: 以对内在操

堆排序(Heap Sort)的C语言实现

堆排序(Heap Sort)具体步骤为 将无序序列建成大顶堆(小顶堆):从最后一个非叶子节点开始通过堆调整HeapAdjust()变成小顶堆或大顶堆 将顶部元素与堆尾数组交换,此是末尾元素就是最大值,顶部元素不满足堆,故要将顶部元素在剩余的i-1个元素中调整为堆 反复第2步.直至所有顶点被输出,序列变成从小到大的有序序列 C语言实现(编译器Dev-c++5.4.0,源代码后缀.cpp) 原创文章,转载请注明来自钢铁侠Mac博客http://www.cnblogs.com/gangtiexia 1