二叉树的四种遍历方式(递归与非递归实现)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43949535/article/details/100726391

2019年9月11日09:13:41
二叉树的遍历向来是 二叉树学习和应用的重中之重,虽然树结构 使用递归会使得我们的代码更加简洁,但是在这里 我也把非递归版本代码也进行详解。而二叉树 作为DSA中极为重要的一种数据结构,二叉树的基础学习是给后面学习 更加高级的数据结构做铺垫的。话不多说,先看一下 二叉树的遍历吧。

基本概念

遍历:从这棵树的根节点出发,按照某种 次序 逐个依次访问树中的每个节点,直到所有节点都被 有且只有一次被访问到为止。
次序:树的一对多的关系,也就决定了 不同于之前线性结构的比较简单的遍历次序(从头到尾、从尾到头、循环、双向等)。正如这种一对多的结构,决定了 树不存在所谓的 唯一前驱和后继的关系,那么在成功遍历一个节点之后 遍历哪个节点是有多个选择的。正是这里不同的选择也确定了不同的遍历次序,因此树就有了这几种遍历方式。
访问:上面说的访问的意思就是:根据我们的需要所进行的动作。最常见的访问其值val,或者进行一些其他的节点操作等。

二叉树的遍历方式

二叉树的遍历方式是有很多种的,但是通常我们规定为从左到右的遍历方式(当然从右到左也是可以的,只是可能不太符合人们的习惯),遍历主要分为以下四种:

  1. 先序遍历
  2. 中序遍历
  3. 后序遍历
  4. 层序遍历

先序遍历

其定义:若二叉树为空,则空操作返回;不为空则先访问根结点,然后先序遍历左子树,再先序遍历右子树。遍历过程如下图所示:
在这里插入图片描述
因此上面这棵二叉树的 先序遍历,次序为:ABDGHCEIF
遍历步骤如下

  1. 二叉树不空,访问根节点,即A
  2. A的左子树不空,先序遍历A的左子树。左子树的根节点为B,访问 即:AB
  3. B的左子树不空,先序遍历B的左子树。左子树的根节点为D,访问 即:ABD
  4. D的左子树不空,先序遍历D的左子树。左子树的根节点为G,访问 即:ABDG
  5. G的左子树为空 返还上一层
  6. G的右子树为空 返还上一层
  7. D的右子树不空,先序遍历D的右子树。右子树的根节点为H,访问 即:ABDGH
  8. H的左子树为空 返还上一层
  9. H的右子树为空 返还上一层
  10. B的右子树为空 返还上一层
  11. A的右子树不空,先序遍历A的右子树。右子树的根节点为C,访问 即:ABDGHC
  12. C的左子树不空,先序遍历C的左子树。左子树的根节点为E,访问 即:ABDGHCE
  13. E的左子树为空 返还上一层
  14. E的右子树不空,先序遍历E的右子树。右子树的根节点为I,访问 即:ABDGHCEI
  15. I的左子树为空 返还上一层
  16. I的右子树为空 返还上一层
  17. C的右子树不空,先序遍历C的右子树。右子树的根节点为F,访问 即:ABDGHCEIF
  18. F的左子树为空 返还上一层
  19. F的右子树为空 返还上一层

代码如下:

1.1 先序遍历的递归版本如下:

/**
 * 先序遍历的递归实现,直接根据定义,首先先访问根节点,
 * 然后先序遍历左子树,接着先序遍历右子树。
 * 上述的每个先序遍历就是一个递归的过程。
 */
class TreeNode
{
public:
	TreeNode(char C):val(C),left(nullptr),right(nullptr){}
	
	//先序遍历 递归实现
	static void preOrder_Operator(TreeNode* this_root, vector<char>& vec)
	{
		if (this_root != nullptr)
		{
			vec.push_back(this_root->val);
			preOrder_Operator(this_root->left, vec);
			preOrder_Operator(this_root->right, vec);
		}
	}
	//先序遍历 把顺序保存在一个数组中 递归实现
	vector<char> preOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		preOrder_Operator(root, myvec);
		return myvec;
	}

	char val;
	TreeNode* left;
	TreeNode* right;
};

测试如下:
在这里插入图片描述
代码如下:

1.2 先序遍历的非递归版本如下:

/*
 * 先序遍历的非递归实现,需要借助栈这个数据结构,由于前先遍历是
 * 先访问根节点,然后前序遍历左子树,接着前序遍历右子树。
 * 那么非递归实现的话,先压入根节点,然后打印栈顶元素,但是由于
 * 出栈和入栈的顺序是相反的,因此我们接着需要先压入右孩子,再压入左孩子
 * 然后打印栈顶元素,继续压入左孩子的右孩子,左孩子的左孩子···
 * 上述便是迭代循环的过程。
 */
//先序遍历 把顺序保存在一个数组中 非递归实现
	vector<char> preOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;
		mystack.push(root);
		while (!mystack.empty())
		{
			TreeNode* top_node = mystack.top();
			myvec.push_back(top_node->val);
			mystack.pop();

			//出栈和入栈的顺序是相反的
			if (top_node->right != nullptr)
			{
				mystack.push(top_node->right);
			}
			if (top_node->left != nullptr)
			{
				mystack.push(top_node->left);
			}
		}
		return myvec;
	}

在这里插入图片描述

中序遍历

其定义:若二叉树为空,则空操作返回;不为空则从根结点开始(注:并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。遍历过程如下图所示:在这里插入图片描述
因此上面这棵二叉树的 中序遍历,次序为:GDHBAEICF
遍历步骤如下

  1. 二叉树不空,根节点A存在左子树,则中序遍历其左子树。左子树根为B
  2. B存在左子树,则中序遍历其左子树。左子树根为D
  3. D存在左子树,则中序遍历其左子树。左子树根为G
  4. G的左子树为空,返还上一层
  5. 访问节点G,即G
  6. G的右子树为空,返还上一层
  7. 访问节点D,即GD
  8. D存在右子树,则中序遍历其右子树。右子树根为H
  9. H的左子树为空,返还上一层
  10. 访问节点H,即GDH
  11. H的右子树为空,返还上一层
  12. 访问节点B,即GDHB
  13. B的右子树为空,返还上一层
  14. 访问节点A,即GDHBA
  15. A存在右子树,则中序遍历其右子树。右子树根为C
  16. C存在左子树,则中序遍历其左子树。左子树根为E
  17. E的左子树为空,返还上一层
  18. 访问节点E,即GDHBAE
  19. E存在右子树,则中序遍历其右子树。右子树根为I
  20. I的左子树为空,返还上一层
  21. 访问节点I,即GDHBAEI
  22. I的右子树为空,返还上一层
  23. 访问节点C,即GDHBAEIC
  24. C存在右子树,则中序遍历其右子树。右子树根为F
  25. F的左子树为空,返还上一层
  26. 访问节点F,即GDHBAEICF
  27. F的右子树为空,返还上一层

代码如下:

2.1 中序遍历的递归版本如下:

/*
 * 中序遍历的递归实现,根据定义,首先中序遍历左子树,
 * 再打印根节点,然后再中序遍历右子树。
 * 上述的每个中序遍历就是一个递归的过程。
 */
//中序遍历 递归实现
	static void inOrder_Operator(TreeNode* this_root, vector<char>& vec)
	{
		if (this_root != nullptr)
		{
			inOrder_Operator(this_root->left, vec);
			vec.push_back(this_root->val);
			inOrder_Operator(this_root->right, vec);
		}
	}
	//中序遍历 把顺序保存在一个数组中 递归实现
	vector<char>inOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		inOrder_Operator(root, myvec);
		return myvec;
	}

测试如下:
在这里插入图片描述
代码如下:

2.2 中序遍历的非递归版本如下:

/*
 * 中序遍历的非递归实现,首先应该一直向左遍历,将结点压栈,
 * 直到结点为空,然后我们打印该节点值,并将其出栈,并继续遍历该节点的右子树
 * 继续上述过程。
 */
//中序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>inOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;
		TreeNode* top_node = root;

		while (!mystack.empty() || top_node!=nullptr)
		{
			if (top_node!= nullptr)//左孩子存在 一直走
			{
				mystack.push(top_node);
				top_node = top_node->left;
			}
			else
			{
				top_node = mystack.top();
				myvec.push_back(top_node->val);
				mystack.pop();

				top_node = top_node->right;
			}
		}
		return myvec;
	}

在这里插入图片描述

后序遍历

其定义:若二叉树为空,则空操作返回;不为空则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。遍历过程如下图所示:
在这里插入图片描述
因此上面这棵二叉树的 后序遍历,次序为:GHDBIEFCA
遍历步骤如下

  1. 二叉树不空,根节点A存在左子树,则后序遍历其左子树。左子树根为B
  2. B存在左子树,则后序遍历其左子树。左子树根为D
  3. D存在左子树,则后序遍历其左子树。左子树根为G
  4. G的左子树为空,返还上一层
  5. G的右子树为空,返还上一层
  6. 访问节点G,即G
  7. D存在右子树,则后序遍历其左子树。右子树根为H
  8. H的左子树为空,返还上一层
  9. H的右子树为空,返还上一层
  10. 访问节点H,即GH
  11. 访问节点D,即GHD
  12. B的右子树为空,返还上一层
  13. 访问节点B,即GHDB
  14. A存在右子树,则后序遍历其右子树。右子树根为C
  15. C存在左子树,则后序遍历其左子树。左子树根为E
  16. E的左子树为空,返还上一层
  17. E存在右子树,则后序遍历其右子树。右子树根为I
  18. I的左子树为空,返还上一层
  19. I的右子树为空,返还上一层
  20. 访问节点I,即GHDBI
  21. 访问节点E,即GHDBIE
  22. C存在右子树,则后序遍历其右子树。右子树根为F
  23. F的左子树为空,返还上一层
  24. F的右子树为空,返还上一层
  25. 访问节点F,即GHDBIEF
  26. 访问节点C,即GHDBIEFC
  27. 访问节点A,即GHDBIEFCA

代码如下:

3.1 后序遍历的递归版本如下:

/*
 * 后序遍历的递归实现,只需先后序遍历左子树,再后序遍历右子树
 * 最后打印根节点值即可。
 * 上述的每个后序遍历就是一个递归的过程。
 */
 //后序遍历 递归实现
	static void lastOrder_Operator(TreeNode* this_root, vector<char>& vec)
	{
		if (this_root != nullptr)
		{
			lastOrder_Operator(this_root->left, vec);		
			lastOrder_Operator(this_root->right, vec);
			vec.push_back(this_root->val);
		}
	}
	//后序遍历 把顺序保存在一个数组中 递归实现
	vector<char>lastOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		lastOrder_Operator(root, myvec);
		return myvec;
	}

测试如下:
在这里插入图片描述
代码如下:

3.2 后序遍历的非递归版本如下:

/*
 * 后序遍历的非递归实现,由于其根节点最后打印,因此这里需要借助两个栈来完成,
 * 因为需要借助一个辅助栈来保存其父节点,而另一个栈则用来保存我们的结果集。
 * 注意压栈顺序,本来应该先压右孩子,再压左孩子。但是使用另一个结果栈
 * 来存储结果集,辅助栈中的元素最终是出栈并压入结果栈的,因此,程序中
 * 应该先压入左孩子,再压入右孩子。
 * 然后每次循环将栈顶元素出栈并压入结果栈中。
 * 最后,结果栈中所存储的就是我们所需的后序遍历结果集。打印出栈中所有的
 * 元素即可
 */

//后序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>lastOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;//这个作为工作栈
		mystack.push(root);
		while (!mystack.empty())
		{
			TreeNode* top_node = mystack.top();
			myvec.push_back(top_node->val);    //这个入结果数组顺序是反向的
			mystack.pop();

			if (top_node->left != nullptr)//因为入栈和出栈顺序相反
				mystack.push(top_node->left);
			if (top_node->right != nullptr)
				mystack.push(top_node->right);		
		}
		
		//把最终的顺序一反序即可 不用再用临时结果栈了
		reverse(myvec.begin(), myvec.end());
		return myvec;
	}

在这里插入图片描述
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

递归版本的代码如下:

/**══════════════════════════════════╗
*作    者:songjinzhou                                                 ║
*CSND地址:https://blog.csdn.net/weixin_43949535                       ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日12:07:06                                                            
*功能描述:                                                            
*                                                                      
*                                                                      
*═══════════════════════════════════╣
*结束时间:  2019年9月11日14:17:18                                                           
*═══════════════════════════════════╝
//                .-~~~~~~~~~-._       _.-~~~~~~~~~-.
//            __.'              ~.   .~              `.__
//          .'//              西南\./联大               \\`.
//        .'//                     |                     \\`.
//      .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
//    .'//.-"                 `-.  |  .-'                 "-.\\`.
//  .'//______.============-..   \ | /   ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>


using namespace std;

class TreeNode
{
public:
	TreeNode(char C):val(C),left(nullptr),right(nullptr){}
	static void preOrder_Operator(TreeNode* this_root, vector<char>& vec)//前序遍历 递归实现
	{
		if (this_root != nullptr)
		{
			vec.push_back(this_root->val);
			preOrder_Operator(this_root->left, vec);
			preOrder_Operator(this_root->right, vec);
		}
	}
	//前序遍历 把顺序保存在一个数组中 递归实现
	vector<char> preOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		preOrder_Operator(root, myvec);
		return myvec;
	}

	//中序遍历 递归实现
	static void inOrder_Operator(TreeNode* this_root, vector<char>& vec)
	{
		if (this_root != nullptr)
		{
			inOrder_Operator(this_root->left, vec);
			vec.push_back(this_root->val);
			inOrder_Operator(this_root->right, vec);
		}
	}
	//中序遍历 把顺序保存在一个数组中 递归实现
	vector<char>inOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		inOrder_Operator(root, myvec);
		return myvec;
	}

	//后序遍历 递归实现
	static void lastOrder_Operator(TreeNode* this_root, vector<char>& vec)
	{
		if (this_root != nullptr)
		{
			lastOrder_Operator(this_root->left, vec);		
			lastOrder_Operator(this_root->right, vec);
			vec.push_back(this_root->val);
		}
	}
	//后序遍历 把顺序保存在一个数组中 递归实现
	vector<char>lastOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		lastOrder_Operator(root, myvec);
		return myvec;
	}

	char val;
	TreeNode* left;
	TreeNode* right;
};

int main()
{
	TreeNode tree(0);
	char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
	TreeNode* root = nullptr;
	TreeNode* pArray[9] = { nullptr };

	int i = 0;
	for (char val : Carray)
	{
		pArray[i++] = new TreeNode(val);
	}
	pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
	pArray[1]->left = pArray[3];
	pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
	pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
	pArray[4]->right = pArray[8];
	root = pArray[0];

	vector<char>myvec_pre = tree.preOrder(root);
	cout << "二叉树的先序遍历序列递归版本:";
	for (char val : myvec_pre)
	{
		cout << val << " ";
	}
	cout << endl;
	vector<char>myvec_in = tree.inOrder(root);
	cout << "二叉树的中序遍历序列递归版本:";
	for (char val : myvec_in)
	{
		cout << val << " ";
	}
	cout << endl;
	vector<char>myvec_last = tree.lastOrder(root);
	cout << "二叉树的后序遍历序列递归版本:";
	for (char val : myvec_last)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}
/**
*备用注释:
*
*
*
*/

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

非递归版本的代码如下:

/**══════════════════════════════════╗
*作    者:songjinzhou                                                 ║
*CSND地址:https://blog.csdn.net/weixin_43949535                       ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日14:20:09                                                          
*功能描述:                                                            
*                                                                      
*                                                                      
*═══════════════════════════════════╣
*结束时间: 2019年9月11日15:21:57                                                            
*═══════════════════════════════════╝
//                .-~~~~~~~~~-._       _.-~~~~~~~~~-.
//            __.'              ~.   .~              `.__
//          .'//              西南\./联大               \\`.
//        .'//                     |                     \\`.
//      .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
//    .'//.-"                 `-.  |  .-'                 "-.\\`.
//  .'//______.============-..   \ | /   ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

class TreeNode
{
public:
	TreeNode(char C) :val(C), left(nullptr), right(nullptr) {}

	//前序遍历 把顺序保存在一个数组中 非递归实现
	vector<char> preOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;
		mystack.push(root);
		while (!mystack.empty())
		{
			TreeNode* top_node = mystack.top();
			myvec.push_back(top_node->val);
			mystack.pop();

			//出栈和入栈的顺序是相反的
			if (top_node->right != nullptr)
			{
				mystack.push(top_node->right);
			}
			if (top_node->left != nullptr)
			{
				mystack.push(top_node->left);
			}
		}
		return myvec;
	}


	//中序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>inOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;
		TreeNode* top_node = root;

		while (!mystack.empty() || top_node!=nullptr)
		{
			if (top_node!= nullptr)//左孩子存在 一直走
			{
				mystack.push(top_node);
				top_node = top_node->left;
			}
			else
			{
				top_node = mystack.top();
				myvec.push_back(top_node->val);
				mystack.pop();

				top_node = top_node->right;
			}
		}
		return myvec;
	}

	
	//后序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>lastOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		stack<TreeNode*>mystack;//这个作为工作栈
		mystack.push(root);
		while (!mystack.empty())
		{
			TreeNode* top_node = mystack.top();
			myvec.push_back(top_node->val);    //这个入结果数组顺序是反向的
			mystack.pop();

			if (top_node->left != nullptr)
				mystack.push(top_node->left);
			if (top_node->right != nullptr)//因为入栈和出栈顺序相反
				mystack.push(top_node->right);		
		}
		//把最终的顺序一反序即可 不用再用临时结果栈了
		reverse(myvec.begin(), myvec.end());
		return myvec;
	}

	char val;
	TreeNode* left;
	TreeNode* right;
};

int main()
{
	TreeNode tree(0);
	char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
	TreeNode* root = nullptr;
	TreeNode* pArray[9] = { nullptr };

	int i = 0;
	for (char val : Carray)
	{
		pArray[i++] = new TreeNode(val);
	}
	pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
	pArray[1]->left = pArray[3];
	pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
	pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
	pArray[4]->right = pArray[8];
	root = pArray[0];

	vector<char>myvec_pre = tree.preOrder(root);
	cout << "二叉树的先序遍历序列非递归版本:";
	for (char val : myvec_pre)
	{
		cout << val << " ";
	}
	cout << endl;
	vector<char>myvec_in = tree.inOrder(root);
	cout << "二叉树的中序遍历序列非递归版本:";
	for (char val : myvec_in)
	{
		cout << val << " ";
	}
	cout << endl;
	vector<char>myvec_last = tree.lastOrder(root);
	cout << "二叉树的后序遍历序列非递归版本:";
	for (char val : myvec_last)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}
/**
*备用注释:
*
*
*
*/

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

层次遍历

其定义:若二叉树为空,则空操作返回;不为空则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。
在这里插入图片描述
因此上面这棵二叉树的 层次遍历,次序为:ABCDEFGHI
遍历步骤如下

  1. 二叉树不空,访问第1层 A入队
  2. (队头A出队)访问 即A。A的左孩子存在 右孩子存在 (B、C入队)
  3. (队头B出队)访问 即AB。B的左孩子存在 右孩子不存在 (D入队)
  4. (队头C出队)访问 即ABC。C的左孩子存在 右孩子存在 (E、F入队)
  5. (队头D出队)访问 即ABCD。D的左孩子存在 右孩子存在 (G、H入队)
  6. (队头E出队)访问 即ABCDE。E的左孩子不存在 右孩子存在 (I入队)
  7. (队头F出队)访问 即ABCDEF。F的左孩子不存在 右孩子不存在
  8. (队头G出队)访问 即ABCDEFG。G的左孩子不存在 右孩子不存在
  9. (队头H出队)访问 即ABCDEFGH。H的左孩子不存在 右孩子不存在
  10. (队头I出队)访问 即ABCDEFGHI。I的左孩子不存在 右孩子不存在

代码如下:

4.1 层次遍历的递归版本如下:

/*
 * 层序遍历不同于上面的前序、中序、后序遍历的DFS,而它是一种典型的BFS
 * 那么对于层序遍历的递归实现,就必须要获取到该树的层数,才能对递归进行一个有效的控制
 * 整体思路就是:向递归函数levelOrder_Operator ,循环传入层数(0-n)
 * 在递归函数中,层数为零,我们直接打印其值即可,若层数不为零,我们就递归
 * 地继续向下遍历。
 * 
 * 那么如何向下继续遍历?我们每次递归遍历就将层数减一即可,那么比如我们遍历第3层
 * 元素,那么传入的参数为3,我们递归调用函数,不断的将参数减一,当减到0时便是
 * 已经遍历到第三层了,参数减到0,递归结束条件满足,我们直接打印其值即可。
 */

//计算一棵二叉树的层次
	int getLevel(TreeNode* root)
	{
		if (root == nullptr)
			return 0;
		else
		{
			return 1 + max(getLevel(root->left), getLevel(root->right));
		}
	}
	void levelOrder_Operator(TreeNode* this_node, int level, vector<char>& myvec)
	{
		if (this_node == nullptr)
			return;
		if (level == 0)//达到该层
		{
			myvec.push_back(this_node->val);
		}
		else
		{
			//既然没有达到该层,则指针向下走
			levelOrder_Operator(this_node->left, level - 1, myvec);
			levelOrder_Operator(this_node->right, level - 1, myvec);
		}
	}
	//层序遍历 把顺序保存在一个数组中 递归实现
	vector<char>levelOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;
		int level = getLevel(root);

		for (int i = 0; i < level; ++i)
		{
			levelOrder_Operator(root, i, myvec);
		}
		
		return myvec;
	}

测试如下:
在这里插入图片描述
代码如下:

4.2 层次遍历的非递归版本如下:

/*
 * 层序遍历的非递归实现,正常思路我们先遍历左子树,再遍历右子树,由于是
 * 层序遍历,从上到下,从左到右,那么从左到右刚好满足队列的性质,先入先出
 * 那么我们需要借助一个队列来保存我们遍历到的元素。
 * 第一步:压入根节点。
 * 第二步:每次遍历我们拿到队列的首元素,然后遍历其左孩子,并入队;然后遍历其右孩子
 * 并入队
 * 第三步:然后将队首元素打印并出队,继续迭代
 *        直到队列为空。
*/

//层序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>nonlevelOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		queue<TreeNode*>myque;
		myque.push(root);
		while (!myque.empty())
		{
			TreeNode* head_node = myque.front();
			myvec.push_back(head_node->val);
			myque.pop();

			if (head_node->left != nullptr)
				myque.push(head_node->left);
			if (head_node->right != nullptr)
				myque.push(head_node->right);
		}
		return myvec;
	}

测试如下:
在这里插入图片描述
层序遍历的全部源代码如下:

/**══════════════════════════════════╗
*作    者:songjinzhou                                                 ║
*CSND地址:https://blog.csdn.net/weixin_43949535                       ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日15:29:39                                                
*功能描述:                                                            
*                                                                      
*                                                                      
*═══════════════════════════════════╣
*结束时间: 2019年9月11日16:21:58                                                      
*═══════════════════════════════════╝
//                .-~~~~~~~~~-._       _.-~~~~~~~~~-.
//            __.'              ~.   .~              `.__
//          .'//              西南\./联大               \\`.
//        .'//                     |                     \\`.
//      .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
//    .'//.-"                 `-.  |  .-'                 "-.\\`.
//  .'//______.============-..   \ | /   ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>
#include <stack>
#include <queue>

using namespace std;

class TreeNode
{
public:
	TreeNode(char C) :val(C), left(nullptr), right(nullptr) {}

	//层序遍历 把顺序保存在一个数组中 非递归实现
	vector<char>nonlevelOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;

		queue<TreeNode*>myque;
		myque.push(root);
		while (!myque.empty())
		{
			TreeNode* head_node = myque.front();
			myvec.push_back(head_node->val);
			myque.pop();

			if (head_node->left != nullptr)
				myque.push(head_node->left);
			if (head_node->right != nullptr)
				myque.push(head_node->right);
		}
		return myvec;
	}
	//计算一棵二叉树的层次
	int getLevel(TreeNode* root)
	{
		if (root == nullptr)
			return 0;
		else
		{
			return 1 + max(getLevel(root->left), getLevel(root->right));
		}
	}
	void levelOrder_Operator(TreeNode* this_node, int level, vector<char>& myvec)
	{
		if (this_node == nullptr)
			return;
		if (level == 0)//达到该层
		{
			myvec.push_back(this_node->val);
		}
		else
		{
			//既然没有达到该层,则指针向下走
			levelOrder_Operator(this_node->left, level - 1, myvec);
			levelOrder_Operator(this_node->right, level - 1, myvec);
		}
	}
	//层序遍历 把顺序保存在一个数组中 递归实现
	vector<char>levelOrder(TreeNode* root)
	{
		vector<char>myvec;
		if (root == nullptr)
			return myvec;
		int level = getLevel(root);

		for (int i = 0; i < level; ++i)
		{
			levelOrder_Operator(root, i, myvec);
		}
		
		return myvec;
	}

	char val;
	TreeNode* left;
	TreeNode* right;
};

int main()
{
	TreeNode tree(0);
	char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
	TreeNode* root = nullptr;
	TreeNode* pArray[9] = { nullptr };

	int i = 0;
	for (char val : Carray)
	{
		pArray[i++] = new TreeNode(val);
	}
	pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
	pArray[1]->left = pArray[3];
	pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
	pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
	pArray[4]->right = pArray[8];
	root = pArray[0];

	vector<char>myvec_pre = tree.nonlevelOrder(root);
	cout << "二叉树的层次遍历序列非递归版本:";
	for (char val : myvec_pre)
	{
		cout << val << " ";
	}
	cout << endl;
	vector<char>myvec_in = tree.levelOrder(root);
	cout << "二叉树的层次遍历序列的递归版本:";
	for (char val : myvec_in)
	{
		cout << val << " ";
	}
	cout << endl;

	return 0;
}
/**
*备用注释:
*
*
*
*/

猜你喜欢

转载自blog.csdn.net/weixin_43949535/article/details/100726391