深度优先与广度优先(二叉树篇)

  1. 我们先定确定需要用到的数据结构,其中有栈,队列,二叉树
//二叉树结构
typedef struct biNode {
	int data;
	struct biNode* lchild;
	struct biNode* rchild;
}biNode,*biTree;
//队列结构,注意队列的data元素是一个指向二叉树节点的指针,即biTree类型的元素
typedef struct bfsQueue {
	biTree data;
	struct bfsQueue* next;
}qnode;

typedef struct bfsList {
	qnode* head;//头节点
	qnode *rear;//尾节点
}list,*qlist;
//栈结构
typedef struct snode {
	biTree data;
	struct snode* next;
}snode;

typedef struct stackNode {
	snode* head;//栈顶节点
}stackNode, * Stack;
  1. 对于二叉树,用先序遍历创建
void preorderInsert(biTree* T) {
	*T = new biNode;
	int data;
	cin >> data;
	if (data!=0) //data为0,表示节点为空
	{
		(*T)->data = data;//先序遍历创建
		preorderInsert(&(*T)->lchild);
		preorderInsert(&(*T)->rchild);
	}
	else {
		*T = NULL;
	}
}

3.先来看广度优先遍历

最开始,我们让一棵二叉树即它的头节点进队列,然后我们从队列中取出一个元素并输出,如果它有左孩子和右孩子,则先让左孩子进队列,再让右孩子进队列。然后我们重复相同的步骤(即从队列取元素,让左孩子右孩子进队列,直到这个队列为空,就完成了广度优先遍历)

//广度优先遍历
void bfs(biTree T) {
	qlist List = new list;
	initQueue(List);//初始化队列
	enter(List, T);//二叉树进队列
	while (List->head) {
		leaveQ(List);//重复相同步骤,直到队列为空
	}
}

void initQueue(qlist Q) {
	Q->head = NULL;
	Q->rear = NULL;
}
void enter(qlist Q,biTree data) {
	qnode* node = new qnode;
	node->data = data;
	node->next = NULL;
	if (Q->head ==NULL)
		Q->head = node;
	if (Q->rear == NULL)
		Q->rear = node;
	else {
		Q->rear->next = node;
		Q->rear = node;
	}
}
void leaveQ(qlist Q) {
	cout << Q->head->data->data << endl;//输出要出队列的元素中的值
	biTree L = Q->head->data->lchild;
	biTree R = Q->head->data->rchild;
	Q->head = Q->head->next;//出队列
	if (Q->head == NULL)
		Q->rear = NULL;
	if (L)//如果左孩子不空,左孩子进队列
		enter(Q, L);
	if (R)//如果右孩子不空,右孩子进队列
		enter(Q, R);
}
  1. 然后是深度优先遍历

和广度优先遍历类似,最开始,我们让一棵二叉树即它的头节点进栈,然后我们从栈中取出一个元素并输出,如果它有左孩子和右孩子,则先让右孩子(注意是先让右孩子,因为栈是先进后出)进栈,再让左孩子进栈。然后我们重复相同的步骤(即从栈取元素,让右孩子左孩子进栈,直到这个栈为空,就完成了深度优先遍历)

//深度优先遍历
void dfs(biTree T) {
	Stack S=new stackNode;
	initStack(S);
	pushStack(S, T);
	while (S->head->next) {
		popStack(S);//重复相同步骤,直到栈为空
	}
}
//初始化栈
void initStack(Stack S) {
	snode* s = new snode;
	S->head = s;
	S->head->next = NULL;
}

进栈
void pushStack(Stack S, biTree data) {
	snode* s = new snode;
	s->data = data;
	s->next = S->head->next;
	S->head->next = s;
}
void popStack(Stack S) {
	cout << S->head->next->data->data << endl;
	biNode *L = S->head->next->data->lchild;
	biNode* R = S->head->next->data->rchild;
	S->head->next = S->head->next->next;
	if (R)
		pushStack(S, R);//右子树不空,右子树进栈
	if (L)
		pushStack(S, L);//左子树不空,左子树进栈
}

5.main函数

int main() {
	biTree T;
	preorderInsert(&T);//先序创建二叉树
	bfs(T);//广度优先遍历
	dfs(T);//深度优先遍历
	return 0;
}

到此,我们已经完成了最简单的二叉树的遍历,在此基础上,我们将考虑图的广度优先与深度优先。不妨先来看看,它与二叉树遍历的不同之处,对于一棵二叉树,每个节点的左孩子右孩子只可能是它自己的左右孩子,所以我们不需要对已经遍历过的节点设置标记,但在图中就不一定,每个节点相邻的节点又可能和别的节点相邻,如果继续按照上述思路,我们就会重复遍历一些节点,所以,我们有必要对已经遍历过的节点设置一个标记,以避免它被重复遍历。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值