【数据结构】二叉树的递归与非递归创建和遍历

下面代码所用到的测试用例画成树的样子长这样:


创建树时给的是数组,用‘#’代表非法值,即该结点为空。

二叉树的递归实现:

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

template<class T>
struct BinaryTreeNode
{
	BinaryTreeNode(T value=0)
	:_value(value), _left(NULL), _right(NULL)
	{}
	T _value;
	BinaryTreeNode<T>* _left;
	BinaryTreeNode<T>* _right;
};

template<class T>
class BinaryTree
{
public:
	typedef BinaryTreeNode<T> Node;
	BinaryTree()
	{}
	BinaryTree(T* a, size_t size, const T& invalid)
	{
		size_t index = 0;
		_root=_CreatTree( a, size,index, invalid);
	}
	BinaryTree(const BinaryTree<T>& bt)
	{
		_root = _Copy(bt._root);
	}
	BinaryTree<T>& operator=(BinaryTree<T>& bt)
	{
		if (this != &bt)
		{
			BinaryTree<T> tmp(bt);
			swap(tmp._root, _root);

		}
	}
	~BinaryTree()
	{
		_Distory(_root);
	}

	void PrevOrder()
	{
		_PrevOrder(_root);
		cout << endl;
	}
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	void PostOrder()
	{
		_PostOrder(_root);
		cout << endl;
	}
	void LevelOrder()  //层序遍历
	{
		_LevelOrder(_root);
		cout << endl;
	}

	size_t Size()
	{
		return _Size(_root);
	}
	size_t Depth()
	{
		return _Depth(_root);
	}
	size_t LeafSize()
	{
		return _LeafSize(_root);
	}
	size_t GetKLevel(size_t k)  //第K层结点个数
	{

	}
protected:

	Node* _Distory(Node* root)
	{
		if (root)
		{
			_Distory(root->_left);
			_Distory(root->_right);
			Node* del = root;
			delete del;
		}
		return root;
	}
	Node* _CreatTree( T*a, size_t size,size_t& index,const T& invalid)
	{
		Node* root = NULL;
		if ((index < size)&&(a[index] != invalid))
		{
			root = new Node(a[index]);
			root->_left = _CreatTree(a, size, ++index, invalid);
			root->_right = _CreatTree(a, size, ++index, invalid);
		}
		return root;
	}

	Node* _Copy(Node* copyroot)
	{
		Node* root = NULL;
		if (copyroot!=NULL)
		{
			root = new Node(copyroot->_value);
			root->_left = _Copy(copyroot->_left);
			root->_right = _Copy(copyroot->_right);
		}
		return root;
	}

	Node* _PrevOrder(Node* root)
	{
		if (root)
		{
			cout << root->_value << " ";
			_PrevOrder(root->_left);
			_PrevOrder(root->_right);
		}
		return root;
	}

	Node* _InOrder(Node* root)
	{
		if (root)
		{
			_InOrder(root->_left);
			cout << root->_value<<" ";
			_InOrder(root->_right);
		}
		return root;
	}

	Node* _PostOrder(Node* root)
	{
		if (root)
		{
			_PostOrder(root->_left);
			_PostOrder(root->_right);
			cout << root->_value << " ";
		}
		return root;
	}

	void _LevelOrder(Node* root)
	{
		queue<Node*> q;
		q.push(root);
		while (!q.empty())
		{
			Node* tmp = q.front();
			cout << tmp->_value<<" ";
			
			if (tmp->_left)
				q.push(tmp->_left);
			if (tmp->_right)
				q.push(tmp->_right);
			q.pop();
		}
	}

	size_t _Size(Node* root)
	{
		size_t size = 0;
		if (root)
		{
			size = _Size(root->_left) + _Size(root->_right)+1;
		}
		return size;
	}

	size_t _Depth(Node* root)
	{
		size_t depth1 = 0;
		size_t depth2 = 0;
		if (root)
		{
			depth1 = _Depth(root->_left) + 1;
			depth2 = _Depth(root->_right) + 1;
		}
		return depth1 > depth2 ? depth1 : depth2;
	}

	size_t _LeafSize(Node* root)
	{
		if (root == NULL)
			return 0;
		else if (root->_left == NULL&&root->_right == NULL)
			return 1;
		return _LeafSize(root->_left) + _LeafSize(root->_right);
	}
private:
	Node* _root;
};

void test()
{
	int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
	int array1[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
	BinaryTree<int> bt(array, 10, '#');
	bt.PrevOrder();
	bt.InOrder();
	bt.PostOrder();
	cout << bt.Size() << endl;
	cout << bt.Depth() << endl;
	cout << bt.LeafSize() << endl;
	BinaryTree<int> bt2(array1, 15, '#');
	cout << bt2.Depth() << endl;
	cout << bt2.LeafSize() << endl;
	BinaryTree<int> bt3(bt);
	bt3.PrevOrder();
	BinaryTree<int> bt4=bt3;
	bt4.PrevOrder();
	bt4.LevelOrder();
}

递归的好处在于代码简练。但递归不容易理解。

非递归的二叉树(面试经常会考的):

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

template<class T>
struct BinaryTreeNode
{
	BinaryTreeNode(T value = 0)
	:_value(value), _left(NULL), _right(NULL)
	{}
	T _value;
	BinaryTreeNode<T>* _left;
	BinaryTreeNode<T>* _right;
};

template<class T>
class BinaryTree
{
public:
	typedef BinaryTreeNode<T> Node;
	BinaryTree()
	{}
	explicit BinaryTree(T* a, size_t size, const T& invalid)    //构造函数,创建一棵树。
	{
		stack<Node*> s;
		size_t index = 0;
		Node* cur = NULL;
		while (index < size)
		{
			while ((index < size) && (a[index] != invalid))
			{
				if (index == 0)
				{
					_root = new Node(a[index++]);
					cur = _root;
				}
				else
				{
					cur->_left = new Node(a[index++]);
					cur = cur->_left;
				}
				s.push(cur);
			}
			index++;
			Node* top = s.top();
			s.pop();
			if ((index < size) && (a[index] != invalid))
			{
				cur = top;
				cur->_right = new Node(a[index++]);
				cur = cur->_right;
				s.push(cur);
			}
		}
	}

	BinaryTree(const BinaryTree<T>& bt)  //拷贝构造
	{
		Node* cur = bt._root;
		Node* root = NULL;
		stack<Node*>s;
		stack<Node*>s1;
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				if (root == NULL)
				{
					root = new Node(cur->_value);
					_root = root;
				}
				else
				{
					root->_left = new Node(cur->_value);
					root = root->_left;
				}
				cur = cur->_left;
				s1.push(root);
			}
			Node* top = s.top();
			Node* top1 = s1.top();
			s.pop();
			s1.pop();

			cur = top->_right;
			if (cur)
			{
				root = top1;
				root->_right = new Node(cur->_value);
				root = root->_right;
				cur = cur->_left;
			}
		}
	}

	BinaryTree<T>& operator=(BinaryTree<T> bt)
	{
		swap(_root, bt._root);
		return *this;
	}

	void PrevOrderNoR()
	{
		Node* cur = _root;
		stack<Node*> s;
		while (cur || !s.empty())
		{
			while (cur)
			{
				cout << cur->_value << " ";
				s.push(cur);
				cur = cur->_left;
			}
			Node* top = s.top();
			s.pop();
			cur = top->_right;
		}
		cout << endl;
	}
	void InOrderNoR()
	{
		Node* cur = _root;
		stack<Node*> s;
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}
			Node* top = s.top();
			s.pop();
			cout << top->_value << " ";
			cur = top->_right;
		}
		cout << endl;
	}

	void PostOrderNoR()
	{
		Node* cur = _root;
		Node* prev = NULL;
		stack<Node*> s;
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}
			Node* top = s.top();
			
			if ((top->_right == NULL) || (prev == top->_right))
			{
				prev = top;
				cout << top->_value << " ";
				s.pop();
				//cur = top->_right;
			}
			else
				cur = top->_right;
		}
		cout << endl;
	}

	size_t SizeNoR()
	{
		size_t size = 0;
		Node* cur = _root;
		stack<Node*> s;
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				size++;
				cur = cur->_left;
			}
			Node* top = s.top();
			s.pop();
			cur = top->_right;
		}
		return size;
	}

	size_t DepthNoR()
	{
		if (_root == NULL)
			return 0;
		size_t depth = 0;
		Node* cur = NULL;
		queue<Node*> q;
		size_t VisitNum = 0;  //有多少数据出栈
		size_t NodeNum = 1;
		size_t LeveNum = 1;  //每一层最后一个数据的序号
		q.push(_root);
		while (!q.empty())
		{
			cur = q.front();
			q.pop();
			VisitNum++;
			
			if (cur->_left)
			{
				NodeNum++;
				q.push(cur->_left);
			}
			if (cur->_right)
			{
				NodeNum++;
				q.push(cur->_right);
			}
			if (LeveNum == VisitNum)
			{
				depth++;
				LeveNum = NodeNum;
			}
		}
		return depth;
	}

	size_t LeveNum()  //叶子节点个数
	{
		size_t count = 0;
		Node* cur = _root;
		stack<Node*> s; 
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				if ((cur->_left == NULL) && (cur->_right == NULL))
					count++;
				cur = cur->_left;
			}

			Node* top = s.top();
			s.pop();
			cur = top->_right;
		}
		return count;
	}
	size_t GetKLeve(size_t k)  //得到第k层结点个数。
	{
		assert(k <= DepthNoR());
		if (k == 1)
			return 1;
		queue<Node*>q;
		size_t NodeNum = 1;
		size_t LeveNum = 1;
		size_t VisitNum = 0;
		size_t leve = 1;
		q.push(_root);
		while (!q.empty())
		{
			Node* cur = q.front();
			q.pop();
			VisitNum++;
			if (cur->_left)
			{
				q.push(cur->_left);
				NodeNum++;
			}
			if (cur->_right)
			{
				q.push(cur->_right);
				NodeNum++;
			}
			if (LeveNum == VisitNum)
			{
				leve++;
				if (leve == k)
					break;
				LeveNum = NodeNum;
			}
		}
		return NodeNum - VisitNum;
	}
private:
	Node* _root;
};

void test()
{
	int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
	BinaryTree<int> bt(array, 10, '#');
	bt.PrevOrderNoR();
	bt.InOrderNoR();
	bt.PostOrderNoR();
	BinaryTree<int> bt1(bt);
	bt1.PrevOrderNoR();
	BinaryTree<int> bt2 = bt1;
	bt2.PrevOrderNoR();
	cout << bt.SizeNoR() << endl;
	cout << bt.DepthNoR() << endl;
	cout << bt.LeveNum() << endl;
	cout << bt.GetKLeve(3) << endl;
}

可以看到,非递归相对来说代码量能多点,但是比较容易理解,而且几个遍历过程代码十分相似,理解其中一个,后面几个都是类似的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值