浅析二叉树的层序建树及其广度优先遍历、深度优先遍历算法(附图易理解)

110 阅读3分钟

一、代码目的

使用C++语言,从零开始按层序构建二叉树,并给出广度优先遍历算法和深度优先遍历算法。

二、核心思路

请读着按照板块S1、S2、S3、S4的顺序阅读

1.jpg

2.jpg

构建二叉数和遍历虽较为复杂,但有了以上的思路,写出代码也是很轻松的事情。

三、代码实现

#include <iostream>
#include <queue>
using namespace std;
 
struct treenode{  //树节点的结构体定义
	char data;  //数据域
	treenode *left;  //左孩子指针
	treenode *right;  //右孩子指针
};
 
struct treequeue{  //辅助队列节点的结构体定义
	treenode *parent;  //指向树结点的指针
	bool isleft;  //指明当前节点是否已有左孩子
};
 
void treeinsert(treenode* &root,queue<treequeue*> &pos,char data){ //树节点插入函数
	if(data!='#'){  //插入的节点不为空
		treenode *tnew=new treenode;  //申请一个新的树结点
		tnew->data=data;  //输入树结点的数据
		treequeue *qnew=new treequeue;  //申请一个新的辅助队列节点
		qnew->parent=tnew; //新的队列节点指向新的树结点
		qnew->isleft=false;  //指明新的树节点没有左孩子
		pos.push(qnew); //新的队列结点入队
		if(root==NULL){  //判断树的根节点是否为空
			root=tnew;  //若为空,则让新的树结点为根,并将根指针指向新节点
			tnew->left=NULL;  //防止脏数据,左右孩子置空
			tnew->right=NULL;
		}else{
			treequeue* cur=pos.front();  //根非空,获取当前队头结点的指针
			if(cur->isleft==NULL){  //若左孩子为空,则插入在左孩子的位置
				cur->parent->left=tnew;
				cur->isleft=true;
				tnew->left=NULL;
				tnew->right=NULL;
			}else{
				cur->parent->right=tnew; //若右孩子为空,则插入右孩子的位置
				tnew->left=NULL;
				tnew->right=NULL;
				pos.pop();  //队头元素的右孩子已访问,队头元素出队
				delete cur;  //释放指向队头元素的指针
			}
		}
	}else{  //插入的节点为空节点
		if(root!=NULL){  //插入的新节点不为根节点
			treequeue* cur=pos.front();  //获取当前队头结点的指针
			if(cur->isleft==false){  //若左孩子为空,则插入在左孩子的位置
				cur->parent->left=NULL;
				cur->isleft=true;
			}else{
				cur->parent->right=NULL;  //若右孩子为空,则插入在右孩子的位置
				pos.pop();  //队头元素出队
				delete cur;  //释放指针
			}
		}
	}
 
}
 
void BFS(treenode* root){  //广度优先遍历算法
	queue<treenode*> pos;
	pos.push(root);  //根节点入队
	while(pos.empty()==false){  //重复此算法直至所有节点入队被访问后出队
		treenode* cur=pos.front();
		pos.pop();  //队头元素出队
		printf("%c",cur->data);  //访问队头元素
		if(cur->left!=NULL){  //左孩子非空,入队
			pos.push(cur->left);
		}
		if(cur->right!=NULL){  //右孩子非空,入队
			pos.push(cur->right);
		}
	}
	printf("\n");
}
 
void DFS(treenode *root){  //深度优先遍历算法(中序遍历算法,若要实现先序、后序可以改变访问节点的语句顺序)
	if(root==NULL){  //空树则返回
		return;
	}else{
		printf("%c",root->data); //访问当前节点
		DFS(root->left);  //递归访问左孩子
		DFS(root->right); //递归访问右孩子
	}
}
 
int main(){
	treenode* root=NULL; //二叉树的根先置空
	char data;
	queue<treequeue*> pos;  //申请一个元素为指针的队列
	while(1){
		scanf("%c",&data);  //循环读入节点的数据
		if(data=='\n'){
			break;
		}
	treeinsert(root,pos,data);  //“插入”操作
	}
	
	BFS(root);  //广度优先遍历算法
	DFS(root);  //深度优先遍历算法(中序序列)
	printf("\n");
	return 0;
}

四、实现效果

以输入A、B、C、D、#、E、#为例(层序建树,“#”为空节点,BFS和DFS并不会将其打印出来)

其对应的二叉树如下图:

3.jpg

执行程序后,上述二叉树的BFS和DFS结果分别如下:

image.png