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;
}


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























二叉树的遍历

转载出处:http://blog.csdn.net/ns_code/article/details/12977901 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的...

二叉树的递归和非递归的遍历算法

一、二叉树的概念 二叉树:二叉树就是每个结点最多有两个子树的树形存储结构。 满二叉树和完全二叉树:满二叉树一定是完全二叉树,但是反过来就不一定。满二叉树的定义是除了叶子结点,其它结点都有左右了两个孩子...

c++ 二叉树的遍历

  • 2012年05月07日 21:48
  • 2KB
  • 下载

二叉树的层序遍历详细讲解(附完整C++程序)

1 说明   二叉树的层序遍历是面试经常会被考察的知识点,甚至要求当场写出实现过程。笔者先后被腾讯和滴滴面试官问过这个问题,腾讯面试官是让称述整个实现过程,本人自信满满的说出来了,所以也没有对具体实现...

二叉树的非递归遍历 C++

  • 2011年12月08日 20:42
  • 4KB
  • 下载

线索二叉树的原理以及创建和遍历(c++)

这是一篇非常好的关于线索二叉树的文章,内容详细到位,叙述清晰。作者是以为很认真、信息的人,估计花了不少时间和精力,向作者致敬! 引用地址:http://waret.iteye.com/blog/70...
  • wbcg111
  • wbcg111
  • 2016年03月26日 10:31
  • 1173

二叉树的遍历C++实现

  • 2012年05月10日 16:07
  • 35KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ 二叉树的遍历
举报原因:
原因补充:

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