数据结构之二叉堆

二叉堆的介绍

二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆。

  • 最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
  • 最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

示意图如下:

二叉堆一般都通过”数组”来实现。数组实现的二叉堆,父节点和子节点的位置存在一定的关系。有时候,我们将”二叉堆的第一个元素”放在数组索引0的位置,有时候放在1的位置。当然,它们的本质一样(都是二叉堆),只是实现上稍微有一丁点区别。
假设”第一个元素”在数组中的索引为 0 的话,则父节点和子节点的位置关系如下:
(01) 索引为i的左孩子的索引是 (2*i+1);
(02) 索引为i的左孩子的索引是 (2*i+2);
(03) 索引为i的父结点的索引是 floor((i-1)/2);

实现

以最大堆为例

template <class T>
class MaxHeap{private:T *mHeap;        // 数据int mCapacity;    // 总的容量int mSize;        // 实际容量private:// 最大堆的向下调整算法void filterdown(int start, int end);// 最大堆的向上调整算法(从start开始向上直到0,调整堆)void filterup(int start);public:MaxHeap();MaxHeap(int capacity);~MaxHeap();// 返回data在二叉堆中的索引int getIndex(T data);// 删除最大堆中的dataint remove(T data);// 将data插入到二叉堆中int insert(T data);// 打印二叉堆void print();
};

添加

假设在最大堆[90,80,70,60,40,30,20,10,50]种添加85,需要执行的步骤如下

如上图所示,当向最大堆中添加数据时:先将数据加入到最大堆的最后,然后尽可能把这个元素往上挪,直到挪不动为止!
将85添加到[90,80,70,60,40,30,20,10,50]中后,最大堆变成了[90,85,70,60,80,30,20,10,50,40]。

/** 最大堆的向上调整算法(从start开始向上直到0,调整堆)** 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。** 参数说明:*     start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)*/
template <class T>
void MaxHeap<T>::filterup(int start)
{int c = start;            // 当前节点(current)的位置int p = (c-1)/2;        // 父(parent)结点的位置 T tmp = mHeap[c];        // 当前节点(current)的大小while(c > 0){if(mHeap[p] >= tmp)break;else{mHeap[c] = mHeap[p];c = p;p = (p-1)/2;   }       }mHeap[c] = tmp;
}/* * 将data插入到二叉堆中** 返回值:*     0,表示成功*    -1,表示失败*/
template <class T>
int MaxHeap<T>::insert(T data)
{// 如果"堆"已满,则返回if(mSize == mCapacity)return -1;mHeap[mSize] = data;        // 将"数组"插在表尾filterup(mSize);    // 向上调整堆mSize++;                    // 堆的实际容量+1return 0;
}

删除

假设从最大堆[90,85,70,60,80,30,20,10,50,40]中删除90,需要执行的步骤如下:

/* * 最大堆的向下调整算法** 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。** 参数说明:*     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)*     end   -- 截至范围(一般为数组中最后一个元素的索引)*/
template <class T>
void MaxHeap<T>::filterdown(int start, int end)
{int c = start;          // 当前(current)节点的位置int l = 2*c + 1;     // 左(left)孩子的位置T tmp = mHeap[c];    // 当前(current)节点的大小while(l <= end){// "l"是左孩子,"l+1"是右孩子if(l < end && mHeap[l] < mHeap[l+1])l++;        // 左右两孩子中选择较大者,即mHeap[l+1]if(tmp >= mHeap[l])break;        //调整结束else{mHeap[c] = mHeap[l];c = l;l = 2*l + 1;   }       }   mHeap[c] = tmp;
}/** 删除最大堆中的data** 返回值:*      0,成功*     -1,失败*/
template <class T>
int MaxHeap<T>::remove(T data)
{int index;// 如果"堆"已空,则返回-1if(mSize == 0)return -1;// 获取data在数组中的索引index = getIndex(data); if (index==-1)return -1;mHeap[index] = mHeap[--mSize];    // 用最后元素填补filterdown(index, mSize-1);        // 从index位置开始自上向下调整为最大堆return 0;
}

二叉堆的C++实现(完整源码)

/*** 二叉堆(最大堆)** @author skywang* @date 2014/03/07*/#include <iomanip>
#include <iostream>
using namespace std;template <class T>
class MaxHeap{private:T *mHeap;        // 数据int mCapacity;    // 总的容量int mSize;        // 实际容量private:// 最大堆的向下调整算法void filterdown(int start, int end);// 最大堆的向上调整算法(从start开始向上直到0,调整堆)void filterup(int start);public:MaxHeap();MaxHeap(int capacity);~MaxHeap();// 返回data在二叉堆中的索引int getIndex(T data);// 删除最大堆中的dataint remove(T data);// 将data插入到二叉堆中int insert(T data);// 打印二叉堆void print();
};/* * 构造函数*/
template <class T>
MaxHeap<T>::MaxHeap()
{new (this)MaxHeap(30);
}template <class T>
MaxHeap<T>::MaxHeap(int capacity)
{mSize = 0;mCapacity = capacity;mHeap = new T[mCapacity];
}
/* * 析构函数*/
template <class T>
MaxHeap<T>::~MaxHeap() 
{mSize = 0;mCapacity = 0;delete[] mHeap;
}/* * 返回data在二叉堆中的索引** 返回值:*     存在 -- 返回data在数组中的索引*     不存在 -- -1*/
template <class T>
int MaxHeap<T>::getIndex(T data)
{for(int i=0; i<mSize; i++)if (data==mHeap[i])return i;return -1;
}/* * 最大堆的向下调整算法** 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。** 参数说明:*     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)*     end   -- 截至范围(一般为数组中最后一个元素的索引)*/
template <class T>
void MaxHeap<T>::filterdown(int start, int end)
{int c = start;          // 当前(current)节点的位置int l = 2*c + 1;     // 左(left)孩子的位置T tmp = mHeap[c];    // 当前(current)节点的大小while(l <= end){// "l"是左孩子,"l+1"是右孩子if(l < end && mHeap[l] < mHeap[l+1])l++;        // 左右两孩子中选择较大者,即mHeap[l+1]if(tmp >= mHeap[l])break;        //调整结束else{mHeap[c] = mHeap[l];c = l;l = 2*l + 1;   }       }   mHeap[c] = tmp;
}/** 删除最大堆中的data** 返回值:*      0,成功*     -1,失败*/
template <class T>
int MaxHeap<T>::remove(T data)
{int index;// 如果"堆"已空,则返回-1if(mSize == 0)return -1;// 获取data在数组中的索引index = getIndex(data); if (index==-1)return -1;mHeap[index] = mHeap[--mSize];    // 用最后元素填补filterdown(index, mSize-1);        // 从index位置开始自上向下调整为最大堆return 0;
}/** 最大堆的向上调整算法(从start开始向上直到0,调整堆)** 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。** 参数说明:*     start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)*/
template <class T>
void MaxHeap<T>::filterup(int start)
{int c = start;            // 当前节点(current)的位置int p = (c-1)/2;        // 父(parent)结点的位置 T tmp = mHeap[c];        // 当前节点(current)的大小while(c > 0){if(mHeap[p] >= tmp)break;else{mHeap[c] = mHeap[p];c = p;p = (p-1)/2;   }       }mHeap[c] = tmp;
}/* * 将data插入到二叉堆中** 返回值:*     0,表示成功*    -1,表示失败*/
template <class T>
int MaxHeap<T>::insert(T data)
{// 如果"堆"已满,则返回if(mSize == mCapacity)return -1;mHeap[mSize] = data;        // 将"数组"插在表尾filterup(mSize);    // 向上调整堆mSize++;                    // 堆的实际容量+1return 0;
}/* * 打印二叉堆** 返回值:*     0,表示成功*    -1,表示失败*/
template <class T>
void MaxHeap<T>::print()
{for (int i=0; i<mSize; i++)cout << mHeap[i] << " ";
}int main()
{int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};int i, len=(sizeof(a)) / (sizeof(a[0])) ;MaxHeap<int>* tree=new MaxHeap<int>();cout << "== 依次添加: ";for(i=0; i<len; i++){cout << a[i] <<" ";tree->insert(a[i]);}cout << "\n== 最 大 堆: ";tree->print();i=85;tree->insert(i);cout << "\n== 添加元素: " << i;cout << "\n== 最 大 堆: ";tree->print();i=90;tree->remove(i);cout << "\n== 删除元素: " << i;cout << "\n== 最 大 堆: ";tree->print();cout << endl; system("pause");return 0;
}

效果如下

这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手术革命:这三家公司如何用AR技术辅助医疗手术

来源&#xff1a;资本实验室作为一种重要的职业&#xff0c;外科医生特别是手术医生需要具备丰富的专业知识&#xff0c;还需要掌握精准的手术操作技术&#xff0c;这都需要不断的学习与练习。受学习资料、手术练习材料等软硬件条件的制约&#xff0c;医生进行手术学习和手术操…

C# Socket初探

闲着无聊&#xff0c;写了个简单的C/S Socket程序&#xff0c;功能很简单&#xff0c;服务器在9000端口监听socket接入&#xff0c;只要有接入&#xff0c;就发送"Welcome."消息给客户端。 代码分2块&#xff0c;server端&#xff1a; class Program{static void Mai…

最新发布 | 2018年度第八届吴文俊人工智能科学技术奖获奖名单公示

来源&#xff1a;人工智能人物摘要&#xff1a;2018年度第八届吴文俊人工智能科学技术奖评审工作已经完成。根据《吴文俊人工智能科学技术奖励条例》和《吴文俊人工智能科学技术奖励实施细则》相关规定&#xff0c;经全国各地方人工智能学会、各高校及科研院所、团体会员单位和…

DNA存储:这些公司正在开启数据存储的未来

来源&#xff1a;资本实验室随着数字化时代的到来&#xff0c;可以毫不夸张地说&#xff0c;数据存储与安全正在成为整个社会正常运行的基础。同时&#xff0c;物联网、人工智能、虚拟现实、自动驾驶等新技术的应用则进一步大幅提升了数据存储要求。据IDC预测&#xff0c;到202…

React基础语法学习

React主要有如下3个特点&#xff1a; 作为UI&#xff08;Just the UI&#xff09;虚拟DOM&#xff08;Virtual DOM&#xff09;:这是亮点 是React最重要的一个特性 放进内存 最小更新的视图,差异部分更新 diff算法数据流&#xff08;Date Flow&#xff09;单向数据流 学习Re…

算力超英伟达?华为推出两款“昇腾”芯片;五大AI战略正式公布

来源&#xff1a;AI科技大本营华为也像是要 All in AI 了。10 月 10 日&#xff0c;华为全联接大会 2018 上&#xff0c;华为轮值董事长徐直军带来了一系列的硬核 AI。在大会上&#xff0c;他系统公布了华为的 AI 发展战略&#xff0c;以及全栈全场景 AI 解决方案&#xff0c;其…

英特尔人工智能副总裁:AI不是一种技能,而是一种对于工作的描述

来源&#xff1a;网络大数据人工智能领域的迅速发展&#xff0c;相关人才不能满足需求已经成为业界共识。有报道称&#xff0c;因为人工智能工程师庞大的缺口&#xff0c;一些公司为了获得人才不得不支付数百万美元的薪水。如何满足对人工智能工程师不断增长的招聘和培训的需求…

React Native实例

本文主要包括以下内容 View组件的实例 Text组件实例 Navigator组件实例 TextInput组件实例 View组件的实例 效果如下 代码如下 /*** Sample React Native App* https://github.com/facebook/react-native* flow*/import React, { Component } from react; import {AppRe…

谷歌的硬件梦:Pixel手机、ChromeOS平板和Home音箱

来源&#xff1a; 网易智能&#xff08;北京时间10月9日23点&#xff09;&#xff0c;谷歌在纽约如期举行了主题为“谷歌制造”&#xff08;Made By Google&#xff09;的硬件发布会&#xff0c;推出了Pixel手机、平板 笔记本&#xff0c;以及音箱等一系列新品硬件。一个月以来…

“万维网之父”发文阐述其下一个网络时代:将数据与应用分离,互联网去中心化正在路上...

来源&#xff1a;Deep Tech深科技关注“万维网之父”Tim Berners-Lee 动态的人&#xff0c;一定知道这位业内大神正在投身于下一代互联网的建设——一个去中心化的互联网。他正在领导其 MIT 团队搭建一个名为“ Solid ”&#xff08;Social Linked Data 社交关联数据&#xff0…

React Native官方DEMO

官方给我们提供了UIExplorer项目&#xff0c;这里边包含React Native的基本所有组件的使用介绍和方法。 运行官方DEMO步骤如下 安装react native环境 React Native项目源码下载下载安装cygwin软件 下载安装NDK然后安装以及配置 添加Node依赖模块:该命令行需要切到react-nati…

牛津教授揭秘AI革命及其前沿进展

来源&#xff1a;专知导读&#xff1a;2018年9月9日-14日&#xff0c;DeepMind主办的Deep Learning Indaba 2018大会在南非斯泰伦博斯举行。会上&#xff0c;牛津大学教授Nando de Freitas和其他15位专家做了《深度学习&#xff1a;AI革命及其前沿进展》的报告。报告导读&#…

数据结构之DFS与BFS实现

本文主要包括以下内容 邻接矩阵实现无向图的BFS与DFS 邻接表实现无向图的BFS与DFS 理论介绍 深度优先搜索介绍 图的深度优先搜索(Depth First Search)&#xff0c;和树的先序遍历比较类似。 它的思想&#xff1a;假设初始状态是图中所有顶点均未被访问&#xff0c;则从某…

一图分析华为最新AI生态与未来趋势

华为全联接大会2018年10月10日在上海召开&#xff0c;作为面向ICT产业的年度大会&#xff0c;华为公布了重要AI战略&#xff0c;将华为AI发展战略概括为以下五大方向&#xff1a;强力投资基础研究、打造全栈解决方案、投资开放生态和人才培养、解决方案增强以及内部效率提升。华…

在读博士的第八年,她破解了量子计算领域最基本的问题之一

来源&#xff1a;原理Urmila Mahadev&#xff08;厄米拉马哈德夫&#xff09;花了八年时间在研究生院解决了量子计算领域最基本的问题之一&#xff1a;怎么知道量子计算机是否做了量子计算呢&#xff1f;2017年春天&#xff0c;Urmila Mahadev发现自己处于大多数研究生都会认为…

React Native实例之房产搜索APP

React Native 开发越来越火了&#xff0c;web app也是未来的潮流, 现在react native已经可以完成一些最基本的功能. 通过开发一些简单的应用, 可以更加熟练的掌握 RN 的知识. 在学习的过程&#xff0c;发现了一个房产搜索APP的实例&#xff0c;但只有ios版本&#xff0c; 本文…

“间谍芯片”疑云:谁在撒谎?警示何在?

芯片级安全没有终点来演&#xff1a;科学网摘要&#xff1a;10月5日起&#xff0c;一则“苹果、亚马逊被卷入&#xff0c;中国黑客利用微芯片入侵美国”的消息不胫而走&#xff0c;消息所波及的中美科技企业的股价应声下跌。10月5日起&#xff0c;一则“苹果、亚马逊被卷入&…

Extjs4前端开发代码规范参考

准则&#xff1a; 一致性&#xff0c; 隔离与统一管理&#xff0c; 螺旋式重构改进&#xff0c; 消除重复&#xff0c; 借鉴现有方案 1. 保证系统实现的一致性&#xff0c;寻求一致性方案&#xff0c; 相同或相似功能尽量用统一模式处理&#xff1b; 2. 尽可能使用隔离技…

数据结构之最小生成树

prime算法 普里姆(Prim)算法&#xff0c;是用来求加权连通图的最小生成树的算法。 基本思想 对于图G而言&#xff0c;V是所有顶点的集合&#xff1b;现在&#xff0c;设置两个新的集合U和T&#xff0c;其中U用于存放G的最小生成树中的顶点&#xff0c;T存放G的最小生成树中…

打造无所不及的智能:徐直军发布华为AI战略及全栈全场景方案

来源&#xff1a;C114通信网摘要&#xff1a;选择正确的问题比寻找新奇的方案更重要。“这是一个伟大的时代&#xff0c;华为立志为推动人类进步和世界繁荣做出贡献。2017年底&#xff0c;我们提出了新的愿景和使命&#xff0c;‘把数字世界带入每个人、每个家庭、每个组织&…