二叉树的基本操作(一)

这篇文章主要保存下二叉树学习中的实现,实现了4类基本功能和一个扩展功能:

1、创建节点

2、插入节点

3、删除节点

4、二叉树销毁

5、遍历

6、按结构显示打印

扩展功能在下篇文章中显示

函数定义及头文件

#pragma once
#include <queue>
#include <iostream>
using namespace std;

typedef struct BinNodetag
{
	BinNodetag* P;		//父节点
	BinNodetag* L;		//左孩子节点
	BinNodetag* R;		//右孩子节点
	unsigned int index; //节点索引
	void * data;		//节点数据
}BinNode;

/*****************************************************************
打印二叉树使用的数据结构,用于保存二叉树节点数据和位置信息,
depth:
	表示深度位置信息,根节点为1,往下一层为2,按层+1增长
local:
	标示x轴位置信息,根节点为单位1,
	其左孩子为1-1/2,右孩子为1+1/2。
	每层的loacl为其父节点的local +/- 0.5^depth
	eg:  node->L->local = node->local - (1 << depth)
*****************************************************************/
typedef struct PaintNodetag //
{
	unsigned int depth;		//Y轴信息 
	float local;			//X轴信息
	BinNode *node;			//当前节点
}PaintNode;

BinNode *Creat(int index);  //按照索引创建一个节点
void Insert(BinNode **head, BinNode *Insertnode); // 在树中插入一个节点
void Delete(BinNode *head, BinNode *node);    //从树中删除一个节点
void Destory(BinNode *node);	//消耗整个二叉树
void InWalkMid(BinNode *head);  //中序遍历打印
void PaintTree(BinNode *head); //显示打印二叉树

具体实现

1、创建节点

BinNode *Creat(int index)
{
	BinNode *node = new BinNode;
	memset(node, 0, sizeof(*node));
	node->index = index;

	return node;
}

2、插入节点

void Insert(BinNode **head, BinNode *Insertnode)
{
	BinNode *node = *head;
	BinNode **child = NULL;

	//头节点为空,成为头节点
	if (*head == NULL)
	{
		*head = Insertnode;
		Insertnode->P = NULL;
		return;
	}

	//类似查找的逻辑,查到当前节点的子节点为空时,插入该处
	while (node != NULL)
	{
		child = (Insertnode->index < node->index) ? &(node->L) : &(node->R);

		if (*child == NULL)
		{
			*child = Insertnode;
			Insertnode->P = node;
			break;
		}

		node = *child;
	}
	return;
}

3、删除节点

删除节点比较麻烦,有两大类情况
1、当前节点没有,或只有一个子节点
2、当前节点有两个子节点
第一种情况下,比较好办,简单的把子节点替换为原节点就行。
第二种情况,核心思想是保证二叉树的结构不变。例如,
中序遍历为 1,2,3,4,5,6,删除3之后,遍历结果也该为1,2,4,5,6
删前2的后继为3,删后2的后继为4,即:
使用删除节点的后继取代原节点位置。
删除节点后继就是他孩子里面最小的数,如果:
1、右孩子没有左孩子那么就是右孩子为后继;
2、否则就一张沿着右孩子的左孩子找下去
a、实现如下,为了方便定义了个替代函数,用于src替代dst的位置:
用于处理一个节点替代另外一个节点的操作,仅仅处理dst->P 和 src 的关系,不处理src的孩子节点
void Replace(BinNode *head, BinNode *dst, BinNode *src)
{
	if (dst == NULL )
	{
		return;
	}

	if (dst->P == NULL)
	{
		head = src;
	}
	else
	{
		((dst->P->L == dst) ? dst->P->L : dst->P->R) = src;
	}

	if (src != NULL && src->P != NULL)
	{
		src->P = dst->P;
	}
	return;
}

b、删除函数主体
void Delete(BinNode *head, BinNode *node)
{
	//head node
	BinNode *tmp_node;

	if (node->L == NULL)
	{
		Replace(head, node, node->R);
	}
	else if (node->R == NULL)
	{
		Replace(head, node, node->L);
	}
	else
	{
		//two parent conditon!the node is replaced by succeeding node
		if (node->R->L == NULL)
		{
			node->R->L = node->L;
			Replace(head, node, node->R);
		}
		else
		{
			tmp_node = node->R->L;
			while (tmp_node->L != NULL)
			{
				tmp_node = tmp_node->L;
			}
			//中继节点删除后,该位置值NULL
			tmp_node->P->L = NULL;

			//replace
			tmp_node->L = node->L;
			tmp_node->R = node->R;
			Replace(head, node, tmp_node);
		}
	}
	delete node;
}

4、二叉树销毁

后续遍历删除二叉树
void Destory(BinNode *node)
{
	if (node == NULL)
	{
		return;
	}
	Destory(node->L);
	Destory(node->R);
	delete node;
	return;
}

5、遍历

遍历较简单,这里实现中序遍历

void InWalkMid(BinNode *head)
{
	if (head == NULL)
	{
		return;
	}

	InWalkMid(head->L);
	printf("%4u", head->index);
	InWalkMid(head->R);
	return;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值