C++实现二叉树

#include <iostream>
using namespace std;
#include <queue>
#include <stack>

template<class T>
struct BinaryTreeNode
{
	BinaryTreeNode<T>* _left;
	BinaryTreeNode<T>* _right;
	T _data;

	BinaryTreeNode(const T& x)
		:_left(NULL)
		,_right(NULL)
		,_data(x)
	{}
};

template<class T>
class BinaryTree
{
public:
	BinaryTree()
		:_root(NULL)
	{}

	BinaryTree(const T* a, size_t size, const T& invalid)
	{
		size_t index = 0;
		_root = _CreateTree(a, size, index, invalid);
	}

	~BinaryTree()
	{
		_Destroy(_root);
		_root = NULL;
	}

	BinaryTree(const BinaryTree<T>& t)
	{
		_root = _Copy(t._root);
	}

	//赋值运算符重载
	BinaryTree<T>& operator=(const BinaryTree& t)
	{
		if (this != &t)
		{
			_Destroy(_root);
			_root = _Copy(t._root);
		}

		return *this;
	}

	//递归前序遍历
	void PreOrderTraverse()
	{
		_PreOrderTraverse(_root);

		cout<<endl;
	}

	//递归中序遍历
	void InOrderTraverse()
	{
		_InOrderTraverse(_root);

		cout<<endl;
	}

	//递归后序遍历
	void PostOrderTraverse()
	{
		_PostOrderTraverse(_root);

		cout<<endl;
	}

	//层序遍历
	void LevelOrderTraverse()
	{
		queue<BinaryTreeNode<T>*> q;

		if (_root)
		{
			q.push(_root);
		}

		while (!q.empty())
		{
			BinaryTreeNode<T>* front = q.front();
			q.pop();
			cout<<front->_data<<" ";

			if (front->_left)
			{
				q.push(front->_left);
			}

			if (front->_right)
			{
				q.push(front->_right);
			}
		}

		cout<<endl;
	}

	//非递归前序遍历
	void PreOrderTraverse_NonR()
	{
		stack<BinaryTreeNode<T>*> s;

		if (_root)
		{
			s.push(_root);
		}

		while (!s.empty())
		{
			BinaryTreeNode<T>* top = s.top();
			s.pop();
			cout<<top->_data<<" ";

			if (top->_right)
			{
				s.push(top->_right);
			}

			if (top->_left)
			{
				s.push(top->_left);
			}
		}

		cout<<endl;
	}

	//非递归中序遍历
	void InOrderTraverse_NonR()
	{
		stack<BinaryTreeNode<T>*> s;
		BinaryTreeNode<T>* cur = _root;

		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}

			if (!s.empty())
			{
				BinaryTreeNode<T>* top = s.top();
				cout<<top->_data<<" ";
				s.pop();

				cur = top->_right;
			}
		}

		cout<<endl;
	}

	//非递归后序遍历
	void PostOrderTraverse_NonR()
	{
		stack<BinaryTreeNode<T>*> s;
		BinaryTreeNode<T>* cur = _root;
		BinaryTreeNode<T>* preVisted = NULL;

		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}

			BinaryTreeNode<T>* top = s.top();
			if (NULL == top->_right
				|| preVisted == top->_right)
			{
				cout<<top->_data<<" ";
				preVisted = top;
				s.pop();
			}
			else
			{
				cur = top->_right;
			}
		}

		cout<<endl;
	}

	//结点数
	size_t Size()
	{
		return _Size(_root);
	}

	//深度
	size_t Depth()
	{
		return _Depth(_root);
	}

	//叶子结点数
	size_t LeafSize()
	{
		size_t size = 0;
		_GetLeafSize(_root, size);
		return size;
	}
protected:
	//构造二叉树
	BinaryTreeNode<T>* _CreateTree(const T* a, size_t size, size_t& index, const T& invalid)
	{
		BinaryTreeNode<T>* root = NULL;

		if (a[index] != invalid && index < size)
		{
			root = new BinaryTreeNode<T>(a[index]);
			root->_left = _CreateTree(a, size, ++index, invalid);
			root->_right = _CreateTree(a, size, ++index, invalid);
		}

		return root;
	}

	//销毁
	void _Destroy(BinaryTreeNode<T>*& root)
	{
		if (NULL == root)
		{
			return;
		}

		if (NULL == root->_left && NULL == root->_right)
		{
			delete root;
			root = NULL;
			return;
		}

		_Destroy(root->_left);
		_Destroy(root->_right);
		delete root;
	}

	//拷贝
	BinaryTreeNode<T>* _Copy(BinaryTreeNode<T>* root)
	{
		if (NULL == root)
		{
			return NULL;
		}

		BinaryTreeNode<T>* newRoot = new BinaryTreeNode<T>(root->_data);
		newRoot->_left = _Copy(root->_left);
		newRoot->_right = _Copy(root->_right);

		return newRoot;
	}

	//递归前序遍历
	void _PreOrderTraverse(BinaryTreeNode<T>* root)
	{
		if (NULL == root)
		{
			return;
		}

		cout<<root->_data<<" ";
		_PreOrderTraverse(root->_left);
		_PreOrderTraverse(root->_right);
	}

	//递归中序遍历
	void _InOrderTraverse(BinaryTreeNode<T>* root)
	{
		if (NULL == root)
		{
			return;
		}

		_InOrderTraverse(root->_left);
		cout<<root->_data<<" ";
		_InOrderTraverse(root->_right);
	}

	//递归后序遍历
	void _PostOrderTraverse(BinaryTreeNode<T>* root)
	{
		if (NULL == root)
		{
			return;
		}

		_PostOrderTraverse(root->_left);
		_PostOrderTraverse(root->_right);
		cout<<root->_data<<" ";
	}

	//结点数
	size_t _Size(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
		{
			return 0;
		}

		return _Size(root->_left) + _Size(root->_right) + 1;
	}

	//深度
	size_t _Depth(BinaryTreeNode<T>* root)
	{
		if (root == NULL)
		{
			return 0;
		}

		size_t leftDepth = _Depth(root->_left);
		size_t rightDepth = _Depth(root->_right);

		return leftDepth < rightDepth ? leftDepth+1 : rightDepth+1;
	}

	//叶子结点数
	void _GetLeafSize(BinaryTreeNode<T>* root, size_t& size)
	{
		if (NULL == root)
		{
			return;
		}

		if (NULL == root->_left && NULL == root->_right)
		{
			++size;
			return;
		}

		_GetLeafSize(root->_left, size);
		_GetLeafSize(root->_right, size);
	}
protected:
	BinaryTreeNode<T>* _root;
};

void Test()
{
	int a[] = {1, 2, 3, ‘#‘, ‘#‘, 4, ‘#‘, ‘#‘, 5, 6};
	BinaryTree<int> t(a, sizeof(a)/sizeof(a[0]), ‘#‘);

	cout<<"前序遍历:";
	t.PreOrderTraverse();
	cout<<"中序遍历:";
	t.InOrderTraverse();
	cout<<"后序遍历:";
	t.PostOrderTraverse();
	cout<<"层序遍历:";
	t.LevelOrderTraverse();
	cout<<"非递归前序遍历:";
	t.PreOrderTraverse_NonR();
	cout<<"非递归中序遍历:";
	t.InOrderTraverse_NonR();
	cout<<"非递归后序遍历:";
	t.PostOrderTraverse_NonR();
	cout<<"Size = "<<t.Size()<<endl;
	cout<<"Depth = "<<t.Depth()<<endl;
	cout<<"LeafSize = "<<t.LeafSize()<<endl;

	BinaryTree<int> t2(t);
	cout<<"t2:";
	t2.PreOrderTraverse();

	BinaryTree<int> t3;
	t3 = t2;
	cout<<"t3:";
	t3.PreOrderTraverse();
}

int main()
{
	Test();

	return 0;
}

时间: 2024-11-09 02:10:32

C++实现二叉树的相关文章

C#实现二叉树的遍历

C#实现二叉树的前序.中序.后序遍历. public class BinaryTreeNode     {         int value;         BinaryTreeNode left;         BinaryTreeNode right;         /// <summary>         /// 前序遍历         /// </summary>         /// <param name="tree">&l

【树4】二叉树的遍历

简介 遍历二叉树就是按照某种顺序,将树中的结点都枚举一遍,且每个结点仅仅访问一次.因为树不是线性的结构,遍历不像线性表那样简单,因此他的遍历需要特点的算法来完成. 从某种角度讲,对二叉树的遍历就是将树形结构转换为线性结构的操作. 二叉树的遍历方法主要有如下几种: 先序遍历:先访问root结点,再先序遍历左子树,再先序遍历右子树. 中序遍历:先中序遍历左子树,再访问root结点,再中序遍历右子树. 后序遍历:先后序遍历左子树,再后序遍历右子树,再访问root结点. 层遍历:从上到下,从左到右,一层

按之字形顺序打印二叉树

题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推 /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: vector<vect

【数据算法】Java实现二叉树存储以及遍历

二叉树在java中我们使用数组的形式保存原数据,这个数组作为二叉树的数据来源,后续对数组中的数据进行节点化操作. 步骤就是原数据:数组 节点化数据:定义 Node节点对象 存储节点对象:通过LinkedList保存Node节点对象 在操作过程中我们需要将当前结点和前一节点.后一节点进行关系绑定 package tree; import java.util.LinkedList; import java.util.List; /** * 功能:把一个数组的值存入二叉树中,然后进行3种方式的遍历 *

二叉树的后序遍历(暴力版) 小白菜oj 1034

给出二叉树的前序遍历和中序遍历,求二叉树的后序遍历-- 作为一个搜索蒟蒻,我真的没有办法很和谐的A掉,但估计过几天就会写有关这个题的和谐的解法--但只是估计-- 下面讲述我的超暴力解法-- 首先,先由前序遍历得到一个父亲节点,然后再由中序遍历得到这个父亲节点的左子树和右子树中的元素(中序遍历中,该点的左边的所有点,都在它的左子树,右边的都在它的右子树,子树中的根节点是在这些节点的前序遍历中排名最靠前的),然后递归建树,之后在递归求后序遍历即可. 但这个方法有两个比较--&¥--&的问题:1

二叉树的序列化和反序列化

http://blog.csdn.net/qq_27703417/article/details/70958692 先序遍历二叉树,如果遇到空节点,就在str的末尾加上"#!","#"表示这个节点为空,节点值不存在,当然你也可以用其他的特殊字符,"!"表示一个值的结束.如果遇到不为空的节点,假设节点值为3,就在str的末尾加上"3!".现在请你实现树的先序序列化. 先序遍历 import java.util.*; //使用递归

【二叉树】 二叉树基础

在计算机科学中,二叉树是每个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(right subtree).二叉树常被用于实现二叉查找树和二叉堆. 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒.二叉树的第i层至多有个结点:深度为k的二叉树至多有个结点:对任何一棵二叉树T,如果其终端结点数为,度为2的结点数为,则. 树和二叉树的三个主要差别: 树的结点个数至少为1,而二叉树的

二叉树的深度

输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 思路:使用递归的方法分别计算左右子树的深度 public class Solution { public int TreeDepth(TreeNode pRoot){ return pRoot == null? 0 : Math.max(TreeDepth(pRoot.left),TreeDepth(pRoot.right)) + 1;     } }

226反转二叉树 Invert Binary Tree

Invert a binary tree. 4 / 2 7 / \ / 1 3 6 9 to 4 / 7 2 / \ / 9 6 3 1 Trivia:This problem was inspired by this original tweet by Max Howell: Google: 90% of our engineers use the software you wrote (Homebrew), but you can't invert a binary tree on a wh

树、二叉树、森林的转换

树转换为二叉树 (1)加线.在所有兄弟结点之间加一条连线. (2)去线.树中的每个结点,只保留它与第一个孩子结点的连线,删除它与其它孩子结点之间的连线. (3)层次调整.以树的根节点为轴心,将整棵树顺时针旋转一定角度,使之结构层次分明.(注意第一个孩子是结点的左孩子,兄弟转换过来的孩子是结点的右孩子) 森林转换为二叉树 (1)把每棵树转换为二叉树. (2)第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来. 二叉树转换为树 是树转换为二