关闭

二叉树的遍历

130人阅读 评论(0) 收藏 举报
分类:

最近在面试中经常被问到二叉树的相关问题,很多涉及到二叉树的问题,一个基础的解法就是遍历,所以这里简单总结一下。

本文介绍二叉树的几种遍历方式,并且用C++语言实现了一遍。其实只要稍微总结一下就可以发现,树或者图的遍历一般有两种方式,一种是用递归的方式来做,这种方法代码简洁,注意判断好边界条件就好。另外一个思路就是利用栈或者队列,这种方式写起来比较复杂,好处是效率比较高。

下面分别介绍一下:

广度优先遍历

深度优先遍历:先序遍历、中序遍历、后序遍历


1. 广度优先遍历

广度优先遍历需要用到队列,每次访问一个节点的时候,我们把它的左节点和右节点(不为空)分别放入队列。由于队列先进先出,根节点总是先于它的子节点被访问,这样就保证了一层一层的遍历节点。

void width_first_search(Tree* root)
{
	queue<Tree*> q;
	Tree* node;
	q.push(root);
	while (!q.empty()) {
		node = q.front();
		cout << node->value << " ";
		q.pop();
		if(node->left != NULL)
			q.push(node->left);
		if(node->right != NULL)
			q.push(node->right);
	}
}

2.深度优先遍历

深度优先遍历需要用到栈,每次访问一个节点,我们把它的右节点和左节点(非空)分别放入栈。由于栈是后进先出,这样就保证了根节点->左节点->右节点的遍历顺序。

下面代码里面的深度优先遍历其实就是先序遍历。

void depth_first_search(Tree *root)
{
	stack<Tree *> s;
	s.push(root);
	while (!s.empty())
	{
		root = s.top();
		cout << root->value << " ";
		s.pop();
		if (root->right != NULL)
			s.push(root->right);
		if (root->left != NULL)
			s.push(root->left);
	}
}


对于树的遍历,我们需要重点掌握上面两种遍历方式,涉及到树的题目,先想想能不能通过上面两种遍历方式或是其变形来解决。

比如,我么要查找一条深度为n的路径,这时候我们就可以用到深度优先遍历。


3. 其他遍历和实现方式

深度优先遍历包括先序、中序和后序遍历,它们的实现方式有递归和非递归两种。具体参考下面的代码。

#include <iostream>
#include <stack>
#include <queue>

using namespace std;

struct Tree
{
	int value;
	Tree* left;
	Tree* right;
	Tree() {}
	Tree(int a, Tree* pl, Tree* pr) : value(a), left(pl), right(pr) {}
};

Tree* create_tree()
{
	// 10, 7  21,  38  57  13,  62
	Tree* t_3_0 = new Tree(62, NULL, NULL);
	Tree* t_2_1 = new Tree(57, NULL, NULL);
	Tree* t_2_2 = new Tree(13, NULL, NULL);
	Tree* t_2_0 = new Tree(38, t_3_0, NULL);
	Tree* t_1_0 = new Tree(7, t_2_0, t_2_1);
	Tree* t_1_1 = new Tree(21, t_2_2, NULL);
	Tree* root = new Tree(10, t_1_0, t_1_1);
	return root;
}

void pre_order_search(Tree* root)
{
	stack<Tree*> s;
	Tree* node = root;
	while (node != NULL || !s.empty()) {
		while (node != NULL) {
			cout << node->value << " ";
			s.push(node);
			node = node->left;
		}
		if (!s.empty()) {
			node = s.top();
			s.pop();
			node = node->right;
		}
	}
}

void in_order_search(Tree* root)
{
	stack<Tree*> s;
	Tree* node = root;
	while (node != NULL || !s.empty()) {
		while (node != NULL) {
			s.push(node);
			node = node->left;
		}
		if (!s.empty()) {
			node = s.top();
			cout << node->value << " ";
			s.pop();
			node = node->right;
		}
	}
}
void pre_order_search_recursion(Tree* root)
{
	if (root != NULL)
	{
		cout << root->value << " ";
		pre_order_search_recursion(root->left);
		pre_order_search_recursion(root->right);
	}
}

void in_order_search_recursion(Tree* root)
{
	if (root != NULL)
	{
		in_order_search_recursion(root->left);
		cout << root->value << " ";
		in_order_search_recursion(root->right);
	}
}

void post_order_search_recursion(Tree* root)
{
	if (root != NULL)
	{
		in_order_search_recursion(root->left);
		in_order_search_recursion(root->right);
		cout << root->value << " ";
	}
}

void width_first_search(Tree* root)
{
	queue<Tree*> q;
	Tree* node;
	q.push(root);
	while (!q.empty()) {
		node = q.front();
		cout << node->value << " ";
		q.pop();
		if(node->left != NULL)
			q.push(node->left);
		if(node->right != NULL)
			q.push(node->right);
	}
}

void depth_first_search(Tree *root)
{
	stack<Tree *> s;
	s.push(root);
	while (!s.empty())
	{
		root = s.top();
		cout << root->value << " ";
		s.pop();
		if (root->right != NULL)
			s.push(root->right);
		if (root->left != NULL)
			s.push(root->left);
	}
}

int main()
{
	// create tree
	Tree* root;
	root = create_tree();
	// pre-order
	cout << "Result of pre-order search: ";
	pre_order_search(root);
	cout << endl;
	cout << "Result of pre-order search (recursion): ";
	pre_order_search_recursion(root);
	cout << endl;
	// in-order
	cout << "Result of in-order search: ";
	in_order_search(root);
	cout << endl;
	cout << "Result of in-order search (recursion): ";
	in_order_search_recursion(root);
	cout << endl;
	// post-order search
	cout << "Result of post-order search (recursion): ";
	post_order_search_recursion(root);
	cout << endl;
	// width first search
	cout << "Width first search: ";
	width_first_search(root);
	cout << endl;
	depth_first_search(root);
	cout << endl;
	system("pause");
	return 0;
}



1
0
查看评论

PTA 4-3 二叉树的遍历

//左根右 void InorderTraversal( BinTree BT ) { if(BT) { InorderTraversal(BT->Left); printf(" %c",BT->Data); ...
  • KEYboarderQQ
  • KEYboarderQQ
  • 2016-11-14 22:03
  • 619

【面试题之算法部分】二叉树的遍历

前序遍历 中序遍历 后序遍历
  • YoungLeoo
  • YoungLeoo
  • 2015-08-24 15:45
  • 1462

二叉树遍历解析

1 / \ 2 3 / \ / \ 4 5 6 7 当你拿到一棵二叉树,无论它的形状如何的千奇百怪 我们都可以将它按照如下的方式划分 ...
  • u014805066
  • u014805066
  • 2016-01-30 13:58
  • 434

C语言数据结构——遍历二叉树

1、二叉树的遍历是指从根节点出发,按照某种次序依次访问二叉树中的所有结点,使得每个节点被访问依次且仅被访问一次。2、前序遍历: 规则是若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。 遍历的顺序为:1 2 4...
  • sunshine_rebrith
  • sunshine_rebrith
  • 2017-06-04 10:53
  • 322

快速写出二叉树的遍历顺序

word和ppt下载:快速写出二叉树的遍历顺序即前序遍历的PPT动态演示   先序遍历(或者前序遍历)       根——左——右 中序遍历:        左——根——...
  • pengdonglin137
  • pengdonglin137
  • 2013-02-25 19:35
  • 1079

6-2 二叉树的遍历 (二叉树的四种遍历方法)

6-2 二叉树的遍历(25 分) 本题要求给定二叉树的4种遍历。 函数接口定义: void InorderTraversal( BinTree BT ); void PreorderTraversal( BinTree BT ); void PostorderTraversal( ...
  • LMengi000
  • LMengi000
  • 2017-12-08 17:05
  • 181

二叉树的三种遍历练习题

一 二叉树的基础问题
  • XSF50717
  • XSF50717
  • 2014-10-11 20:10
  • 5769

二叉树的遍历及其应用

#include #include using namespace std; typedef int ElemType; typedef struct TreeNode *BinTree; typedef BinTree Position; typedef struct TreeNode ...
  • guojz049
  • guojz049
  • 2016-06-06 19:51
  • 247

二叉树的遍历有几种方式?

先建立一个二叉树 public class Tree{ public string Value; public Tree Left; public Tree Right; } public static Tree CreatFakeTree(){ Tree tree = new Tre...
  • ax1274669874
  • ax1274669874
  • 2017-04-21 22:28
  • 157

用代码实现二叉树的遍历-Java经典面试题算法部分核心

树的特征: 都有根节点:根节点指的是最上面的一个节点 当孩子节点没有孩子,我们称这样的孩子称为叶子节点 在一棵树中,纵向最长的长度为数的深度 当一棵树每一个节点的孩子不超过2个,我们称这棵树为二叉树 二叉树中,孩子分为左孩子和右孩子 一颗深度为n的二叉树,最多有2^n-1个根节点,最少有...
  • SoWhatWorld
  • SoWhatWorld
  • 2017-08-20 16:04
  • 120
    个人资料
    • 访问:2141次
    • 积分:97
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:3篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论