数据结构 堆
来源:互联网 发布:交通枢纽大数据 编辑:程序博客网 时间:2024/05/18 13:11
堆的概念:
优先队列: 特殊的队列,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的顺序
堆:实现用完全二叉树进行实现
堆的特性: 堆必须是一棵完全二叉树
大顶堆:一棵二叉树中所有的节点都是其子树节点中的最大值
小顶堆:一棵二叉树中所有的节点都是其子树节点中的最小值
堆的插入:
如图所示 这是一个大顶堆
在6处插入一个新的元素
如果插入的是20,符合大顶堆的规则,此时不用发生变换
如果插入的是35 35要大于31,不符合大顶堆的规则,此时将35与31交换
如果插入的是58 58要大于31且大于44,不符合规则,此时发生两次交换,最终58成为堆顶
注:在编写程序前,需要明确一个知识点,如果一个节点的编号是i 则它的父节点的编号为i/2
证明如下:
(1)假设子节点为第K层的第2M个结点。
则其父节点为第K-1层的第M个结点。
根据二叉树的特性,满二叉树的第K层共有2^K-1个节点,则父节点为全二叉树的第t=2^(K-2)-1+M个节点。子节点为全二叉树的第i=2^(K-1)-1+2M。即父结点编号为t=(i-1)/2=i/2。
(2)假设子节点为第K层的第2M+1个结点。
则其父节点为第K-1层的第M+1个结点。
则父结点为全二叉树的第t=2^(K-2)-1+M+1=2^(K-2)+M个结点。子节点为全二叉树的第i=2^(K-1)-1+2M+1=2^(K-1)+2M个结点。即父结点编号为t=i/2
从而得证。
插入程序:
void MaxHeap::Insert(Elementype item) {int i; //初始插入位置if (IsFull()) {cout << "the heap has been full!" << endl;return;}i = ++size; //先比较 后插入for (; heapData[i / 2] < item; i /= 2) { //如果父节点比子节点小 则交换位置 同时将节点位置调整为父节点heapData[i] = heapData[i/2];}heapData[i] = item; //节点入位置return;}
最大堆的删除:
(1)先从堆中取出顶部,比如这个堆的顶是58,则取出58用于返回
(2)将堆中的最后一个元素移动到堆顶
(3)31和左右两子进行比较 如果比孩子小 则进行交换(这里比44要小),则和44进行交换
(4)31到了[2]这个位置,此时31比35要小 将31和35进行交换
(5)最终31移动到了[4]这个位置
Elementype MaxHeap::deleteMaxHeap() {int Parent, Child;Elementype MaxItem, temp; //MaxItem 用来暂存顶部的元素 temp用来移动Parent = 1;Child = 0;if (IsEmpty()) {cout << "The heap has been empty!!" << endl;return NULL;}MaxItem = heapData[1]; //堆顶temp = heapData[size--]; //用来暂存数据for (; Parent * 2 <= size; Parent = Child) { //将Parent设置为1 从顶部开始 进行比较Child = Parent * 2; //先调整成左节点//先判断左右子哪个更大if ((Child < size) && (heapData[Child] < heapData[Child + 1]))Child++; if (temp >= heapData[Child])break; //找到合适的位置 退出循环else heapData[Parent] = heapData[Child]; //Parent用子节点代替}heapData[Parent] = temp;return MaxItem; //返回底部最大值}
最大堆的构建:
(1)先从最后一个带子节点的元素开始(最后一个顶元素,这里是87)
(2)将87调整成大顶堆(调整方法与删除一样)
(3)然后遍历 依次将30->83->83->43->66->调成大顶堆
void MaxHeap::adjustMent(int i) {int Parent, Child; //调整父节点 子节点Parent = i; if (IsEmpty()) {cout << "The heap has been empty!" << endl;return;}Elementype HeapTop = heapData[i]; //取出根节点用于比较for (; HeapTop * 2 <= size; Parent = Child) {Child = Parent * 2;if ((Child < size) && (heapData[Child] < heapData[Child + 1]))Child++;if (HeapTop >= heapData[Child])break;elseheapData[HeapTop] < heapData[Child];}heapData[Parent] = HeapTop;}void MaxHeap::adjustMentHeap() {int i = size/2; //从最后一个节点的根节点开始for (; i > 0; i--) {adjustMent(i);}}
整个程序架构如下
#include <iostream>#include <algorithm>#include <stdlib.h>#define MAXSIZE 100001#define MAXDATA 999999using namespace std;class HeapNode;typedef int Elementype;class MaxHeap {public:Elementype *heapData;int size; //当前数组元素个数int capacity; //数组容量public:MaxHeap(int MaxSize) {heapData = new Elementype[MaxSize]; //申请内存空间size = 0;capacity = MaxSize;heapData[0] = MAXDATA; //哨兵节点}/*操作结合*/bool IsFull(); //判断是否为满void Insert(Elementype item); //插入一个元素bool IsEmpty(); //判断是否为空Elementype deleteMaxHeap(); //弹出一个最大元素void adjustMent(int i); //调整void adjustMentHeap(); //调整整个堆};bool MaxHeap::IsFull() { //判断为满if (size == capacity)return true;return false;}bool MaxHeap::IsEmpty() { //判断为空if (size == 0)return true;return false;}void MaxHeap::Insert(Elementype item) {int i; //初始插入位置if (IsFull()) {cout << "the heap has been full!" << endl;return;}i = ++size; //先比较 后插入for (; heapData[i / 2] < item; i /= 2) { //如果父节点比子节点小 则交换位置 同时将节点位置调整为父节点heapData[i] = heapData[i/2];}heapData[i] = item; //节点入位置return;}Elementype MaxHeap::deleteMaxHeap() {int Parent, Child;Elementype MaxItem, temp; //MaxItem 用来暂存顶部的元素 temp用来移动Parent = 1;Child = 0;if (IsEmpty()) {cout << "The heap has been empty!!" << endl;return NULL;}MaxItem = heapData[1]; //堆顶temp = heapData[size--]; //用来暂存数据for (; Parent * 2 <= size; Parent = Child) { //将Parent设置为1 从顶部开始 进行比较Child = Parent * 2; //先调整成左节点//先判断左右子哪个更大if ((Child < size) && (heapData[Child] < heapData[Child + 1]))Child++; if (temp >= heapData[Child])break; //找到合适的位置 退出循环else heapData[Parent] = heapData[Child]; //Parent用子节点代替}heapData[Parent] = temp;return MaxItem; //返回底部最大值}void MaxHeap::adjustMent(int i) {int Parent, Child; //调整父节点 子节点Parent = i; if (IsEmpty()) {cout << "The heap has been empty!" << endl;return;}Elementype HeapTop = heapData[i]; //取出根节点用于比较for (; HeapTop * 2 <= size; Parent = Child) {Child = Parent * 2;if ((Child < size) && (heapData[Child] < heapData[Child + 1]))Child++;if (HeapTop >= heapData[Child])break;elseheapData[HeapTop] < heapData[Child];}heapData[Parent] = HeapTop;}void MaxHeap::adjustMentHeap() {int i = size/2; //从最后一个节点的根节点开始for (; i > 0; i--) {adjustMent(i);}}int main() {MaxHeap aaa(100);aaa.Insert(10);aaa.Insert(20);aaa.Insert(30);aaa.Insert(40); aaa.Insert(50);system("PAUSE");return 0;}
- 数据结构:堆
- 数据结构-堆
- 堆数据结构
- 堆数据结构
- 数据结构:堆
- 数据结构-堆
- 数据结构-堆
- 数据结构 堆
- 数据结构--堆
- 数据结构:堆
- 数据结构:堆
- 数据结构--堆
- 堆数据结构
- 数据结构- 堆
- 数据结构:堆
- 【数据结构】堆
- 数据结构--堆
- 数据结构-堆
- JavaScript面试题
- mybatis 数据库配置
- PCA的数学原理
- 使用网易提供的YUM服务
- Angular购物车的完整版
- 数据结构 堆
- struts2上转文件:
- 类的定义
- 在Linux下彻底删除掉mysql
- XML DOM解析文档 获取文本DoM4j实现增删改
- 柱形图中求最大四边形面积
- NOIp2016 题解
- 逃离焦油坑的伟大尝试——《人月神话》推荐
- 定义函数