从零开始的数据结构学习日记(十二)——1.12二叉树的遍历

1.1深度优先遍历

1.递归遍历

LDR分别代表左子树、根结点、右子树。
1.先序遍历DLR
若二叉树为空,则结束遍历;否则访问根结点,先序遍历左子树,先序遍历右子树。算法如下:

void preorder(bitree *p)
{
	if(p!=NULL)
	{
		printf("%c",p->data);
		preorder(p->lchild);
		preorder(p->rchild);
	}
}

2.中序遍历LDR
若二叉树为空,则结束遍历;否则中序遍历左子树,访问根结点,中序遍历右子树。算法如下:

voidinorder(bitree*p)
{
	if(p!=NULL)
	{
		inorder(p->lchild);
		printf("%c",p->data);
		inorder(p->rchild);
	}
}

3.后序遍历LRD
若二叉树为空,则结束遍历;否则后序遍历左子树,后序遍历右子树,访问根结点。

void postorder(bitree*p)
{
	if(p!=NULL)
	{
		postorder(p->lchild);
		postorder(p->rchild);
		printf("%c",p->data);
	}
}

2.非递归遍历

以中序遍历为例,在遍历左子树之前,先把根结点入栈;当左子树遍历结束后,从栈中弹出访问,再遍历右子树。
具体如下:
1.当指针p所指的结点非空时,将该结点的存储地址进栈,然后再将p指向该结点的左孩子。
2.当指针p所指的结点为空时,从栈顶退出栈顶元素送给p,并访问该结点,然后再将p指向右孩子结点。
3.反复直到p为空且栈顶指针top==-1为止。

void ninorder(bitree*T)
{
	SqStack*S;
	bitree*p=T;
	InitStack(S);
	while(p!=NULL||!Empty(S))
	{
		if(p!=NULL)
		{
			Push(S,p);
			p=p->lchild;
		}
		else
		{
			Pop(S,p);
			printf("%c",p->data);
			p=p->rchild;
		}
	}
}

1.2广度优先遍历

指按层从上到下、从左到右访问每个结点。主要思路为:
(1) 树的根结点入队

(2)判断队列是否为空,不为空,则将一个结点出队,并输出出队树结点的值

(3)出队树结点的左子树进入队列

(4)出队树结点的右子树进入队列

(5)循环回到(2)

void layer(BiTree*T)
{
	bitree*p;
	bitree *Q[maxsize];
	SqQueue *Q;
	InitQueue(Q);
	if(T!=NULL)
	{
		Q->rear=(Q->rear+1)%maxsize;//移动循环队列尾指针
		Q->data[Q->rear]=T;//入队
		while(Q->front!=Q->rear)//判断队列是否为空
		{
				Q->front=(Q->front+1)%maxsize;//修改队头指针
				p=Q->data[Q->front];//出队
				printf("%c",p->data);
				if(p->lchild!=NULL)
				{
					Q->rear=(Q->rear+1)%maxsize;
					Q->data[Q->rear]=p->lchilde;
				}
				if(p->rchild!=NULL)
				{
					Q->rear=(Q->rear+1)%maxsize;
					Q->data[Q->rear]=p->rchild;
				}
		}
	}
}

你可能感兴趣的:(二叉树,数据结构,算法,队列,指针)