二叉树 (C++)

1.前言

数据结构 二叉树

测试数据:利用先序遍历二叉树建树(包括所有空结点)
'*'表示空结点

①测试数据1

ABC**DE*G**F***1:
	    A
	 B
   C    D
      E   F
       G
树深度为5(根结点为1)3个叶结点C、G、F
先序遍历:ABCDEGF
中序遍历:CBEGDFA
后序遍历:CGEFDBA
层序遍历:ABCDEFG

②测试数据2

AB**CD***2:
		A
	  B   C
	     D
树深度为3(根结点为1)2个叶结点B、D
先序遍历:ABCD
中序遍历:BADC
后序遍历:BDCA
层序遍历:ABCD

2.内容

1.二叉树的遍历

①先序遍历

[1]递归
//Recursion Preorder Traverse
void Preorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	v.emplace_back(T->val);  //根
	Preorder(T->left, v);    //左
	Preorder(T->right, v);   //右
}
vector<ElemType> PreorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Preorder(T, v);
	return v;
}
[2]迭代
	stack<Tree> preOrderStk;
	vector<ElemType> preOrderVec;
	Tree preTree = T;
	while (preTree || preOrderStk.size())
	{
		while (preTree)
		{
			preOrderVec.emplace_back(preTree->val);
			preOrderStk.emplace(preTree);
			preTree = preTree->left;
		}
		preTree = preOrderStk.top();
		preOrderStk.pop();
		preTree = preTree->right;
	}
	printf("迭代先序遍历:");
	for (const ElemType& x : preOrderVec)
		cout << x;
	puts("");

力扣先序遍历

144. 二叉树的前序遍历

②中序遍历

[1]递归
//Recursion Inorder Traverse
void Inorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	Inorder(T->left, v);    //左
	v.emplace_back(T->val); //根
	Inorder(T->right, v);   //右
}
vector<ElemType> InorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Inorder(T, v);
	return v;
}

[2]迭代
	stack<Tree> inOrderStk;
	vector<ElemType> inOrderVec;
	Tree inTree = T;
	while (inTree || inOrderStk.size())
	{
		while (inTree)
		{
			inOrderStk.emplace(inTree);
			inTree = inTree->left;
		}
		inTree = inOrderStk.top();
		inOrderStk.pop();
		inOrderVec.emplace_back(inTree->val);
		inTree = inTree->right;
	}
	printf("迭代中序遍历为:");
	for (const ElemType& x : inOrderVec)
		cout << x;
	puts("");

力扣中序遍历

94. 二叉树的中序遍历

③后序遍历

[1]递归
//Recursion Postorder Traverse
void Postorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	Postorder(T->left, v);
	Postorder(T->right, v);
	v.emplace_back(T->val);
}
vector<ElemType> PostorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Postorder(T, v);
	return v;
}
[2]迭代
	stack<Tree> postOrderStk;
	vector<ElemType> postOrderVec;
	Tree postTree = T;
	Tree prev = nullptr;
	while (postTree || postOrderStk.size())
	{
		while (postTree)
		{
			postOrderStk.emplace(postTree);
			postTree = postTree->left;
		}
		postTree = postOrderStk.top();
		postOrderStk.pop();
		if (postTree->right == nullptr || postTree->right == prev) //无右子树 或 为第二次遍历的根
		{
			postOrderVec.emplace_back(postTree->val);
			prev = postTree;
			postTree = nullptr;
		}
		else {
			postOrderStk.emplace(postTree);
			postTree = postTree->right;
		}
	}
	printf("迭代后序遍历为:");
	for (const ElemType& x : postOrderVec)
		cout << x;
	puts("");
力扣后序遍历

145. 二叉树的后序遍历

④层序遍历

[1]队列
	//[1]队列  传空树时要特判
	queue<Tree> levelOrderQue;
	vector<vector<ElemType>> levelOrderVec;
	vector<ElemType> leafVec;   //叶结点
	levelOrderQue.emplace(T);
	while (levelOrderQue.size())
	{
		int sz = levelOrderQue.size();
		vector<ElemType> v;
		for (int i = 0; i < sz; ++i)
		{
			auto t = levelOrderQue.front();
			levelOrderQue.pop();

			v.emplace_back(t->val);
			if (t->left) levelOrderQue.emplace(t->left);
			if (t->right) levelOrderQue.emplace(t->right);
			if (t->left == nullptr && t->right == nullptr) leafVec.emplace_back(t->val);  //叶结点
		}
		levelOrderVec.emplace_back(v);
	}
	cout << "树的深度为: " << levelOrderVec.size() << endl;
	cout << "树的叶结点个数为: " << leafVec.size() << " 分别为: ";
	for (const ElemType& x : leafVec)
		cout << x << " ";
	puts("");
	printf("层序遍历为:");
	for (const vector<ElemType>& x : levelOrderVec)
		for (const ElemType& y : x)
			cout << y;
	puts("");

2.队列 + 哈希
	//[2]队列 + 哈希[注意传入空树时,要特判!]
	queue<Tree> q;
	unordered_map<int, vector<ElemType>> v;
	unordered_map<Tree, int> dep;
	vector<ElemType> leaf;
	q.emplace(T);
	dep[T] = 0;
	int depth = 0;
	while (q.size())
	{
		auto t = q.front();
		q.pop();

		int d = dep[t];
		v[d].emplace_back(t->val);
		if (t->left) q.emplace(t->left), dep[t->left] = d + 1;
		if (t->right) q.emplace(t->right), dep[t->right] = d + 1;
		if (t->left == nullptr && t->right == nullptr) leaf.emplace_back(t->val), depth = max(depth, d);
	}
	cout << "树的深度为:" << depth + 1 << endl;
	cout << "树的叶结点数为:" << leaf.size() << " 分别是:";
	for (auto l : leaf)
		cout << l << " ";
	puts("");
	printf("层序遍历为:");
	for (int i = 0; i <= depth; ++i)
		for (auto x : v[i])
			cout << x;
	puts("");

力扣层序遍历

102. 二叉树的层序遍历

※※二叉树遍历的完整代码

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
using namespace std;
#include <vector>  
#include <stack>  //迭代先序、中序、后序遍历
#include <queue> //层序遍历1
#include <unordered_map> //层序遍历2

//Definations
typedef char ElemType;
typedef struct TreeNode {
	ElemType val;
	struct TreeNode* left, * right;
	TreeNode() :val(-1), left(nullptr), right(nullptr) {}
	TreeNode(ElemType e) :val(e), left(nullptr), right(nullptr) {}
}TreeNode, *Tree;

//Build BiTree
void InitBiTree(Tree& T)
{
	char ch;
	scanf("%c", &ch);
	if (ch == '*') T = nullptr;
	else {
		T = (Tree)malloc(sizeof(TreeNode));
		if(T == NULL)exit(OVERFLOW);

		T->val = ch;
		InitBiTree(T->left);
		InitBiTree(T->right);
	}
}

//Recursion Preorder Traverse
void Preorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	v.emplace_back(T->val);  //根
	Preorder(T->left, v);    //左
	Preorder(T->right, v);   //右
}
vector<ElemType> PreorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Preorder(T, v);
	return v;
}
//Recursion Inorder Traverse
void Inorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	Inorder(T->left, v);    //左
	v.emplace_back(T->val); //根
	Inorder(T->right, v);   //右
}
vector<ElemType> InorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Inorder(T, v);
	return v;
}
//Recursion Postorder Traverse
void Postorder(const Tree& T, vector<ElemType>& v)
{
	if (T == nullptr) return;
	Postorder(T->left, v);
	Postorder(T->right, v);
	v.emplace_back(T->val);
}
vector<ElemType> PostorderTraversal(const Tree& T)
{
	vector<ElemType> v;
	Postorder(T, v);
	return v;
}

int main()
{
	//1.建树
	Tree T;
	InitBiTree(T);

	//2.递归遍历
	//[1]先序
	vector<ElemType> preOrderVector = PreorderTraversal(T);
	printf("递归先序遍历:");
	for (const ElemType ch : preOrderVector)
		cout << ch;
	puts("");
	//[2]中序
	vector<ElemType> inOrderVector = InorderTraversal(T);
	printf("递归中序遍历:");
	for (const ElemType ch : inOrderVector)
		cout << ch;
	puts("");
	//[3]后序
	vector<ElemType> postOrderVector = PostorderTraversal(T);
	printf("递归后序遍历:");
	for (const ElemType ch : postOrderVector)
		cout << ch;
	puts("");

	//3.迭代遍历
	//[1]先序
	stack<Tree> preOrderStk;
	vector<ElemType> preOrderVec;
	Tree preTree = T;
	while (preTree || preOrderStk.size())
	{
		while (preTree)
		{
			preOrderVec.emplace_back(preTree->val);
			preOrderStk.emplace(preTree);
			preTree = preTree->left;
		}
		preTree = preOrderStk.top();
		preOrderStk.pop();
		preTree = preTree->right;
	}
	printf("迭代先序遍历:");
	for (const ElemType& x : preOrderVec)
		cout << x;
	puts("");


	//中序
	stack<Tree> inOrderStk;
	vector<ElemType> inOrderVec;
	Tree inTree = T;
	while (inTree || inOrderStk.size())
	{
		while (inTree)
		{
			inOrderStk.emplace(inTree);
			inTree = inTree->left;
		}
		inTree = inOrderStk.top();
		inOrderStk.pop();
		inOrderVec.emplace_back(inTree->val);
		inTree = inTree->right;
	}
	printf("迭代中序遍历为:");
	for (const ElemType& x : inOrderVec)
		cout << x;
	puts("");

	//后序
	stack<Tree> postOrderStk;
	vector<ElemType> postOrderVec;
	Tree postTree = T;
	Tree prev = nullptr;
	while (postTree || postOrderStk.size())
	{
		while (postTree)
		{
			postOrderStk.emplace(postTree);
			postTree = postTree->left;
		}
		postTree = postOrderStk.top();
		postOrderStk.pop();
		if (postTree->right == nullptr || postTree->right == prev) //无右子树 或 为第二次遍历的根
		{
			postOrderVec.emplace_back(postTree->val);
			prev = postTree;
			postTree = nullptr;
		}
		else {
			postOrderStk.emplace(postTree);
			postTree = postTree->right;
		}
	}
	printf("迭代后序遍历为:");
	for (const ElemType& x : postOrderVec)
		cout << x;
	puts("");


	//4.层序遍历
	//[1]队列
	queue<Tree> levelOrderQue;
	vector<vector<ElemType>> levelOrderVec;
	vector<ElemType> leafVec;   //叶结点
	levelOrderQue.emplace(T);
	while (levelOrderQue.size())
	{
		int sz = levelOrderQue.size();
		vector<ElemType> v;
		for (int i = 0; i < sz; ++i)
		{
			auto t = levelOrderQue.front();
			levelOrderQue.pop();

			v.emplace_back(t->val);
			if (t->left) levelOrderQue.emplace(t->left);
			if (t->right) levelOrderQue.emplace(t->right);
			if (t->left == nullptr && t->right == nullptr) leafVec.emplace_back(t->val);  //叶结点
		}
		levelOrderVec.emplace_back(v);
	}
	cout << "树的深度为: " << levelOrderVec.size() << endl;
	cout << "树的叶结点个数为: " << leafVec.size() << " 分别为: ";
	for (const ElemType& x : leafVec)
		cout << x << " ";
	puts("");
	printf("层序遍历为:");
	for (const vector<ElemType>& x : levelOrderVec)
		for (const ElemType& y : x)
			cout << y;
	puts("");

	//[2]队列 + 哈希[注意传入空树时,要特判!]
	queue<Tree> q;
	unordered_map<int, vector<ElemType>> v;
	unordered_map<Tree, int> dep;
	vector<ElemType> leaf;
	q.emplace(T);
	dep[T] = 0;
	int depth = 0;
	while (q.size())
	{
		auto t = q.front();
		q.pop();

		int d = dep[t];
		v[d].emplace_back(t->val);
		if (t->left) q.emplace(t->left), dep[t->left] = d + 1;
		if (t->right) q.emplace(t->right), dep[t->right] = d + 1;
		if (t->left == nullptr && t->right == nullptr) leaf.emplace_back(t->val), depth = max(depth, d);
	}
	cout << "树的深度为:" << depth + 1 << endl;
	cout << "树的叶结点数为:" << leaf.size() << " 分别是:";
	for (auto l : leaf)
		cout << l << " ";
	puts("");
	printf("层序遍历为:");
	for (int i = 0; i <= depth; ++i)
		for (auto x : v[i])
			cout << x;
	puts("");
	return 0;
}

3.总结

绕行踩点法
递归方法较易,迭代需要思考

4.更新日志

2022.12.2 整理 二叉树的遍历

欢迎评论留言、指正~~

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值