关闭

C++ 二叉树的遍历

标签: 二叉树二叉树的遍历C++数据结构
191人阅读 评论(0) 收藏 举报

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

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

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


二叉树的遍历分为(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;
}


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























0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:289次
    • 积分:43
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档