二叉堆的创建以及新结点的插入(C++实现)

前言

本文中的代码实现的是最小堆,最大堆的原理与此相似,故省略;另外,由于二叉堆插入结点与删除结点的操作相反,所以本文中也只实现插入结点的操作,删除结点的操作的实现略去。

阅读文中代码所需的预备知识

  • 二叉堆是一个完全二叉树,但是它的存储方式并不是链式存储,而是顺序存储,即二叉树的所有结点都存储在数组中。
  • 若父结点在数组中的下标是parent,则其左孩子的下标是2*parent+1,右孩子的下标是2*parent+2。
  • 二叉堆插入结点时,插入位置是完全二叉树的最后一个位置。
  • 构建二叉堆,就是把一个无序的完全二叉树调整为二叉堆,本质就是让所有非叶子结点从最后一个非叶子结点开始依次“下沉”。最后一个非叶子结点的数组下标的计算方法是:(数组长度-2)/ 2。

代码

#include<iostream>
using namespace std;

//分别用于存储array1和array2的长度 
int len1,len2;

//结点的“上浮”过程
void upAdjust(int *array){
	int childIndex=len1-1;
    //求出父结点的下标
	int parentIndex=(childIndex-1)/2;
	//temp保存插入的叶子结点的值,用于最后的赋值
	int temp=array[childIndex];
	while(childIndex>0&&temp<array[parentIndex]){
		//无需真正交换,单向赋值即可
		array[childIndex]=array[parentIndex];
		childIndex=parentIndex;
		parentIndex=(childIndex-1)/2; 
	}
	array[childIndex]=temp;
}

//结点的“下沉”过程
void downAdjust(int *array,int parentIndex,int len){
	//temp保存父结点值,用于最后的赋值
	int temp=array[parentIndex];
    //求出左孩子的下标
	int childIndex=2*parentIndex+1;
	while(childIndex<len){
		//如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
		if(childIndex+1<len&&array[childIndex+1]<array[childIndex]){
			childIndex++;
		} 
		//如果父结点的值小于任何一个孩子结点的值,则直接跳出
		if(temp<=array[childIndex])
			break;
		//无需真正交换,单向赋值即可
		array[parentIndex]=array[childIndex];
		parentIndex=childIndex;
		childIndex=2*childIndex+1; 
	} 
	array[parentIndex]=temp;
}

//二叉堆的建立
void buildHeap(int *array){
	//从最后一个非叶子结点开始,依次做"下沉"调整
	for(int i=(len2-2)/2;i>=0;i--){
		downAdjust(array,i,len2);
	} 
}
int main()
{
	//array1用于测试在一个二叉堆插入一个数后,堆的"上浮"调整 
	int array1[]={1,3,2,6,5,7,8,9,10,0};
	len1=sizeof(array1)/sizeof(array1[0]);
	upAdjust(array1);
	cout<<"调整后的堆是: ";
	for(int i=0;i<len1;i++)
		cout<<array1[i]<<" "; 
	cout<<endl;
	//array2用于测试由一个数组建立二叉堆时,堆的"下沉"调整 
	int array2[]={7,1,3,10,5,2,8,9,6};
	len2=sizeof(array2)/sizeof(array2[0]);
	buildHeap(array2); 
	cout<<"建成的堆是: "; 
	for(int i=0;i<len2;i++)
		cout<<array2[i]<<" ";
	cout<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值