二叉堆

     二叉堆是一种支持插入,删除,查询最值的数据结构. 它其实是一棵满足"堆性质"的完全二叉树, 树上的每个节点带有一个权值。如果树上的任意一个子节点权值都小于等于父节点权值的,称该二叉树满足"大根堆"性质.如果树上任意一个子节点权值都大于等于父节点权值的,称该二叉树满足"小根堆"性质 . 

    这里以大根堆为例 .

    1 . 存储采用一维数组 heap[i] ,  节点 i 的 左孩子为 i*2 , 右孩子为 i*2+1 ; 

    2 . Insert 操作 

      insert(val) 操作向二叉堆中插入一个权值为 val 的新节点 一般会破坏大根堆的性质.通过调整,使得二叉树重新满足大根堆性质 . 

     这里不详细说了. 

   

void up(int p){ // 向上调整
	while(p>1 ){
		if(heap[p] > heap[p/2]){ // 如果子节点大于父节点
			swap(heap[p] , heap[p/2]) ;
			p/=2 ;
		}
		else{
			break ;
		}
	}
}
void insert(int val) {
	heap[++n] = val ;
	up(n) ; // 每加一个数都要维护一遍二叉树
	// 保证满足大根堆
}

   3 . GetTop ,  返回二叉堆的堆顶权值, 即最大值 ,复杂度O(1)

int GetTop(){
	return heap[1] ;
}

   4 . Extract  , 将堆顶从二叉堆中移除. 我们把堆顶元素 heap[1] 与存储在数组末尾的节点heap[n] 交换, 然后移除数组末尾节点,最后把堆顶通过交换方式向下调整,直到满足大根堆性质 . 

 

void down(int p ){
	int s = p*2 ;
	while(s<=n){
		if(s heap[p]){ // 如果孩子节点都大于父节点
			swap(heap[s],heap[p]) ;
			p = s ;
			s = p*2 ;
		}
		else{
			break ;
		}
	}
}
void Extract(){
	heap[1] = heap[n--] ;
	down(1) ;
}

4 . Remove(p)  , 把数组p 位置上的元素从二叉堆中移除 . 

void Remove(int k ){
	heap[k] = heap[n--] ;
	up(k) ;
	down(k) ;
}

代码 :

 

#include 
#include 
#include 
#include 
using namespace std ;
const int MAX = 100015 ;
typedef long long LL ;
int heap[MAX]  ;
int n ;
void up(int p){ // 向上调整
	while(p>1 ){
		if(heap[p] > heap[p/2]){ // 如果子节点大于父节点
			swap(heap[p] , heap[p/2]) ;
			p/=2 ;
		}
		else{
			break ;
		}
	}
}
void down(int p ){
	int s = p*2 ;
	while(s<=n){
		if(s heap[p]){
			swap(heap[s],heap[p]) ;
			p = s ;
			s = p*2 ;
		}
		else{
			break ;
		}
	}
}
void Extract(){
	heap[1] = heap[n--] ;
	down(1) ;
}
void Remove(int k ){
	heap[k] = heap[n--] ;
	up(k) ;
	down(k) ;
}
void insert(int val) {
	heap[++n] = val ;
	up(n) ; // 每加一个数都要维护一遍二叉树
	// 保证满足大根堆
}
int GetTop(){
	return heap[1] ;
}
int main(){
	cin >> n ;
	for(int i = 1 ; i<=n ; i++ ) {
		int x ;
		cin >>x ;
		heap[i] = x ;
	}
	Extract();
	cout<>x ;
	insert(x) ;
	//Extract();
	cout<<"这时候最大值 "<

 

你可能感兴趣的:(二叉堆)