堆
这几天准备把三种比较重要的数据结构整理下,分别是堆,AVL树,红黑树。今天谈谈堆吧。
简介:
https://baike.baidu.com/item/堆/20606834?fr=aladdin
简单的介绍百度百科上就有,他是一种二叉树形式的数据结构,主要是用来维护数据中的最小和最大值,且插入和删除操作的复杂度都为
O
(
l
o
g
n
)
O(logn)
O(logn). 二叉树相信大家都知道吧(不知道的朋友请先百度一下二叉树)。一个堆其实就是一颗二叉树,而且是平衡二叉树,这也就保证了插入和删除的复杂度。
堆分为最小堆和最大堆,以最小堆来阐述,最小堆满足一个特性,那就是父结点的值要比其左右子结点的来得小 ,最大堆同理。为了维护在对堆的插入和删除操作后破坏堆的特性,引入了两个调整的过程,分为向下调整和向上调整。具体一点的可以参考代码。(代码有点儿多,如有错误还请指出,谢谢)
C++代码实现
// 小学生一发的刷题之路
// 数据结构-堆
// 手动实现下最小堆;
//
//
#pragma comment(linker, "/STACK:1024000000,1024000000") //解决爆栈,手动加栈;
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <deque> //双向队列;
#include <cmath>
#include <set>
#include <stack>
#include <map>
#include <vector>
#include <cstdlib>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double PI=acos(-1.0);
const double eps=1e-10;
const int maxn=1e2+5;
const int maxm=1e3+5;
const ll mod=1e9+7;
const int INF=1e9;
const ll llINF=1e18;
template<class T>
inline void read(T &ret){ //快速输入模版;
ret=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ret=ret*10+c-'0';
c=getchar();
}
ret*=f;
}
template <class T>
inline void out(T ret){ //快速输出模版;
if(ret>9)
{
out(ret/10);
}
putchar(ret%10+'0');
}
template<class T>
class heap{
public:
heap(); //无参构造函数;
heap(int n); //带参构造函数;
T top()const{ return arr[0];}; //取堆顶元素;
void pop(); //删除堆顶元素;
void push(T x); //插入元素;
int size()const{ return CurrentSize;}; //返回堆的元素个数;
bool empty()const{ return CurrentSize==0?true:false;}; //判断堆是否为空;
void down(int start,int end); //向下调整;
void up(int start,int end); //向上调整;
void print(); //打印堆里面的元素;
private:
int MaxSize; //堆的最大容量;
int Currentpos; //当前的位置;
int CurrentSize; //当前的位置;
T arr[maxn];
};
template<class T>
heap<T>::heap(){
MaxSize=maxn;
CurrentSize=0;
}
template<class T>
heap<T>::heap(int n){
MaxSize=maxn;
CurrentSize=n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
Currentpos=(CurrentSize-2)/2; //找到调整结点;
while(Currentpos>=0){ //调整整棵树;
down(Currentpos,n-1);
Currentpos--;
}
}
template<class T>
void heap<T>::up(int start,int end){
//向上调整;
int i=start,j=(start-1)/2; //j为i的父结点;
while(j>=end){
if(i==0){ //避免出现死循环;
break;
}
if(arr[i]<arr[j]){
swap(arr[i],arr[j]);
}
i=j;
j=(i-1)/2;
}
}
template<class T>
void heap<T>::down(int start,int end){
//向下调整;
int i=start,j=2*start+1; //j为i左子结点;
while(j<=end){
if(j<end&&arr[j]>arr[j+1]){ //找到左右字数最小的点;
j++;
}
if(arr[j]<arr[i]){ //子结点的值小于父结点的值;
swap(arr[j],arr[i]);
}
i=j;
j=2*i+1;
}
}
template<class T>
void heap<T>::pop(){
if(CurrentSize==0){ //堆里面没有元素;
return;
}
arr[0]=arr[CurrentSize-1]; //把堆顶元素用最后一个元素代替;
CurrentSize--;
down(0,CurrentSize-1); //向下调整整棵树;
}
template<class T>
void heap<T>::push(T x){
if(CurrentSize==MaxSize){ //堆已满;
cout<<"堆已满,插入元素失败"<<endl;
return;
}
arr[CurrentSize]=x; //把元素插入到最后一个位置;
CurrentSize++;
up(CurrentSize-1,0); //向上调整整棵树;
}
template<class T>
void heap<T>::print(){ //打印堆里面的元素;
for(int i=0;i<CurrentSize;i++){
cout<<arr[i]<<endl;
}
}
int main()
{
//测试堆的各个功能;
heap<int> node;
for(int i=1;i<=10;i++){
int x=rand();
node.push(x);
}
while(!node.empty()){
cout<<node.top()<<endl;
node.pop();
}
return 0;
}
新的开始,每天都要快乐哈!