C++ 二叉树的遍历

原创 2015年11月19日 18:01:13

最近数据结构讲到了二叉树,为了知识的积累以及分享,此篇博文对二叉树的遍历做一下简单的说明。

(本文的代码很多来源于网络,因为上机课的好多题并不会敲……我会尽量附上原作者)

(由于我学得不是很好,有些地方可能说的不对,请有取舍的看吧(捂脸))


二叉树的遍历分为(1)广度优先遍历,又名逐层遍历

(2)深度优先遍历。深度优先遍历又分为 前序(先序)、中序、后序。


一、广度优先遍历

广度优先遍历需要用到队列,这里我使用了模版

#include <iostream>
#include <string>
using namespace std;

template <typename T>
class queue
{
private:
	int maxsize;
	int front;
	int rear;
	T *arr;
public:
	queue(int size = 10)
	{
		maxsize = size;
		arr = new T[maxsize];	
		front = rear = 0;
	}
	~queue()
	{
		delete[]arr;
	}
	void clear()
	{
		front = rear;
	}
	bool enqueue(T item)
	{
		if ((rear + 1) % maxsize == front)
		{
			cout << "队列已满,溢出" << endl;
			return false;
		}
		arr[rear] = item;
		rear = (rear + 1) % maxsize;
		return true;
	}
	bool dequeue(T item)
	{
		if (front == rear)
		{
			cout << "队列为空" << endl;
			return false;
		}
		item = arr[front];
		front = (front + 1) % maxsize;
		return true;
	}
	T getfront()
	{
		if (front == rear)
		{
			cout << "队列为空" << endl;
			return false;
		}
		return arr[front];
	}
	void pop()
	{
		front++;
	}
	bool isesmpty()
	{
		if (front == rear)
		{
			cout << "队列为空!" << endl;
			return 1;
		}
		else
			return 0;
	}
	bool isfull()
	{
		if ((rear + 1) % maxsize == front)
		{
			cout << "队列已满!" << endl;
			return 1;
		}
		else
			return 0;
	}
	void showque()
	{
		int i = 0;
		if (!isesmpty())
		{
			cout << "打印队列:" << endl;
			for (i = front;i != rear;i++)
			{
				cout << arr[i];
				if ((i + 1) % maxsize == 0)
				{
					i = -1;
				}
			}
			cout << endl;
		}
	}
};<pre name="code" class="cpp">



逐层遍历也就是把二叉树的数据一层一层先放到队列里

从最高层(或最低层)开始,向下(或向上)逐层访问每个结点,在每一层上,自左向右(或自右向左)访问每个结点。



图好像有点大……咳咳


二、深度优先遍历


前序即是按照“根左右”的顺序访问,中序是按照“左根右”的顺序,后序是按照“左右根”的顺序。

而这三种遍历方法又可以有递归与非递归,也就是3*2 = 6种了。

附上这6种的代码以及二叉树的定义。
template <typename T>
class BinaryTreeNode
{
public:
	T data;//存储的数据
	BinaryTreeNode<T> *leftchild;
	BinaryTreeNode<T> *rightchild;
	BinaryTreeNode()
	{
		leftchild = rightchild = NULL;
	}
	BinaryTreeNode(T dat)
	{
		data = dat;
		leftchild = NULL;
		rightchild = NULL;
	}
	BinaryTreeNode(T dat, BinaryTreeNode *left, BinaryTreeNode *right)
	{
		data = dat;
		leftchild = left;
		rightchild = right;
	}
};
template <typename T>
class BinaryTree
{
public:
	BinaryTreeNode<T> *root;
	BinaryTree(BinaryTreeNode<T> *t = NULL)
	{
		root = t;
	}
	bool isempty()
	{
		if (root == NULL)
			return true;
		else
			return false;
	}
	void makeTree(const T dat, BinaryTree<T> left, BinaryTree<T> right)
	{
		root = new BinaryTreeNode<T>(dat, left.root, right.root);
		left.root = right.root = 0;
	}
	void visit(BinaryTreeNode<T> *t)
	{
		cout << t->data << "  ";
	}
	void levelorder()//广度优先遍历二叉树(即逐层遍历二叉树)
	{
		queue<BinaryTreeNode<T> *> nodequeue;
		BinaryTreeNode<T> * pointer = root;
		if (pointer)
			nodequeue.enqueue(pointer);
		while (!nodequeue.isesmpty())
		{
			pointer = nodequeue.getfront();
			visit(pointer);
			nodequeue.pop();
			if (pointer->leftchild)
				nodequeue.enqueue(pointer->leftchild);
			if (pointer->rightchild)
				nodequeue.enqueue(pointer->rightchild);
		}
	}
	void preOrder(BinaryTreeNode<T> * root)//前序递归
	{
		if (root != NULL)
		{
			visit(root);
			preOrder(root->leftchild);
			preOrder(root->rightchild);
		}
	}
	void inOrder(BinaryTreeNode<T> * root)//中序递归
	{
		if (root != NULL)
		{
			inOrder(root->leftchild);
			visit(root);
			inOrder(root->rightchild);
		}
	}
	void postOrder(BinaryTreeNode<T> * root)//后序递归
	{
		if (root != NULL)
		{
			postOrder(root->leftchild);
			postOrder(root->rightchild);
			visit(root);
		}
	}
	void preorderwithoutrecusion(BinaryTreeNode<T> * r)//非递归前序遍历二叉树
	{
		stack<BinaryTreeNode<T> *>nodestack;
		BinaryTreeNode<T> * pointer = r;
		while (!nodestack.empty() || pointer)
		{
			if (pointer)
			{
				visit(pointer);
				if (pointer->rightchild != NULL)
					nodestack.push(pointer->rightchild);
				pointer = pointer->leftchild;
			}
			else
			{
				pointer = nodestack.Top();
				nodestack.pop();
			}
		}
	}
	void inorderwithoutrecusion(BinaryTreeNode<T> * r)//非递归中序遍历二叉树
	{
		stack<BinaryTreeNode<T> *>nodestack;
		BinaryTreeNode<T> * pointer = r;
		while (!nodestack.empty() || pointer)
		{
			if (pointer)
			{
				nodestack.push(pointer);
				pointer = pointer->leftchild;

			}
			else
			{
				pointer = nodestack.Top();
				visit(pointer);
				pointer = pointer->rightchild;
				nodestack.pop();
			}
		}
	}
	void postorderwithoutrecusion(BinaryTreeNode<T> *r)//非递归后序遍历
	{
		stack<BinaryTreeNode<T> *> nodestack;
		BinaryTreeNode<T> *pointer = r;
		BinaryTreeNode<T> *pre = r;
		while (pointer)
		{
			for (;pointer->leftchild != NULL;pointer = pointer->leftchild)
				nodestack.push(pointer);
			while (pointer != NULL && (pointer->rightchild == NULL || pointer->rightchild == pre))
			{
				visit(pointer);
				pre = pointer;
				if (nodestack.empty())
					return;
				pointer = nodestack.Top();
				nodestack.pop();
			}
			nodestack.push(pointer);
			pointer = pointer->rightchild;
		}
	}
};


在深度遍历操作里,需要使用到栈,具体的我说不清,可以到书上查看。其中后序非递归遍历有一些特殊,它需要使用到另外一个指针pre,记录的是指针pointer的之前的位置,作用是看看有没有走重复了,避免重复访问。

下面附上栈的定义。

template <class T>
class stack
{
private:
	int top;
	int maxsize;
	T * sta;
public:
	stack(int size = 10)
	{
		maxsize = size;
		sta = new T[maxsize];
		top = -1;
	}
	~stack()
	{
		delete[]sta;
	}
	void push(T t)
	{
		sta[++top] = t;
	}
	bool empty()
	{
		return top == -1;
	}
	bool full()
	{
		return top == maxsize - 1;
	}
	T Top()
	{
		if (empty())
		{
			cout << "栈为空";
			return 0;
		}
		else
			return sta[top];
	}
	void pop()
	{
		top--;
	}
};


三、主函数


构造好了二叉树,来测试一下。
int main()
{
	BinaryTreeNode<int> a(1), b(2), c(3);
	BinaryTreeNode<int> d(4, &a, &b), e(5, NULL, &c);
	BinaryTreeNode<int> f(6, NULL, &d), g(7, NULL, &e);
	BinaryTreeNode<int> h(8, &f, &g);
	
	BinaryTree<int> tree1(&h);
	tree1.levelorder();
	tree1.preOrder(&h);
	cout << endl;
	tree1.preorderwithoutrecusion(&h);
	cout << endl;
	tree1.inOrder(&h);
	cout << endl;
	tree1.inorderwithoutrecusion(&h);
	cout << endl;
	tree1.postOrder(&h);
	cout << endl;
	tree1.postorderwithoutrecusion(&h);
        return 0;
}


其实我感觉遍历的过程就是在创建二叉树了。
以上。























C++实现二叉树遍历

二叉树节点图: 简述: 分别使用前序遍历(LNR)、中序遍历(NLR)、后续遍历(LRN)实现数据输出 代码及实现: /***********************二叉树遍历...
  • anialy
  • anialy
  • 2012年06月03日 01:57
  • 9844

C++ 二叉树遍历(三种遍历的递归实现)

//二叉树遍历 //作者:nuaazdh //时间:2011年12月1日 #include #include //二叉树结点结构 typedef struct BiTNode{ ...
  • nuaazdh
  • nuaazdh
  • 2011年12月01日 20:14
  • 14274

二叉树遍历c++实现

//自己还真是个菜鸡,大一学了一年c++,现在还在基础的语法上转圈,还没有意识到c++真正的 //的强大之处在于它的多变,封装,等算法告一段落了在考虑是往Java上走还是深造c++ #include ...
  • weixin_36346676
  • weixin_36346676
  • 2016年10月28日 17:30
  • 204

二叉树的三种遍历方法(递归和非递归)(转载)

#include #include //STL #include using namespace std; class Tree { public: Tree *Left; Tre...
  • acdnjjjdjkdckjj
  • acdnjjjdjkdckjj
  • 2011年03月10日 17:24
  • 4183

C++数据结构之 --二叉树简单实现和4种遍历

实验目的:实现简单的二叉树! 头文件: 二叉树.h #ifndef 二叉树_h__ #define 二叉树_h__ #include #include template class Binar...
  • yjhdxflqm
  • yjhdxflqm
  • 2016年02月29日 14:11
  • 938

C++二叉树的遍历总结

1、二叉树的存储结构      二叉树是非线性结构,即每个数据结点至多只有一个前驱,但可以有多个后继。它可采用顺序存储结构和链式存储结构。 (1)顺序存储结构      二叉树的顺序存储,就是用一...
  • JIEJINQUANIL
  • JIEJINQUANIL
  • 2016年08月03日 22:33
  • 749

PTA 4-3 二叉树的遍历

//左根右 void InorderTraversal( BinTree BT ) { if(BT) { InorderTraversal(BT->Left); ...
  • KEYboarderQQ
  • KEYboarderQQ
  • 2016年11月14日 22:03
  • 621

【C++】非递归遍历二叉树

//以下出现的_root标示二叉树的根节点 //非递归先序遍历(根节点->左节点->右节点)思想:即用栈实现 //遍历二叉树的前提条件是:该二叉树不为空。在满足该条件的情况下,进行以下步骤: //1...
  • ZDF0414
  • ZDF0414
  • 2015年11月19日 21:12
  • 475

c语言-数据结构-二叉树-生成、遍历代码

1. 目标 生成一个二叉树,遍历输出二叉树中的内容,并显示所在的层级。 2. 运行示例 输入如下图二叉树(前序遍历方式),不存在的子节点用空格代替。显示如下。 ...
  • kuweicai
  • kuweicai
  • 2016年09月17日 22:47
  • 3105

二叉树建立与遍历递归操作c++实现

#include #include #include using namespace std; //二叉树的数据类型 typedef char BiTType; ...
  • lwy313722871
  • lwy313722871
  • 2013年12月14日 00:50
  • 1584
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ 二叉树的遍历
举报原因:
原因补充:

(最多只允许输入30个字)