二叉树的实现

原文地址:https://wanqbin.xyz/2019/07/31/二叉树的实现/

一、二叉树结点类定义

templateclass BinaryTree;
templateclass BiTreeNode
{
	friend class BinaryTree;
public:
	T data;//数据域
	BiTreeNode() :leftChild(NULL), rightChild(NULL) {}//构造函数
	BiTreeNode(T item,BiTreeNode*left=NULL,BiTreeNode*right=NULL)//构造函数
		:data(item),leftChild(left),rightChild(right){}
	~BiTreeNode(){}//析构函数

	BiTreeNode*& Left()
	{//获得左孩子
		return leftChild;
	}
	BiTreeNode*& Right()
	{//获得右孩子
		return rightChild;
	}
private:
	BiTreeNode* leftChild;//左子树指针
	BiTreeNode* rightChild;//右子树指针
};

二、二叉树类定义

templateclass BinaryTree
{
public:
	BinaryTree() :root(NULL){};//构造函数
	~BinaryTree() {};//析构函数
	//构造二叉树
	void MakeTree(const T& item);
	//第一类操作的成员函数
	bool Root();//使根结点为当前结点
	bool Parent();//使双亲结点为当前结点
	bool LeftChild();//使左孩子结点为当前结点
	bool RightChild();//使右孩子结点为当前结点

	//第二类操作的成员函数
	
	void InsertChild(const T &value);//使根结点为当前结点
	void DeleteSubTree(BiTreeNode*& t);//删除以t为根结点的子树
	void clear();//清空树
	//第三类操作的成员函数
	//遍历访问二叉树
	void PreOrder(void(*visit)(T item));//前序遍历访问树
	void InOrder(void(*visit)(T item));//中序遍历访问树
	void PostOrder(void(*visit)(T item));//后序遍历访问树

private:
	BiTreeNode* root;//根结点指针
	BiTreeNode* current;//当前结点指针
	bool Current(BiTreeNode*& t);//使当前结点为t所指结点
	void PreOrder(BiTreeNode*& t, void(*visit)(T item));
	void InOrder(BiTreeNode*& t, void(*visit)(T item));
	void PostOrder(BiTreeNode*& t, void(*visit)(T item));
	//插入
	void Insert(const T& value, BiTreeNode*& t);
	//在树root中回溯查找s的双亲结点
	BiTreeNode* SearchParent(BiTreeNode*& root, BiTreeNode*& s);
};

三、二叉树实现的部分代码

前序遍历

即DLR,也叫做先根遍历、先序遍历、前序周游,记作根左右。前序遍历首先访问根结点,然后遍历左子树,最后遍历右子树。

这里使用visit(item)函数来输出结点数据域值,同时,visit(item)函数经过修改之后,也可以输出自定义数据类型中需要输出的数据。

visit(item)函数的实现如下:

template
void Visit(T item)
{
	cout << item << " ";
}
template
inline void BinaryTree::PreOrder(void(*visit)(T item))
{
	PreOrder(root,Visit);
}

template
inline void BinaryTree::PreOrder(BiTreeNode*& t, void(*visit)(T item))
{
	if (t != NULL)
	{
		visit(t->data);
		PreOrder(t->leftChild,visit);
		PreOrder(t->rightChild,visit);
	}
}

中序遍历

即DLR,也叫中根遍历、中序周游。可记作根左右。在二叉树中,中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。

template
inline void BinaryTree::InOrder(void(*visit)(T item))
{
	InOrder(root,Visit);
}

template
inline void BinaryTree::InOrder(BiTreeNode*& t, void(*visit)(T item))
{
	if (t != NULL)
	{
		InOrder(t->leftChild, visit);
		visit(t->data);
		InOrder(t->rightChild, visit);
	}
}

后序遍历

即LRD,也叫后根遍历、后序变周游,可记作左右根。在二叉树中,首先遍历左子树,然后遍历右子树,最后访问根结点。

template
inline void BinaryTree::PostOrder(void(*visit)(T item))
{
	PostOrder(root,Visit);
}

template
inline void BinaryTree::PostOrder(BiTreeNode*& t, void(*visit)(T item))
{
	if (t != NULL)
	{
		PostOrder(t->leftChild, visit);
		PostOrder(t->rightChild, visit);
		visit(t->data);
	}
}

删除子树

template
inline void BinaryTree::DeleteSubTree(BiTreeNode*& t)
{
	if (t == NULL)
		return;
	else
	{
		BiTreeNode* q=t->leftChild, *p;
		while (q != NULL)
		{
			p = q->rightChild;
			DeleteSubTree(q);
			q = p;
		}
		delete t;
		t = NULL;
	}
}

插入结点

在此实现中,对于二叉树结点的插入基本与二叉搜索树相同。当根结点为空时,新插入的结点作为根结点。当新插入的结点值小于根结点值时,插入到左子树;当新插入的结点值大于根结点值时,插入到右子树。

template
inline void BinaryTree::InsertChild(const T& value)
{
	Insert(value, root);
}

template
inline void BinaryTree::Insert(const T& value, BiTreeNode*& t)
{
	if (t == NULL)
		t = new BiTreeNode(value);
	else if (value < t->data)
	{
		Insert(value, t->leftChild);
	}
	else if (value > t->data)
	{
		Insert(value, t->rightChild);
	}
	else
		return;
}

四、主函数及执行结果

int main()
{
	BinaryTreeBiTree;
	BiTree.InsertChild(15);
	BiTree.InsertChild(5);
	BiTree.InsertChild(6);
	BiTree.InsertChild(8);
	BiTree.InsertChild(20);
	BiTree.InsertChild(22);
	BiTree.InsertChild(16);
	BiTree.InsertChild(18);
	cout << "前序:" << endl;
	BiTree.PreOrder(Visit);
	cout << endl << "中序:" << endl;
	BiTree.InOrder(Visit);
	cout << endl << "后序:" << endl;
	BiTree.PostOrder(Visit);
	cout << endl;
	BiTree.clear();
	cout << "前序:" << endl;
	BiTree.PreOrder(Visit);
	system("pause");
	return EXIT_SUCCESS;
}

执行结果:

[外链图片转存失败(img-ojmDeH2F-1565276184605)(执行结果.PNG)]

五、源码地址

​ 二叉树的实现源码

你可能感兴趣的:(二叉树,数据结构,数据结构)