1. 程式人生 > >二叉樹的各種遍歷演算法C++實現

二叉樹的各種遍歷演算法C++實現

大概在網上摘抄和總結了二叉樹的幾種遍歷方法,有遞迴和非遞迴的,先貼在這裡,用的時候在來看看。再次謝謝網上的各種資源。謝謝CSDN博主SJF0115,謝謝劍指offer作者何海濤~

#include"stdafx.h"
#include<iostream>  
#include<stack>  
#include<queue>  
using namespace std;

//二叉樹結點  
typedef struct BinaryTreeNode{
	//資料  
	char data;
	//左右孩子指標  
	struct BinaryTreeNode *lchild, *rchild;
}BinaryTreeNode, *BiTree;

//按先序序列建立二叉樹  
int CreateBiTree(BiTree &T){
	char data;
	//按先序次序輸入二叉樹中結點的值(一個字元),‘#’表示空樹  
	scanf_s("%c", &data);
	if (data == '#'){
		T = NULL;
	}
	else{
		T = (BiTree)malloc(sizeof(BinaryTreeNode));
		//生成根結點  
		T->data = data;
		//構造左子樹  
		CreateBiTree(T->lchild);
		//構造右子樹  
		CreateBiTree(T->rchild);
	}
	return 0;
}
//輸出  
void Visit(BiTree T){
	if (T->data != '#'){
		printf("%c ", T->data);
	}
}
//先序遍歷  
void PreOrder(BiTree T)
{
	if (T != NULL){
		//訪問根節點  
		Visit(T);
		//訪問左子結點  
		PreOrder(T->lchild);
		//訪問右子結點  
		PreOrder(T->rchild);
	}
}
//中序遍歷    
void InOrder(BiTree T)
{
	if (T != NULL){
		//訪問左子結點    
		InOrder(T->lchild);
		//訪問根節點    
		Visit(T);
		//訪問右子結點    
		InOrder(T->rchild);
	}
}
//後序遍歷  
void PostOrder(BiTree T)
{
	if (T != NULL){
		//訪問左子結點  
		PostOrder(T->lchild);
		//訪問右子結點  
		PostOrder(T->rchild);
		//訪問根節點  
		Visit(T);
	}
}
/* 先序遍歷(非遞迴)
思路:訪問T->data後,將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應為T,出棧,再先序遍歷T的右子樹。
*/
void PreOrder2(BiTree T)
{
	stack<BiTree> stack;
	//p是遍歷指標  
	BiTree p = T;
	//棧不空或者p不空時迴圈  
	while (p || !stack.empty())
	{
		if (p != NULL)
		{
			//存入棧中  
			stack.push(p);
			//訪問根節點  
			printf("%c ", p->data);
			//遍歷左子樹  
			p = p->lchild;
		}
		else
		{
			//退棧  
			p = stack.top();
			stack.pop();
			//訪問右子樹  
			p = p->rchild;
		}
	}//while  
}
/* 中序遍歷(非遞迴)
思路:T是要遍歷樹的根指標,中序遍歷要求在遍歷完左子樹後,訪問根,再遍歷右子樹。
先將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應為T,出棧,訪問T->data,再中序遍歷T的右子樹。
*/
void InOrder2(BiTree T)
{
	stack<BiTree> stack;
	//p是遍歷指標  
	BiTree p = T;
	//棧不空或者p不空時迴圈  
	while (p || !stack.empty())
	{
		if (p != NULL){
			//存入棧中  
			stack.push(p);
			//遍歷左子樹  
			p = p->lchild;
		}
		else
		{
			//退棧,訪問根節點  
			p = stack.top();
			printf("%c ", p->data);
			stack.pop();
			//訪問右子樹  
			p = p->rchild;
		}
	}//while  
}

//後序遍歷(非遞迴)  
typedef struct BinaryTreeNodePost
{
	BiTree biTree;
	char tag;
}BinaryTreeNodePost, *BiTreePost;

void PostOrder2(BiTree T)
{
	stack<BiTreePost> stack;
	//p是遍歷指標  
	BiTree p = T;
	BiTreePost BT;
	//棧不空或者p不空時迴圈  
	while (p != NULL || !stack.empty())
	{
		//遍歷左子樹  
		while (p != NULL)
		{
			BT = (BiTreePost)malloc(sizeof(BinaryTreeNodePost));
			BT->biTree = p;
			//訪問過左子樹  
			BT->tag = 'L';
			stack.push(BT);
			p = p->lchild;
		}
		//左右子樹訪問完畢訪問根節點  
		while (!stack.empty() && (stack.top())->tag == 'R')
		{
			BT = stack.top();
			//退棧  
			stack.pop();
			BT->biTree;
			printf("%c ", BT->biTree->data);
		}
		//遍歷右子樹  
		if (!stack.empty())
		{
			BT = stack.top();
			//訪問過右子樹  
			BT->tag = 'R';
			p = BT->biTree;
			p = p->rchild;
		}
	}//while  
}
//層次遍歷  
void LevelOrder(BiTree T)
{
	BiTree p = T;
	//佇列  
	queue<BiTree> queue;
	//根節點入隊  
	queue.push(p);
	//佇列不空迴圈  
	while (!queue.empty())
	{
		//對頭元素出隊  
		p = queue.front();
		//訪問p指向的結點  
		printf("%c ", p->data);
		//退出佇列  
		queue.pop();
		//左子樹不空,將左子樹入隊  
		if (p->lchild != NULL)
		{
			queue.push(p->lchild);
		}
		//右子樹不空,將右子樹入隊  
		if (p->rchild != NULL)
		{
			queue.push(p->rchild);
		}
	}
}
/*
	@"之"字形或是"S"型層級遍歷;
	@方法是:注意每一層是怎麼遍歷的,順序如何,只要
	@分析出規律就可以寫出程式碼了
*/
void S_PrintBinaryTree(BinaryTreeNode *pRoot)
{
	//if (pRoot)
		//return;
	std::stack<BinaryTreeNode* >levels[2];	//兩個棧用於兩個入棧順序;
	int current = 0;											//狀態標識,當前狀態;
	int next = 1;												//下一狀態;

	levels[current].push(pRoot);
	while (!levels[0].empty() || !levels[1].empty())
	{
		BinaryTreeNode* pNode = levels[current].top();
		levels[current].pop();

		printf("%c  ", pNode->data);

		if (current == 0)
		{
			if (pNode->rchild != NULL)
				levels[next].push(pNode->rchild);
			if (pNode->lchild != NULL)
				levels[next].push(pNode->lchild);
		}
		else
		{
			if (pNode->lchild != NULL)
				levels[next].push(pNode->lchild);
			if (pNode->rchild != NULL)
				levels[next].push(pNode->rchild);
		}

		if (levels[current].empty())
		{
			printf("\n");
			current = 1 - current;
			next = 1 - next;
		}
	}
}

int main()
{
	BiTree T;
	CreateBiTree(T);
	printf("先序遍歷:\n");
	PreOrder(T);
	printf("\n");
	printf("先序遍歷(非遞迴):\n");
	PreOrder2(T);
	printf("\n");
	printf("中序遍歷:\n");
	InOrder(T);
	printf("\n");
	printf("中序遍歷(非遞迴):\n");
	InOrder2(T);
	printf("\n");
	printf("後序遍歷:\n");
	PostOrder(T);
	printf("\n");
	printf("後序遍歷(非遞迴):\n");
	PostOrder2(T);
	printf("\n");
	printf("層次遍歷:\n");
	LevelOrder(T);
	printf("\n");
	printf("S形層次遍歷:\n");
	S_PrintBinaryTree(T);
	printf("\n");
	return 0;
}

測試用例:


輸入:

ABC##DE#G##F###

輸出:



測試用例:


輸入:

ABC##DE#G##F###

輸出: