二叉树的【先序遍历】【中序遍历】【后序遍历】【层序遍历】【递归】【非递归】

目录

 

1 先序遍历

2 中序遍历

3 后序遍历

 4 层序遍历

测试代码:


帮助理解:浙江大学数据结构:https://www.bilibili.com/video/BV1H4411N7oD?p=33

1 先序遍历

//前序遍历
void ProOrderTraverse(BiTree tree)
{
	if (tree == NULL)
		return;
	cout << tree->data << " ";
	ProOrderTraverse(tree->lchild);
	ProOrderTraverse(tree->rchild);
}
//非递归前序遍历
void ProOrder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	BiTree p = pRoot;
	stack<BiTree>s;

	while (p != NULL || !s.empty())
	{
		while (p != NULL)
		{
			s.push(p);
			cout << p->data << " ";		//第一次遇见的时候输出
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			s.pop();
			p = p->rchild;
		}
	}
}

2 中序遍历

//中序遍历
void midOrderTraverse(BiTree tree)
{
	if (tree == NULL)
		return;
	midOrderTraverse(tree->lchild);
	cout << tree->data << " ";
	midOrderTraverse(tree->rchild);
}

//非递归中序遍历
void midOrder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	BiTree p = pRoot;
	stack<BiTree>s;
	while (p != NULL || !s.empty())
	{
		while (p!=NULL)
		{
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			cout << p->data << " ";		//第二次遇见的时候输出
			s.pop();
			p = p->rchild;
		}
	}
}

3 后序遍历

3.1 对于后序遍历的非递归遍历,可以将先序遍历的左右顺序颠倒,逆序输出结果。(喜欢用这一种)

根→左→右 ——(颠倒左右顺序)——根→右→左——(逆序输出)——左→右→根

3.2 对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。
 

//后序遍历
void postOrderTraverse(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	postOrderTraverse(pRoot->lchild);
	postOrderTraverse(pRoot->rchild);
	cout << pRoot->data<<" ";
}
//后序遍历非递归

void PostOrderNoRecursion(BiTree pRoot){
	if (pRoot == NULL){
        cout << "Root is NULL!" << endl;
        return;
    }
	stack<BiTree> s1; //辅助栈 
	stack<BiTree> s2; //逆序记录遍历结果 
    
    BiTree p = pRoot;
    
    while(p || !s1.empty()){
    	if(p){
    		s2.push(p);//根节点先压栈
    		s1.push(p);
    		p = p->rchild;//找右儿子
		}
		else{
			p = s1.top();
			s1.pop();
			p = p->lchild;//找左儿子
		}
    	
    }
    //此时倒序输出stack2即为后序遍历的序列
    while(!s2.empty()){
    	p = s2.top();
    	s2.pop();
    	cout << p->data << " ";
    }
    cout<<endl;
}

 4 层序遍历

定义一个队列,将根节点入队。

取队首元素出队,将他的左右儿子入队。

知道队空,遍历结束。

//层序遍历
 void printTree(BiTree pRoot)
{
    queue<BiTree> q; //定义一个队列,数据类型是二叉树指针,不要仅是int!!不然无法遍历
    q.push(pRoot);
    while (!q.empty())
    {
        BiTree front = q.front();
        cout<<front->data<<" ";
        q.pop();
        if(front->lchild != nullptr)
        	q.push(front->lchild);
        if (front->rchild != nullptr)//判断最前面的右节点是否为空,不是则放入队列
            q.push(front->rchild);	
       
    }
}

深度优先dfs——先序遍历

广度优先bfs——层次遍历

测试代码:

#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue> 
using namespace std;
#define len 15						//定义一个长度

typedef int ElemType;

typedef struct BiTNode
{
	ElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

typedef struct Node
{
	BiTree btnode;
	bool isfirst;
}Node,*node;

//向下遍历,找到节点s应该插入的位置,节点有重复时,忽略这个节点
void SearchTreeNode(BiTree &root, BiTree &s)	//注意:使用引用传递
{
	if (root == NULL)
		return;
	if (s->data > root->data)
	{
		if (root->rchild == NULL)
		{
			root->rchild = s;
			return;
		}
		SearchTreeNode(root->rchild, s);//s值大于根节点值,未到达叶子节点,继续向右孩子遍历
	}

	else if (s->data < root->data)
	{
		if (root->lchild == NULL)
		{
			root->lchild = s;
			return;
		}
		SearchTreeNode(root->lchild, s);//s值小于根节点值,未到达叶子节点,继续向左孩子遍历
	}
}

//插入一个节点,树为空,插入节点即为根节点,否则找合适的位置插入
void InsertNode(BiTree &tree, BiTree &s)		//注意:使用引用传递
{
	if (tree == NULL)
		tree = s;
	else
		SearchTreeNode(tree, s);
}

//二叉排序树创建,每次增加一个结点,插到现有的二叉树上去
void CreateOrderBinaryTree(BiTree &tree, int *a)
{
	for (int i = 0; i < len; i++)
	{
		BiTree s = (BiTree)malloc(sizeof(BiTNode));
		s->data = a[i];
		s->lchild = NULL;
		s->rchild = NULL;
		InsertNode(tree, s);
	}
}
//前序遍历
void ProOrderTraverse(BiTree tree)
{
	if (tree == NULL)
		return;
	cout << tree->data << " ";
	ProOrderTraverse(tree->lchild);
	ProOrderTraverse(tree->rchild);
}
//非递归前序遍历
void ProOrder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	BiTree p = pRoot;
	stack<BiTree>s;

	while (p != NULL || !s.empty())
	{
		while (p != NULL)
		{
			s.push(p);
			cout << p->data << " ";		//第一次遇见的时候输出
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			s.pop();
			p = p->rchild;
		}
	}
}

//中序遍历
void midOrderTraverse(BiTree tree)
{
	if (tree == NULL)
		return;
	midOrderTraverse(tree->lchild);
	cout << tree->data << " ";
	midOrderTraverse(tree->rchild);
}

//非递归中序遍历
void midOrder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	BiTree p = pRoot;
	stack<BiTree>s;
	while (p != NULL || !s.empty())
	{
		while (p!=NULL)
		{
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty())
		{
			p = s.top();
			cout << p->data << " ";		//第二次遇见的时候输出
			s.pop();
			p = p->rchild;
		}
	}
}

//后序遍历
void postOrderTraverse(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	postOrderTraverse(pRoot->lchild);
	postOrderTraverse(pRoot->rchild);
	cout << pRoot->data<<" ";
}

//非递归实现后续遍历
void postOrder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	stack<node>s;
	BiTree p = pRoot;
	node tmp;
	while (p!=NULL || !s.empty())
	{
		while (p != NULL)		//沿左子树一直往下搜索,直至出现没有左子树的结点
		{
			node btn = (node)malloc(sizeof(Node));
			btn->btnode = p;
			btn->isfirst = true;
			s.push(btn);
			p = p->lchild;
		}
		if (!s.empty())
		{
			tmp = s.top();
			s.pop();
			if (tmp->isfirst == true)			//第一次出现在栈顶
			{
				tmp->isfirst = false;
				s.push(tmp);
				p = tmp->btnode->rchild;
			}
			else						//第二次出现在栈顶
			{
				cout << tmp->btnode->data<<" ";
				p = NULL;
			}
		}
	}
}
void PostOrderNoRecursion(BiTree pRoot){
	if (pRoot == NULL){
        cout << "Root is NULL!" << endl;
        return;
    }
	stack<BiTree> s1; //辅助栈 
	stack<BiTree> s2; //逆序记录遍历结果 
    
    BiTree p = pRoot;
    
    while(p || !s1.empty()){
    	if(p){
    		s2.push(p);
    		s1.push(p);
    		p = p->rchild;
		}
		else{
			p = s1.top();
			s1.pop();
			p = p->lchild;
		}
    	
    }
    //此时倒序输出stack2即为后序遍历的序列
    while(!s2.empty()){
    	p = s2.top();
    	s2.pop();
    	cout << p->data << " ";
    }
    cout<<endl;
}
//非递归实现后续遍历
void postorder(BiTree pRoot)
{
	if (pRoot == NULL)
		return;
	stack<BiTree>s;
	BiTree cur = pRoot, pre = NULL;
	s.push(pRoot);
	while (!s.empty())
	{
		cur = s.top();
		if ((cur->lchild == NULL&&cur->rchild == NULL) ||
			((pre == cur->lchild || pre == cur->rchild) && pre != NULL))
		{
			cout << cur->data << " ";
			s.pop();
			pre = cur;
		}
		else
		{
			if (cur->rchild != NULL)
				s.push(cur->rchild);
			if (cur->lchild != NULL)
				s.push(cur->lchild);
		}
	}
}

//层序遍历
 void printTree(BiTree pRoot)
{
    queue<BiTree> q; //定义一个队列,数据类型是二叉树指针,不要仅是int!!不然无法遍历
    q.push(pRoot);
    while (!q.empty())
    {
        BiTree front = q.front();
        cout<<front->data<<" ";
        q.pop();
        if(front->lchild != nullptr)
        	q.push(front->lchild);
        if (front->rchild != nullptr)//判断最前面的右节点是否为空,不是则放入队列
            q.push(front->rchild);	
       
    }
}


int main()
{
	int a[len] = { 62, 88, 58, 47, 35, 73, 51, 99, 37, 93, 23, 27, 45, 21, 12 };
	//int a[] = {1,2,3,4,5};

	BiTree tree = NULL;
	//创建一个二叉树,并中序遍历
	CreateOrderBinaryTree(tree, a);

	cout << "前序遍历" << endl;
	ProOrderTraverse(tree);
	cout << endl;
	ProOrder(tree);
	cout << endl<<endl;

	cout << "中序遍历" << endl;
	midOrderTraverse(tree);
	cout << endl;
	midOrder(tree);
	cout << endl<<endl;

	cout << "后序遍历" << endl;
	postOrderTraverse(tree);
	cout << endl;
	postOrder(tree);
	cout << endl;
	postorder(tree);
	cout << endl<<endl;

	cout << "后序遍历2" << endl;
	PostOrderNoRecursion(tree);
	cout << endl;
	
	cout << "层序遍历" << endl;
	printTree(tree);
	cout << endl;
	
	return 0;
}

测试用例:

参考:https://blog.csdn.net/happyjacob/article/details/83116702

参考:https://blog.csdn.net/z_ryan/article/details/80854233

参考:https://blog.csdn.net/m0_37946085/article/details/89468313?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-37&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-37

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章