ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

堆之初步使用

2020-03-24 16:04:23  阅读:205  来源: 互联网

标签:结点 int 初步 maxsize num 二叉树 heap 使用


  上一篇博客我们讲了一种叫并查集的数据结构,这里我们再讲另外一种数据结构——堆。

  堆是一种能凸显最重要数据的数据结构(最大值或最小值)。

  首先,堆是由完全二叉树勾成的。什么是完全二叉树呢?进化到完全体的树状数码宝贝。完全二叉树是指如二叉树的高度为h,除h层外,其他各层(1到h-1层)的结点个数都达到最大,第h层的结点都连续集中分布在最左边。如图:

 

  同时,通过观察我们还发现对于结点x,它的父亲结点为x/2(若存在)(舍去小数部分),它的左右儿子结点分别为2x,2x+1(若存在)

  知道了完全二叉树的这两个特性,我们会发现,咦,我完全可以用数组模拟一个完全二叉树。没错,数组确实可以模拟完全二叉树,接下来我们就聊聊堆。

 

  堆分为大根堆与小根堆。对大根堆来说,对每一个结点都有:它的父亲结点的值比它大,它的儿子结点的值比它小。那么第一个节点存储的值就是整个堆里最大的值了。小根堆的特性与之相反。

  哦。原来这就是堆。那大根堆里第二个结点就是第二大的元素啦,最后一个结点就最小的元素啦。然而并不是这样,大根堆只是保证对每个结点,它的值大于它的儿子结点的值,小于它的父亲结点得值。也就是说,堆里的元素并不是按升序或降序排列的,堆仅仅是凸显了最重要的元素,使得大根堆的根结点为最大的元素,小根堆的结点为最小的元素。

 

  下面我们以大根堆为例,看看如何创建一个堆。

  首先是堆的创建,我们用push函数将一个新元素加入到堆中。

1 #define maxsize 3000000
2 
3 int heap[maxsize];
4 
5 void push(int x) {
6     num++;    //num代表当前堆中的元素数量
7     heap[num] = x;
8     up(num);
9 }

   咦,为什么出现了一个奇怪的up函数。我们直接把x放在第num个节点中,但第num个结点不一定遵循堆的特性,为了维护堆的特性,我们必须让x上浮。怎样上浮呢?如果x的值大于它的父亲结点的值,那么就交换它和它的父亲结点,直到它的值小于它的父亲结点或已经是根结点为止。

 1 #define maxsize 3000000
 2 
 3 int heap[maxsize];
 4 
 5 void up(int x) {
 6     while (x/2 > 0) {    //如果x/2<=0,说明x已经是根结点了,不能再上浮了
 7         if (heap[x] > heap[x/2]) {
 8             swap(&heap[x], &heap[x/2]);
 9             x = x / 2;
10         }
11         else {
12             break;
13         }
14     }
15 }

  这里出现的swap函数是一个简单的交换函数,相信大家都能实现(如果不能实现,建议先学好基础,暂时不学习堆)。

  学会了怎么把数据读入堆的小茗又犯愁了,我该怎么把根结点从堆中弹出呢?这时候就需要一个pop函数了。

1 #define maxsize 3000000
2 
3 int heap[maxsize];
4 
5 void pop() {
6     heap[1] = heap[num];
7     num--;
8     down(1);
9 }

  这里我们将最后一个结点的值赋值给根结点,根结点就被覆盖了。同时num--,原来的第num个结点就在范围外了。但原来的num结点不一定是堆中最大的元素,为了维护堆,我们就让这个结点下沉,直到它的值大于它的儿子结点或它没有儿子结点。

 1 #define maxsize 3000000
 2 
 3 int heap[maxsize];
 4 
 5 void down(int x) {
 6     while (x*2 <= num) {
 7         int maxson = 2*x;
 8         if (maxson+1 <= num && heap[maxson+1] > heap[maxson]) {
 9             maxson++;
10         }
11 
12         if (heap[maxson] > heap[x]) {
13             swap(&heap[maxson], &heap[x]);
14             x = maxson;
15         }
16         else {
17             break;
18         }
19     }
20 }

  这样,我们就基本实现了堆的基本功能,我们就能随时查看堆中最重要的值了。

1 #define maxsize 3000000
2 
3 int heap[maxsize];
4 
5 int gettop() {
6     return heap[1];
7 }

  怎么样,堆这种数据结构你学废了学会了吗?

 

标签:结点,int,初步,maxsize,num,二叉树,heap,使用
来源: https://www.cnblogs.com/zymmyz/p/12559484.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有