C++数据结构--用向量数组实现大(小)根堆的插入和删除
来源:互联网 发布:网络男歌手名字大全 编辑:程序博客网 时间:2024/06/05 19:25
1.基于数组的二叉树
例如,可以用向量数组{5,1,3,9,6,2,4,7,0,8}表示下图的完全二叉树
Tips:
对于结点v[i],可利用下列公式计算其子结点和父结点
左结点:v[2*i+1]
右结点:v[2*i+2]
父结点: v[int((i-1)/2] <==> v[(i-1)/2] 因为i为整数
2.大根堆:父结点总是大于或等于它的每个子结点
小根堆:父结点总是小于或等于它的每个子结点
example:
3.大根堆的插入操作
Example:在大根堆插入50
调整大根堆
4从对中删除堆中的根节点元素
Example:
step1: 把根结点和最后一个结点交换
step2:调整
实现代码:
#include <iostream>
#include<vector>
#include<functional>
using namespace std;
template<typename T,typename compare>
/*v为向量数组
*last为向量数组的size(),
*此算法假设[0,last-2]范围是已经调整好了的大根堆
*cp为比较函数对象,例如:当greater_equal<int> ge时实现大根堆
*当less_equal<int> le时实现小根堆
*/
void insertHeap(vector<T> &v,int last,compare cp=compare())
{
int currPos=last-1; //当前结点索引
int prtPos=(currPos-1)/2; //父结点索引
T target=v[last-1]; //保存将要被调整的目标结点
while(currPos)//当currPos!=0
{
if(cp(target,v[prtPos]))
{
v[currPos]=v[prtPos]; //用父结点的值覆盖当前结点
currPos=prtPos; //改变当前结点索引为父结点,继续向上查找
prtPos=(currPos-1)/2;
}
else //找到了正确位置,跳出循环
{
break;
}
}
v[currPos]=target; //把被调整的目标结点放到正确的位置
}
template<typename T,typename compare>
/*此算法假设v[first,last-1]范围内只有v[fisrt]需要被调整
*fisrt为需要被调整的结点索引
*last为向量数组中可能被调整结点的最后一个节点的下标+1
*/
void adjustHeap(vector<T> &v,int first,int last,compare cp=compare())
{
int prtPos=first; //当前父结点索引
int chilPos=2*prtPos+1; //左结点或右节点索引
T target=v[first]; //将要被调整的结点
while(chilPos<=last-1)
{
if((chilPos+1<=last-1)&&cp(v[chilPos+1],v[chilPos]))//如果存在左右结点,则找出符合条件的结点
{
chilPos=chilPos+1;
}
if(cp(v[chilPos],target))//当前父结点和孩子结点
{
v[prtPos]=v[chilPos];
prtPos=chilPos;//继续向下查找
chilPos=2*prtPos+1;
}
else //找到了正确位置,跳出循环
{
break;
}
}
v[prtPos]=target; //把被调整的目标结点放到正确的位置
}
template<typename T,typename compare>
//删除堆中的根结点
//可能需要调整的范围[0,v.size()-2]
//last为向量数组的size()
void popHeap(vector<T> &v,int last,compare cp=compare())
{
T tem=v[0]; //交换根结点和最后一个节点
v[0]=v[last-1];
v[last-1]=tem;
adjustHeap(v,0,last-1,cp); //重新调整堆
}
测试代码
int main(int argc, char** argv)
{
int arr[]{20,25,22,10,5,11,55,52,50};
vector<int> vec;
for(int x:arr) //vec每插入一个元素,就调用insertHeap来构建堆
{
vec.push_back(x);
insertHeap(vec,vec.size(),greater_equal<int>());
}
while(!vec.empty()) //每删除一个根结点就重新调整堆
{
popHeap(vec,vec.size(),greater_equal<int>());
cout<<vec.back()<<ends;
vec.pop_back();
}
return 0;
}
output:
55 52 50 25 22 20 11 10 5
例如,可以用向量数组{5,1,3,9,6,2,4,7,0,8}表示下图的完全二叉树
Tips:
对于结点v[i],可利用下列公式计算其子结点和父结点
左结点:v[2*i+1]
右结点:v[2*i+2]
父结点: v[int((i-1)/2] <==> v[(i-1)/2] 因为i为整数
2.大根堆:父结点总是大于或等于它的每个子结点
小根堆:父结点总是小于或等于它的每个子结点
example:
3.大根堆的插入操作
Example:在大根堆插入50
调整大根堆
4从对中删除堆中的根节点元素
Example:
step1: 把根结点和最后一个结点交换
step2:调整
实现代码:
#include <iostream>
#include<vector>
#include<functional>
using namespace std;
template<typename T,typename compare>
/*v为向量数组
*last为向量数组的size(),
*此算法假设[0,last-2]范围是已经调整好了的大根堆
*cp为比较函数对象,例如:当greater_equal<int> ge时实现大根堆
*当less_equal<int> le时实现小根堆
*/
void insertHeap(vector<T> &v,int last,compare cp=compare())
{
int currPos=last-1; //当前结点索引
int prtPos=(currPos-1)/2; //父结点索引
T target=v[last-1]; //保存将要被调整的目标结点
while(currPos)//当currPos!=0
{
if(cp(target,v[prtPos]))
{
v[currPos]=v[prtPos]; //用父结点的值覆盖当前结点
currPos=prtPos; //改变当前结点索引为父结点,继续向上查找
prtPos=(currPos-1)/2;
}
else //找到了正确位置,跳出循环
{
break;
}
}
v[currPos]=target; //把被调整的目标结点放到正确的位置
}
template<typename T,typename compare>
/*此算法假设v[first,last-1]范围内只有v[fisrt]需要被调整
*fisrt为需要被调整的结点索引
*last为向量数组中可能被调整结点的最后一个节点的下标+1
*/
void adjustHeap(vector<T> &v,int first,int last,compare cp=compare())
{
int prtPos=first; //当前父结点索引
int chilPos=2*prtPos+1; //左结点或右节点索引
T target=v[first]; //将要被调整的结点
while(chilPos<=last-1)
{
if((chilPos+1<=last-1)&&cp(v[chilPos+1],v[chilPos]))//如果存在左右结点,则找出符合条件的结点
{
chilPos=chilPos+1;
}
if(cp(v[chilPos],target))//当前父结点和孩子结点
{
v[prtPos]=v[chilPos];
prtPos=chilPos;//继续向下查找
chilPos=2*prtPos+1;
}
else //找到了正确位置,跳出循环
{
break;
}
}
v[prtPos]=target; //把被调整的目标结点放到正确的位置
}
template<typename T,typename compare>
//删除堆中的根结点
//可能需要调整的范围[0,v.size()-2]
//last为向量数组的size()
void popHeap(vector<T> &v,int last,compare cp=compare())
{
T tem=v[0]; //交换根结点和最后一个节点
v[0]=v[last-1];
v[last-1]=tem;
adjustHeap(v,0,last-1,cp); //重新调整堆
}
测试代码
int main(int argc, char** argv)
{
int arr[]{20,25,22,10,5,11,55,52,50};
vector<int> vec;
for(int x:arr) //vec每插入一个元素,就调用insertHeap来构建堆
{
vec.push_back(x);
insertHeap(vec,vec.size(),greater_equal<int>());
}
while(!vec.empty()) //每删除一个根结点就重新调整堆
{
popHeap(vec,vec.size(),greater_equal<int>());
cout<<vec.back()<<ends;
vec.pop_back();
}
return 0;
}
output:
55 52 50 25 22 20 11 10 5
- C++数据结构--用向量数组实现大(小)根堆的插入和删除
- 数据结构—堆的学习:堆化数组、堆的插入、堆的删除
- 堆插入和删除的简单实现
- 实现最大堆的插入和删除!
- 堆的插入删除实现和优化
- 最小堆的插入、删除和创建的C语言实现
- c++实现数组的插入和删除
- java实现堆的操作(建堆,插入,删除)
- 【数据结构】最大堆的插入与删除
- 【数据结构】C语言实现链表节点的插入和删除
- 数据结构和算法分析c++:向量的实现
- 数组实现“堆”(数据结构)
- 数据结构 单链表插入删除操作(c语言实现)
- 数据结构Java实现 --单向链表的插入和删除
- 平衡二叉树的C语言实现(创建、插入、查找、删除、旋转)【数据结构】
- 最小堆的调整、插入和删除
- 最大堆的插入,删除和初始化
- 最大堆的创建、插入和删除
- poj 1611 (并查集)
- 栈和队列
- OO设计原则
- cocos2d-x中的模态对话框
- Ubuntu在恢复模式下无法修改文件
- C++数据结构--用向量数组实现大(小)根堆的插入和删除
- 常用排序算法--归并排序
- SAP移动类型路径
- intent intent-filter
- 【rmzt:进击的巨人三笠xp主题】
- Mysql 远程连接
- ZStack串口操作
- 常用排序算法--快速排序
- java集合类详解