先来点题外话:遍历就是按照某种顺序进行访问对应的数据元素。二叉树的遍历是为了访问结点,但是该结点仅且被访问一次。用D,L,R分别表示根结点,左孩子,右孩子,所以这可以组成6中遍历方式,但是我们只看L在R的前面被访问的方式。不是说好的题外话吗???
一、二叉树的递归遍历
1.先序遍历(DLR):先访问根,再是左,最后是右
2.中序遍历(LDR):左,根,右
3.后序遍历(LRD):左,右,根
以上不是说的是递归吗?从何而见它体现了递归呢: 详细解释:比如DLR细化是为:D(DLR)L(DLR)R(DLR),这下明白了吧,递归就是这样体现的。sogo
具体实现:
//先序
void PreOrder(BiTree root)
{
if(root == NULL)
return;
cout<<root->data<<" ";
PreOrder(root->lchild);
PreOrder(root->rchild);
}
//中序
void InOrder(BiTree root)
{
if(root == NULL)
return;
InOrder(root->lchild);
cout<<root->data<<" ";
InOrder(root->rchild);
}
//后序
void PostOrder(BiTree root)
{
if(root == NULL)
return;
PostOrder(root->lchild);
PostOrder(root->rchild);
cout<<root->data<<" ";
}
4.层次遍历:就是从根结点开始,一层层的往下遍历,先遇到的结点先访问。(ps:有点感觉跟排队一样,既然这样就可以用队列(queue)来实现啊!yes,非常正确)
实现方法:首先将根结点入队,然后从队首取出一个元素;具体实现过程如下:
void levelOrder(BiTree root)
{
//用一个一维数组实现队列
BiTree queue[100];
int front = -1, rear = 0;//队首,队尾
if(root == NULL)
{
return;
}
//(1)首先将根结点入队
queue[rear] = root;
//当队列为null时,遍历结束
while (front != rear)
{
front++;//从队首取出一个元素,相当于就是将双亲节点顺序出队
int returnValue = queue[front]->data;
//(2)若该元素所指节点的左,右孩子结点非NULL,则将该元素所指结点的左孩子指针和右孩子指针顺序入队
if(queue[front]->lchild != NULL)
{
rear++;
queue[rear] = queue[front]->lchild;//将队首节点的左孩子入队
}
if(queue[front]->rchild != NULL)
{
rear++;
queue[rear] = queue[front]->rchild;
}
}
}
二、二叉树遍历的非递归实现
/*
非递归遍历的思想:(1)首先提出两个概念“深入”和“返回”,它们所代表的意思就是“入栈”和“出栈”;为什么这里用栈来表示,因为它们之间的关系是返回时是返回
刚刚压入栈的元素即栈顶元素。(2)深入是从根结点的左孩子开始,当左孩子为null时,将压入的栈顶元素返回,在深入右孩子。
先序遍历的思想:在深入时遇到结点就访问
中序:在左子树返回是访问节点
*/
//先序遍历非递归
void NRPreOrder(BiTree root)
{
BiTree statck[100];//声明栈
int top = -1;
BiTree temp = root;
if(temp == NULL)
return;
while (!(temp ==NULL && top == -1))
{
while(temp)
{
cout<<temp->data<<" ";
top++;
statck[top] = temp;
temp = temp->lchild;
}
if(top == -1)
return ;
else
{
temp = statck[top];
//中序:在这里访问数据cout<<temp->data<<" ";
top--;
temp = temp->rchild;
}
}
}
三、通过遍历序列恢复二叉树
只能通过先序和中序,其次是中序和后序才能确定一个二叉树;
(1)已知先序序列和中序序列:首先通过先序确定根结点,然后通过中序确定左右子树,再依次确定相应的节点。
(2)已知中序和后序:同理可以通过后序序列的最后一个结点找到根结点,然后通过中序分为左右子树,依次递归,便可以得到唯一的二叉树。
(3)已知先序和后序:这种是不可以的找到唯一的二叉树,因为这种不能唯一确定左右子树。
非递归的二叉树遍历难道只能是通过用栈来实现吗?
no, 常用的不用栈的二叉树非递归遍历方法:
1、采用三叉链表
2、采用逆转链表
3、采用线索二叉树的遍历