创建一个最大堆的两种方法

创建一个最大堆的两种方法

方法一:逐个插入来实现

(在插入数据的规程中一边插入一边调整顺序使之成为最大堆)
复杂度: O(Nlog(n))

第一步:创建堆的结构体
constexpr int  Maxsize = 20;
struct Theap {
	int a[Maxsize];// 用数组来存储数据
	int size;//显示数据的大小
	int capacity;// 当前堆的容量

};
第二步: 把堆进行初始化
Theap* creatHeap() {
	Theap* temp = new Theap;//为新建的堆分配内存
	temp->capacity = Maxsize;//初始化容量
	temp->size = 0;// 初始化大小
	temp->a[0] = INT_MAX;//把数组0号位置作为哨兵

	return temp;
}
第三步:把初始化完的堆进行插入操作

(插入新元素后,新元素新元素可能回破坏最大堆的结构,每插入一次对堆进行调整一次,保证每次调整之后,这个堆都是最大堆)

// 判断树是否已满
bool If_full(Theap* T) {
	if (T->capacity == T->size) {
		return true;
	}
	else {
		return false;
	}
}

//实现树的插入
void Tinsert(Theap* H, int num) {
	int i = 0; 
	if (If_full(H)) {//判断堆是否已满,比较size 和 capacity 的大小关系
		cout << "堆已满" << endl;
	}
	i = ++H->size;//指向堆中最后一个元素的位置,假设先把数字插入到最后一个叶节点后边
	// 同时插入之后给size执行+1操作
	for (; H->a[i / 2] < num&& i>1; i /= 2) {
		//父节点小于插入的子节点,且当前节点不为根节点;
		H->a[i] = H->a[i / 2];//把父节点的值赋值给子节点
	}
	// 找到当前该插入的节点
	H->a[i] = num;
}

方法二: 分两步走,先把数据组成完全二叉树,再把组成的完全二叉树调整成为最大树

复杂度:O(N)

第一步:批量将数据读入,并且创建成完全二叉树

创建结构体: 见法一
初始化结构体: 见法一

将数据读入并且创建成完全二叉树

// 读入数组构成满二叉树
Theap* heap_in(int arr[], int len) {// arr为传入的数组名,len为传入的数组长度
	Theap* H = new Theap;
	H = creatHeap();//初始化
	if (len > H->capacity- H->size) {// 检测容量
		cout << "容量不足" << endl;
	}
	for (int i = 0; i < len; i++) {
		H->a[++H->size] = arr[i];//顺序将数组中的元素传入二叉树中,对size进行加加操作
	}
	return H;
}
第二步:将创建好的二叉树进行节点顺序调整,使之成为最大堆
//将读入的满二叉树进行排序
void rand_heap(Theap* H) {
	if (If_empty(H)) {
		cout << "堆为空" << endl;
	}
	int i = H->size / 2;//倒数第一个有孩子的节点
	while (i >= 1) {//对每一个有孩子的节点都进行操作
		int j = i;
		int temp = H->a[j];
		while (j * 2 < H->size && (H->a[j] < H->a[2 * j] || H->a[2*j+1])) {
		//在当前节点所形成的树上进行比较
		//进入循环的条件为当前节点有子节点,且当前节点比其中一个子节点小
			H->a[j] = H->a[2 * j] > H->a[2 * j + 1] ? H->a[2 * j] : H->a[2 * j + 1];
			//如果满足条件,将当前节点和大的一个节点进行交换
			j = H->a[2 * j] > H->a[2 * j + 1] ? 2 * j : 2 * j + 1;//更新当前节点
		}
		H->a[j] = temp;
		i--;//移动一个节点;
	}
}

补充:最大堆的pop

问题:输入一个最大堆,根节点为最大值,但是pop出来之后,最大堆的样子就被破坏,所以,pop出根节点之后得,重新排序,使根节点变成当前树中的最大值

int T_pop(Theap* H) {
	if (If_empty(H)) {
		cout << "堆为空" << endl;
	}
	//记录根节点的值
	int res = H->a[1];
	//将最后一个叶子节点移动到堆根 size-1
	H->a[1] = H->a[H->size--];
	//从根堆开始把节点进行排序
	int i = 1;
	while (2 * i + 1 <= H->size) {//当当前节点的右儿子节点存在时
		//记录当前节点
		int temp = H->a[i];
		//把当前节点和较大的子节点进行交换
		H->a[i] = H->a[2 * i] < H->a[2 * i + 1]? H->a[2 * i + 1]: H->a[2 * i];
		//把i更新 
		i = H->a[2 * i] < H->a[2 * i + 1] ? 2 * i + 1 : 2 * i;
		//把交换后的值给当前的i
		H->a[i] = temp;
	}
	return res;
}

附,学习链接,浙江大学,数据结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值