二叉堆的实现

文章目录

  • 介绍
  • 实现原理
  • 代码实现(C++)
    • 最大堆
    • 最小堆

介绍

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

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

实现原理

1、二叉堆一般使用数组实现,如果从索引1开始存放元素,那么

  • i 的左孩子是2*i
  • i 的右孩子是2*i+1
  • i 的父节点 i/2

2、插入操作(最大堆)

当向最大堆中添加数据时,先将数据加入最大堆的最后(即数组中最后一个元素的下一个位置),然后尽可能把这个元素往上挪,直到挪不动为止。

3、删除操作(最大堆)

当从最大堆中删除数据时,先删除该数据,然后用最大堆中最后一个元素插入这个空位,然后把这个空位尽量向下挪,直到重新变为最大堆。

注意:最小堆相比最大堆的实现只需改动大小关系即可。

代码实现(C++)

最大堆

//最大堆 
 
#include
 
using namespace std;
 
template<class T> 
class MaxHeap{
	private:
		T *heap;//数据
		int capacity;//总的容量
		int size;//实际容量
		
		void down(int start,int end);//最大堆向下调整算法
		void up(int start);//最大堆向上调整算法
		
	public:
		MaxHeap();
		MaxHeap(int capacity); 
		~MaxHeap();
		int getIndex(T data);//返回data在二叉堆中的索引
		bool remove(T data);//删除最大堆中的data
		bool insert(T data);//将data插入二叉堆中
		void print();//打印二叉堆 
}; 
 
//构造函数 
template<class T>
MaxHeap<T>::MaxHeap(int capacity)
{
	this->capacity=capacity;
	this->size=0;
	heap=new T[this->capacity];
} 
 
template<class T>
MaxHeap<T>::MaxHeap()
{
	new (this)MaxHeap(30);
} 
 
//析构函数
template<class T>
MaxHeap<T>::~MaxHeap()
{
	size=capacity=0;
	delete[] heap;
}
 
//返回data在二叉堆的索引位置,如果不存返回-1 
template<class T>
int MaxHeap<T>::getIndex(T data)
{
	for(int i=1;i<=size;i++)
	  if(heap[i]==data)
	    return i;
	return -1;
}
 
//最大堆的向上调整算法 
template<class T>
void MaxHeap<T>::up(int start)//start上调的开始位置 
{
	int c=start;
	T temp=heap[c];
	int p=c/2;//p是c的父节点
	while(p>0)
	{
		if(temp<=heap[p])
		  break;//上调结束
		else
		{
			heap[c]=heap[p];
			c=p;
			p=p/2;
		} 
	}
	heap[c]=temp; 
}
 
//插入值为data的元素 
template<class T>
bool MaxHeap<T>::insert(T data)
{
	if(size==capacity)//堆已满,添加失败,返回false 
	  return false;
	heap[++size]=data;//将数据插在最后
	up(size);//上调元素 
	return true; 
}
 
/*
最大堆的向下调整算法 
start:被下调节点的起始位置
end:数组的最后一个元素的位置 
*/ 
 
template<class T>
void MaxHeap<T>::down(int start,int end)
{
	int c=start;//c表示当前结点的位置 
	T temp=heap[c];//当前结点的值 
	int l=2*c;//c的左孩子
	//进行下调
	while(l<=end)
	{
		// l是左孩子,l+1是右孩子
		if(l<end&&heap[l]<heap[l+1])
		  l++;//左右两个孩子中选择较大者
		if(temp>=heap[l])//下调结束 
		  break; 
		else
		{
			heap[c]=heap[l]; 
			c=l;
			l=l*2;
		}
	}
	heap[c]=temp; 
}
 
//删除值为data的元素 
template<class T>
bool MaxHeap<T>::remove(T data)
{
	//获取data在数组中的索引
	int index=getIndex(data);
	if(index==-1)//未找到 ,删除失败,返回false 
	  return false;
	heap[index]=heap[size--];//用最后元素填补index位置
	down(index,size);//从index位置开始自上而下调整为最大堆 
	return true;//删除失败 
}
 
//打印二叉堆 
template<class T>
void MaxHeap<T>::print()
{
	if(size==0)
	  cout<<"堆为空!";
	for(int i=1;i<=size;i++)
	  cout<<heap[i]<<" ";
	cout<<endl;
}
 
int main()
{
	MaxHeap<int> *tree=new MaxHeap<int>;
	while(1)
	{
		cout<<"1.插入元素\n2.删除元素\n3.打印最大堆\n4.退出\n";
		int op;
		cin>>op;
		if(op==1)
		{
			int e;
			cout<<"输入元素值:";
			cin>>e;
			bool flag=tree->insert(e);
			cout<<"---------------"<<endl;
			cout<<"插入元素"<<e;
			if(flag)
			  cout<<"成功!"<<endl;
			else
			  cout<<"失败!"<<endl;
			cout<<"---------------"<<endl; 
		}
		else if(op==2)
		{
			int e;
			cout<<"输入元素值:";
			cin>>e;
			bool flag=tree->remove(e);
			cout<<"---------------"<<endl;
			cout<<"删除元素"<<e;
			if(flag)
			  cout<<"成功!"<<endl;
			else
			  cout<<"失败!"<<endl;
			cout<<"---------------"<<endl; 			
		}
		else if(op==3)
		{
			cout<<"---------------"<<endl;
			tree->print();
			cout<<"---------------"<<endl;
		}
		else
		  break;
	}	
	return 0;
}

最小堆

//最大堆 
 
#include
 
using namespace std;
 
template<class T> 
class MaxHeap{
	private:
		T *heap;//数据
		int capacity;//总的容量
		int size;//实际容量
		
		void down(int start,int end);//最大堆向下调整算法
		void up(int start);//最大堆向上调整算法
		
	public:
		MaxHeap();
		MaxHeap(int capacity); 
		~MaxHeap();
		int getIndex(T data);//返回data在二叉堆中的索引
		bool remove(T data);//删除最大堆中的data
		bool insert(T data);//将data插入二叉堆中
		void print();//打印二叉堆 
}; 
 
//构造函数 
template<class T>
MaxHeap<T>::MaxHeap(int capacity)
{
	this->capacity=capacity;
	this->size=0;
	heap=new T[this->capacity];
} 
 
template<class T>
MaxHeap<T>::MaxHeap()
{
	new (this)MaxHeap(30);
} 
 
//析构函数
template<class T>
MaxHeap<T>::~MaxHeap()
{
	size=capacity=0;
	delete[] heap;
}
 
//返回data在二叉堆的索引位置,如果不存返回-1 
template<class T>
int MaxHeap<T>::getIndex(T data)
{
	for(int i=1;i<=size;i++)
	  if(heap[i]==data)
	    return i;
	return -1;
}
 
//最小堆的向上调整算法 
template<class T>
void MaxHeap<T>::up(int start)//start上调的开始位置 
{
	int c=start;
	T temp=heap[c];
	int p=c/2;//p是c的父节点
	while(p>0)
	{
		if(temp>=heap[p])//最大堆是<= 
		  break;//上调结束
		else
		{
			heap[c]=heap[p];
			c=p;
			p=p/2;
		} 
	}
	heap[c]=temp; 
}
 
//插入值为data的元素 
template<class T>
bool MaxHeap<T>::insert(T data)
{
	if(size==capacity)//堆已满,添加失败,返回false 
	  return false;
	heap[++size]=data;//将数据插在最后
	up(size);//上调元素 
	return true; 
}
 
/*
最小堆的向下调整算法 
start:被下调节点的起始位置
end:数组的最后一个元素的位置 
*/ 
 
template<class T>
void MaxHeap<T>::down(int start,int end)
{
	int c=start;//c表示当前结点的位置 
	T temp=heap[c];//当前结点的值 
	int l=2*c;//c的左孩子
	//进行下调
	while(l<=end)
	{
		// l是左孩子,l+1是右孩子
		if(l<end&&heap[l]>heap[l+1])//最大堆是heap[l]
		  l++;//左右两个孩子中选择较小者
		if(temp<=heap[l])//下调结束 
		  break; 
		else
		{
			heap[c]=heap[l]; 
			c=l;
			l=l*2;
		}
	}
	heap[c]=temp; 
}
 
//删除值为data的元素 
template<class T>
bool MaxHeap<T>::remove(T data)
{
	//获取data在数组中的索引
	int index=getIndex(data);
	if(index==-1)//未找到 ,删除失败,返回false 
	  return false;
	heap[index]=heap[size--];//用最后元素填补index位置
	down(index,size);//从index位置开始自上而下调整为最大堆 
	return true;//删除失败 
}
 
//打印二叉堆 
template<class T>
void MaxHeap<T>::print()
{
	if(size==0)
	  cout<<"堆为空!";
	for(int i=1;i<=size;i++)
	  cout<<heap[i]<<" ";
	cout<<endl;
}
 
int main()
{
	MaxHeap<int> *tree=new MaxHeap<int>;
	while(1)
	{
		cout<<"1.插入元素\n2.删除元素\n3.打印最小堆\n4.退出\n";
		int op;
		cin>>op;
		if(op==1)
		{
			int e;
			cout<<"输入元素值:";
			cin>>e;
			bool flag=tree->insert(e);
			cout<<"---------------"<<endl;
			cout<<"插入元素"<<e;
			if(flag)
			  cout<<"成功!"<<endl;
			else
			  cout<<"失败!"<<endl;
			cout<<"---------------"<<endl; 
		}
		else if(op==2)
		{
			int e;
			cout<<"输入元素值:";
			cin>>e;
			bool flag=tree->remove(e);
			cout<<"---------------"<<endl;
			cout<<"删除元素"<<e;
			if(flag)
			  cout<<"成功!"<<endl;
			else
			  cout<<"失败!"<<endl;
			cout<<"---------------"<<endl; 			
		}
		else if(op==3)
		{
			cout<<"---------------"<<endl;
			tree->print();
			cout<<"---------------"<<endl;
		}
		else
		  break;
	}	
	return 0;
}

你可能感兴趣的:(数据结构)