二叉堆

二叉堆是完全二叉树,实现    查询最值,插入元素,删除任意元素(堆顶或其他),修改任意元素值    的功能,复杂度为O(logN)

由于是完全二叉树,所以用数组实现,方便快捷

法一:之前常用的普通实现,没进行封装,也可以写一个封装实现的

//Binary Heap,the most common implement of Poriority Queen(Heap)  
//以最小堆为例  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
struct Heap{  
    int capacity;  
    int size;  
    int *data;  
};  
struct Heap* Init(struct Heap*binaryHeap,int n)//初始化  
{  
    binaryHeap=(struct Heap*)malloc(sizeof(struct Heap));  
    binaryHeap->capacity=n;  
    binaryHeap->size=0;  
    binaryHeap->data=(int*)malloc(sizeof(int)*(n+1));  
    binaryHeap->data[0]=-10000;  
    return binaryHeap;  
}  
void Destory(struct Heap* binaryHeap)//释放  
{  
    free(binaryHeap->data);  
    free(binaryHeap);  
    return;  
}  
int IsEmpty(struct Heap *binaryHeap)//判断堆空不空  
{  
    return binaryHeap->size==0;  
}  
int IsFull(struct Heap* binaryHeap)//判断堆满不满  
{  
    return binaryHeap->size==binaryHeap->capacity;  
}  
void Insert(struct Heap* binaryHeap,int number)//插入  
{  
    int i;  
    if(!IsFull(binaryHeap)){  
        binaryHeap->size++;  
        //percolated up 上滤  
        for(i=binaryHeap->size;i>1&&binaryHeap->data[i/2]>number;i/=2)  
            binaryHeap->data[i]=binaryHeap->data[i/2];  
        binaryHeap->data[i]=number;  
    }  
    return;  
}  
void DeleteMin(struct Heap* binaryHeap)//删除最小  
{  
    int i,child;  
    int minElement;  
    int lastElement;  
    if(!IsEmpty(binaryHeap)){  
        //minElement=binaryHeap->data[1];  
        if(binaryHeap->size==1){  
            binaryHeap->size--;  
            return;  
        }  
        lastElement=binaryHeap->data[binaryHeap->size--];  
        //percolated down 下滤  
        for(i=1;i*2<=binaryHeap->size;i=child){//此处用i*2判断很重要  
            child=i*2;  
            if(child!=binaryHeap->size&&binaryHeap->data[child+1]<binaryHeap->data[child])  
                child++;  
            if(lastElement>binaryHeap->data[child])  
                binaryHeap->data[i]=binaryHeap->data[child];  
            else  
                break;  
        }  
        binaryHeap->data[i]=lastElement;  
        return;  
    }  
    return;  
}  
void BuildHeap(struct Heap* binaryHeap)//建堆  
{  
    int n,temp,child,j;  
    scanf("%d",&n);  
    if(n>binaryHeap->capacity)  
        return;  
    for(int i=1;i<=n;i++)  
        scanf("%d",&(binaryHeap->data[++binaryHeap->size]));  
    for(int i=binaryHeap->size/2;i>=1;i--){//逐一下滤  
        temp=binaryHeap->data[i];  
        for(j=i;j*2<=binaryHeap->size;j=child){//此处用j*2判断很重要  
            child=2*j;  
            if(child!=binaryHeap->size&&binaryHeap->data[child+1]<binaryHeap->data[child])  
                child=child+1;  
            if(temp>binaryHeap->data[child])  
                binaryHeap->data[j]=binaryHeap->data[child];  
            else  
                break;  
        }  
        binaryHeap->data[j]=temp;  
    }  
    return;  
}  
void Delete(struct Heap* binaryHeap,int loc)//删除某个节点的值  
{  
    int i,number;  
    if(loc<=0||loc>binaryHeap->size)  
        return;  
    //先把此处的值变为近似无限小  
    binaryHeap->data[loc]=-100000000;  
    number=binaryHeap->data[loc];  
    //上滤  
    for(i=loc;i>1&&number<binaryHeap->data[i/2];i--)  
        binaryHeap->data[i]=binaryHeap->data[i/2];  
    binaryHeap->data[i]=number;  
    //删除目前位于1处的节点  
    DeleteMin(binaryHeap);  
    return;  
}  
void IncreaseKey(struct Heap* binaryHeap,int loc,int increasement)//增加某个节点的键值  
{  
    int i,number,child;  
    if(loc<=0||loc>binaryHeap->size||increasement<=0)  
        return;  
    binaryHeap->data[loc]+=increasement;  
    //下滤  
    number=binaryHeap->data[loc];  
    for(i=1;i*2<=binaryHeap->size;i=child){//此处用i*2判断很重要  
        child=i*2;  
        if(child!=binaryHeap->size&&binaryHeap->data[child+1]<binaryHeap->data[child])  
            child++;  
        if(number>binaryHeap->data[child])  
            binaryHeap->data[i]=binaryHeap->data[child];  
        else  
            break;  
    }  
    binaryHeap->data[i]=number;  
    return;  
}  
void DecreaseKey(struct Heap* binaryHeap,int loc,int decreasement)//减少某个节点的键值 假设decreasement为正  
{  
    int i,number,child;  
    if(loc<=0||loc>binaryHeap->size||decreasement<=0)  
        return;  
    binaryHeap->data[loc]-=decreasement;  
    //上滤  
    number=binaryHeap->data[loc];  
    for(i=loc;i>=1&&binaryHeap->data[i/2]>number;i/=2)  
        binaryHeap->data[i]=binaryHeap->data[i/2];  
    binaryHeap->data[i]=number;  
    return;  
}  
void levelOrderTrversal(struct Heap* binaryHeap)//按照节点编号打印节点数值  
{  
    for(int i=1;i<=binaryHeap->size;i++)  
        printf("%d:%d%c",i,binaryHeap->data[i],i==binaryHeap->size?'\n':' ');  
    return;  
}  
int main(){  
    struct Heap *binaryHeap;  
    binaryHeap=Init(binaryHeap,100);  
    BuildHeap(binaryHeap);  
    levelOrderTrversal(binaryHeap);  
    Insert(binaryHeap,10);  
    levelOrderTrversal(binaryHeap);  
    DeleteMin(binaryHeap);  
    levelOrderTrversal(binaryHeap);  
    Delete(binaryHeap,2);  
    levelOrderTrversal(binaryHeap);  
    IncreaseKey(binaryHeap,1,7);  
    levelOrderTrversal(binaryHeap);  
    DecreaseKey(binaryHeap,3,7);  
    levelOrderTrversal(binaryHeap);  
    return 0;  
}  

法二:基于C++类封装实现,但思路不同上,多出两个数组,id[MAXN],用于记录 队中位置为 i 的元素是第几个插入堆中的,pos[MAXN],用于记录 第 i 个插入堆中的元素在堆中的位置。此思路没写不基于封装的。

以最小堆为例

#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
#define MAXN 100005
#define MINNUM -0X3f3f3f3f
int arr[MAXN];
class BinaryHeap {
private:
	int n, counter;
	int heap[MAXN], id[MAXN], pos[MAXN];
public:
	BinaryHeap():n(0),counter(0){}
	BinaryHeap(int arr[], int offest):n(0),counter(0) {
		for (int i = 0; i < offest; i++) {
			heap[++n] = arr[i];
			id[n] = n;
			pos[n] = n;
		}
		for (int i = n / 2; i >= 1; i--) {
			down(i);
		}
	}
	void push(int te) {
		heap[++n] = te;
		id[n] = ++counter;
		pos[counter] = n;
		up(n);
	}
	int pop() {
		swap(heap[1], heap[n]);
		swap(id[1], id[n]);
		pos[id[1]] = 1;
		pos[id[n--]] = -1;
		down(1);
		return heap[n + 1];
	}
	void change(int i,int value) {//i指的是第几个插入的
		if (pos[i] == -1) {
			cerr << "ERROR" << endl;
			return;
		}
		heap[pos[i]] = value;
		down(pos[i]);
		up(pos[i]);
		//也可写成:
		//int t = heap[i];heap[i] = value;
		//if(value > t) down(i);else if(value < t) up(i);
	}
	void erase(int i) {//i指的是第几个插入的
		if (pos[i] == -1) {
			cerr << "ERROR" << endl;
			return;
		}
		heap[pos[i]] = MINNUM;
		up(pos[i]);
		pop();
	}
	void up(int i) {//i指的是heap下标
		int j;
		int x = heap[i], y = id[i];
		for (j = i; j > 1 && heap[j] < heap[j / 2]; j /= 2) {
			heap[j] = heap[j / 2];
			id[j] = id[j/2];
			pos[id[j]] = j;
		}
		heap[j] = x;
		id[j] = y;
		pos[y] = j;
	}
	void down(int i) {//i指的heap是下标
		int j,child;
		int x = heap[i], y = id[i];
		for (j = i; j*2 <= n; j = child) {
			child = j * 2;
			if (child + 1 < n && heap[child + 1] < heap[child]) {
				child++;
			}
			if (x > heap[child]) {
				heap[j] = heap[child];
				id[j] = id[child];
				pos[id[j]] = j;
			}
			else {
				break;
			}
		}
		heap[j] = x;
		id[j] = y;
		pos[y] = j;
	}
};
int main() {
	int n;
	BinaryHeap *binaryHeap;
	while (scanf("%d", &n) != EOF) {
		for (int i = 0; i < n; i++) {
			cin >> arr[i];
		}
		binaryHeap = new BinaryHeap(arr, n);
		
		cout << binaryHeap->pop() << endl;
		//...
		//...
		//...
		//...

		delete binaryHeap;
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值