关于二叉树的几个基本操作

//Geeksun 2018.05.13 输入样例 AB#D##C## 详情见扩展二叉树
#include <iostream>
using namespace std;
enum flag{Child = 0,Thread = 1};//两种枚举类型,表示该节点的指针是指向下一个节点,还是作为线索。
struct node
{
	char data;
	struct node *leftChild, *rightChild;
	flag ltag, rtag;
};
class Tree	
{
public:
	Tree()
	{
		this->root = treeCreat(getRoot());//此处需要在类里再定义一个创建树的函数,因为构造函数不能被递归调用。
		pre = NULL;
		threadTreeCreat(getRoot());
	 }
	Tree(const Tree& tree)//复制构造函数
	{
		this->root = treeCopy(this->root,tree.root);
	}
	~Tree()
	{
		destroyTree(getRoot());
	}
	void destroyTree(struct node* node);//析构整个树
	bool isCompleteBinaryTree(struct node* node);//判断是否为完全二叉树
	void threadInorder_travelsal(struct node* node);//根据线索二叉树中序遍历
	void deleteNodeTree(char data, struct node* node, struct node* pre);删除子树
	bool searchNode(char data, struct node* node, struct node*& cur, bool &isFind);//查找某个节点
	struct node** arrayReserve(struct node* node,int& count);//将树按中序保存在数组中
	struct node* getRoot()
	{
		return root;
	}
private:
	struct node* root;
	struct node* pre;
	struct node* treeCreat(struct node* node);
	struct node* treeCopy(struct node* son_node,struct node* father_node);
	struct node* threadNext(struct node* p);//中序遍历时查找后继节点的位置
	void threadTreeCreat(struct node* node);
};
bool Tree::isCompleteBinaryTree(struct node* node)
{
	int head = 0, tail = 0;
	struct node* queue[20];
	if (!node)
	{
		return false;
	}
	queue[tail++] = node;
	while (head != tail)
	{
		struct node* p;
		p = queue[head++ % 20];
		if (p->leftChild != NULL&&p->rightChild != NULL)//若左孩子,右孩子不为空则直接入队列
		{
			queue[tail++ % 20] = p->leftChild;
			queue[tail++ % 20] = p->rightChild;
		}
		if (p->leftChild == NULL&&p->rightChild != NULL)//若有右孩子没有左孩子则不是完全二叉树
		{
			return false;
		}
		if (p->leftChild != NULL && p->rightChild == NULL|| p->leftChild == NULL && p->rightChild == NULL)//若左孩子和右孩子存在或左孩子和右孩子都不存在,则在此节点后的全是叶子结点
		{
			while (head != tail)
			{
				p = queue[head];
				if (p->leftChild == NULL && p->rightChild == NULL)
				{
					head++;
				}
				else
				{
					return false;
				}
			}
			return true;
		}
	}
	return true;
}
struct node* Tree::treeCopy(struct node* son_node, struct node* father_node)
{
	if (father_node)
	{
		son_node = new struct node;
		son_node->data = father_node->data;
		son_node->leftChild = treeCopy(son_node->leftChild, father_node->leftChild);//此处的struct node* son_node 可以用引用,因为要修改它的指向,也可以在修改后将它传出来,覆盖之前的指针。
		son_node->rightChild = treeCopy(son_node->rightChild, father_node->rightChild);
	}
	else
	{
		son_node = NULL;//此处一定要加上新节点为空,不然它就是一个野指针了。
	}
	return son_node;
}
bool Tree::searchNode(char data, struct node* node, struct node*& cur,bool &isFind)//此处isFind传引用较为新颖,只要isFind被修改为True,那么就可以知道,在节点中有该数据。
{
	if (!node)
	{
		return isFind;
	}
	if (node->data == data)
	{
		cur = node;
		isFind = true;
		return isFind;
	}
	searchNode(data, node->leftChild, cur, isFind);
	searchNode(data, node->rightChild, cur, isFind);
	return isFind;
}
void Tree::deleteNodeTree(char data,struct node* node,struct node* pre)
{
	if (node != NULL)
	{
		if (node->data == data && node != getRoot())//如果删除的不是根节点
		{ 
			if (pre->leftChild == node) //防止删除节点的父节点的指针悬空
				pre->leftChild = NULL;
			else if (pre->rightChild == node) 
				pre->rightChild = NULL;
			destroyTree(node);
			return;
		}
		else if (node->data == data)
		{
			destroyTree(node);
			return;
		}
		if(node->ltag == 0)
			deleteNodeTree(data,node->leftChild,node);
		if(node->rtag == 0)
			deleteNodeTree(data,node->rightChild,node);
	}
}
void Tree::threadInorder_travelsal(struct node* node)
{
	struct node* p;
	p = node;
	if (!p)
	{
		return;
	}
	while (p->ltag == 0)
	{
		p = p->leftChild;//先找到树最左下方的节点。
	}
	cout << p->data;
	while (p->rightChild != NULL)
	{
		p = threadNext(p);
		cout << p->data;
	}
}
struct node** Tree::arrayReserve(struct node* node,int &count)
{
	int head = 0, tail = 0;
	count = 0;
	struct node**  array = new struct node*[20];//这里需要在堆中创建数组,因为如果在栈中创建数组,当函数结束后array中的数据都会消失,而堆中数据需自己清空。
	struct node* queue[20];
	if (!node)
	{
		return NULL;
	}
	queue[tail++ % 20] = node;
	while (head != tail)
	{
		struct node* q = queue[head++];
		array[count++] = q;
		if (q->leftChild != NULL) queue[tail++] = q->leftChild;
		if (q->rightChild != NULL) queue[tail++] = q->rightChild;
	}
	return array;
}
struct node* Tree::threadNext(struct node* p)
{
	struct node* q;
	if (p->rtag == 1)
		q = p->rightChild;
	else
	{
		q = p->rightChild;//此处p的右孩子不可能为空,若为空则他的rtag一定为1
		while (q->ltag == 0)
		{
			q = q->leftChild;
		}
	}
	return q;
}
void Tree::threadTreeCreat(struct node* node)
{
	if (node == NULL)
		return;
	threadTreeCreat(node->leftChild);
	if (node->leftChild == NULL)
	{
		node->ltag = (flag)1;//这里要使用强转类型转换,不然会报错!
		node->leftChild = pre;
	}
	if (node->rightChild == NULL) 
		node->rtag = (flag)1;//右孩子指针指向的是下一个中序结点的地址,但是暂时还不知道下一个是谁,因此只能在下一轮循环指向下一个结点。
	if (pre != NULL&& pre->rtag == 1)//当pre为指向空的时候,当然不会有数据,所以要判断一下!
	{
			pre->rightChild = node;
	}	
	pre = node;
	threadTreeCreat(node->rightChild);
	return;
}
struct node* Tree::treeCreat(struct node* node)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		node = NULL;
	}
	else
	{
		node = new struct node;
		node->data = ch;
		//node->ltag = (flag)0; node->rtag = (flag)0;
		node->leftChild = treeCreat(node->leftChild);
		node->rightChild = treeCreat(node->rightChild);
	}
	return node;
}
void Tree::destroyTree(struct node* node)
{
	if (node == NULL)
	{
		return;
	}
	if (node->leftChild != NULL&&node->ltag == 0)
	{
		destroyTree(node->leftChild);
	}
	if (node->rightChild != NULL&&node->rtag == 0)
	{
		destroyTree(node->rightChild);
	}
	delete node;
	node = NULL;
	return;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值