数据结构(五) 二叉树、堆

本文探讨了二叉查找树的实现,包括插入、删除、查找操作,以及如何找到节点的后继和前驱。接着,介绍了二叉树的不同遍历方式。在堆的部分,讲解了小顶堆和大顶堆的构建,以及如何用它们实现优先级队列和堆排序。此外,还讨论了如何利用优先级队列来动态合并K个有序数组,以及求解动态数据集合的最大Top K问题。
摘要由CSDN通过智能技术生成

二叉树

实现一个二叉查找树,并且支持插入、删除、查找操作

//实现一个二叉查找树,并且支持插入、删除、查找操作
typedef char datatype
typedef struct Bnode
{
	datatype data;
	struct Bnode *Lchild, *Rchild;
}Btnode, *BTptr;

CreateLBtree(BTptr BT)  //建立以BT为根节点指针的二叉链表结构 
{
	datatype ch; int i = 0;
	BTptr p, q;
	Clearqueue(Q);  //置队Q为空 
	BT = NULL;  //置空树 
	ch = getchar();  //读入数据 
	while(ch != '#')
	{
		p = NULL;  //p为新节点的地址,但空节点地址为NULL 
		if(ch != '@')
		{
			p = (BTptr)malloc(sizeof(BTnode));  //申请新节点 
			p -> data = ch;  //存入数据 
			p -> Lchild = p -> Rchild = NULL;
		 }
		 i++;  //节点序号计数 
		 Enqueue(q, p);  //新节点地址或虚节点地址(NULL)进队 
		 if(i == 1) BT = p;  //第一输入节点为根 
		 else
		 {
		 	q = Getqtop(Q);  //取队头元素 
		 	if(p && q)  //若新节点及父几点均存在 
		 	if(1 % 2 == 0) q -> Lcchild = p;  //i为偶数,p是双亲的左子 
		 	else q -> Rchild = p;  //i为奇数,p是双亲的右子 
		 	if(i % 2 == 1) Delqueue(Q, q);  //当前双亲处理完出队 
		 }
		 ch = getchar();  //输入下一数据 
	}
	return (BT);
}

实现查找二叉查找树中某个节点的后继、前驱节点

//实现查找二叉查找树中某个节点的后继、前驱节点

//线索二叉树
typedef struct Bnode
{
	short int Ltag, Rtag;
	datatype data;
	struct Bnode *Lchild, *Rchild;
 } BTnode, *BTptr;
 
 BTptr pre = NULL;
 
void Inthreadbt(BTptr BT)  //对二叉树BT的线索华的算法 
{
 	if(BT)
 	{
 		Inthreadbt(BT -> Lchild);  //线索化左子树 
 		if(BT -> Lchild == NULL)  //左指针空闲时 
 		{  //本节点前驱为中序遍历下前一个节点 
 			BT -> Ltag = 1;
 			BT -> Lchild == pre;
		}
		if(BT -> Rchild == NULL)  //右指针空闲时 
			BT -> Rtag = 1;  //记录下此点有空闲指针 
		if(pre && pre->Rtag == 1)  //上一个节点有空的后继指针时, 
			pre -> Rchild = BT;  //该指针指向其后继(本节点) 
		pre = BT;  //次节点已访问,更新为前驱 
		Inthreadbt(BT -> Rchild);  //线索化右子树 
	 }
}

BTptr Inpre(BTptr p)  //求中序线索二叉树中p节点前驱的算法 
{
	BTptr pre;
	if(p == NULL) return(NULL);
	pre = p -> Lchild;   //p有左子时pre为p的左子,否则取p前驱 
	if(p -> Ltag == 0)  //p有左子树时 
		while(pre->Rtag == 0)  //取该子树最右边的节点,即为p的前驱 
			pre = pre -> Rchild;
	return(pre);  //返回p的前驱 
 } 
 
 
BTptr Insucc(BTptr p)  //求中序线索二叉树中p节点后继的算法 
{
	BTptr s;
	if(p == NULL) return(NULL);
	s = p -> Lchild;   //p有右子时s为p的右子,否则取p后继 
	if(p -> Ltag == 0)  //p有左子树时 
		while(s->Rtag == 0)  //取该子树最左边的节点,即为p的后继 
			s = s -> Rchild;
	return(pre);  //返回p的后继 
 } 

实现二叉树前、中、后序以及按层遍历

//实现二叉树前、中、后序以及按层遍历 

void preorder(BTptr T)  //对当前根节点指针为T的二叉树按前序遍历的算法 
{
	if(T)
	{
		visit(T);  //访问T的所有节点 
		preorder(T -> Lchild);  //前序遍历T的左子树 
		preorder(T -> Rchild);  //前序遍历T的右子数
	}
}

void inorder(BTptr T)  //对当前根节点指针为T的二叉树按中序遍历的算法 
{
	if(T)
	{
		inorder(T -> Lchild);  //中序遍历T的左子树
		visit(T);  //访问T的所有节点  
		inorder(T -> Rchild);  //中序遍历T的右子数
	}
}


void postorder(BTptr T)  //对当前根节点指针为T的二叉树按后序遍历的算法 
{
	if(T)
	{
		postorder(T -> Lchild);  //后序遍历T的左子树 
		pstorder(T -> Rchild);  //后序遍历T的右子数
		visit(T);  //访问T的所有节点
	}
}


void Layerorder(BTptr T)  //对二叉树按层次遍历的算法 
{
	BTptr p;
	if(T)
	{
		Clearqueue(Q);  //置队Q空 
		Enqueue(Q, T); //先将指针进队 
		while(!Emptyqueue(Q))
		{
			p = Dequeue(Q);  //出队,队头元素指向p 
			visit(p);  //访问p节点 
			if(p -> Lchild) Enqueue(Q, p -> Lchild);  //左子指针进队 
			if(p -> Rchild) Enqueue(Q, p -> Rchild);  //右子指针进队
		}
	}
 } 

实现一个小顶堆、大顶堆、优先级队列

实现堆排序

void Heapsort(sqfile F)  //对顺文件F的堆排序算法 
{
	int i;
	Retype temp;
	for(i = F.len / 2; i >= 1; i--)
		Adjust(F, i, F.len);  //调整(R[i]...R[n])为堆 
	for(i = F.len; i >= 2; i--)  //选择n-1次 
	{
		temp = F.R[1];  //根与当前最后一个节点互换 
		F.R[1] = F.R[i];
		F.R[i] = temp;
		Adjust(F, 1, i-1);  //互换后再建堆 
	}
 } 

利用优先级队列合并 K 个有序数组

求一组动态数据集合的最大 Top K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值