一、实验目的
掌握二叉树遍历的基本操作,并对其进行简单应用。
二、实验内容
下图是一颗二叉树,树中的每一个结点都可以有左右两个分支。如果将其视为一张线路图,此时的每一个结点都是岔路口,可以在此选择往左或往右走。当然,如果该结点没有左右岔口,就认为这是一个死胡同。
现在把问题缩小,无论哪一个结点面对的都是往左或往右的选择,整个遍历过程可以简化成为持续的处理选择,直到没路可走。所以,给问题转化为对二叉树的递归遍历,由于递归函数的排列顺序不同,可以分为三种不同的遍历方式:
-
中序遍历
沿着树的左方往下走,直到无法继续前进,记录结点的值,然后退回到父节点,再按照此法往右走,如果右方都无法前进,再往上一层退回。
中序遍历的递归函数是inorder(),指针root是二叉树指针,递归操作步骤如下:
Step 1: 检查是否可以继续前进,即指针root不等于NULL
Step 2: 如果可以前进,处理方式如下:
(1)递归调用inorder(root->left),往左走
(2)处理目前的结点
(3)递归调用inorder(root->right),往右走 -
先序遍历
每遍历到一个结点,就立刻处理该结点。遍历的顺序是先向着树的左方走直到无法前进后,才转往右方走。
先序遍历的递归函数是preorder(),指针root是二叉树指针,递归操作步骤如下:
Step 1: 先检查是否已经到达叶结点,也就是指针root等于NULL
Step 2: 如果不是叶子结点,表示可以继续走,处理方式如下:
(1)处理目前结点
(2)递归调用preorder(root->left),往左走
(3)递归调用preorder(root->right),往右走 -
后序遍历
后序遍历方式刚好和前序遍历的方式相反,它是等到结点的两个子结点都遍历过后才运行处理。后序遍历的递归函数是postorder(),输入的参数是树指针root,此时后序遍历的递归操作如下:
Step 1: 先检查是否已经到达叶结点,也就是指针root等于NULL
Step 2: 如果不是叶子结点,表示可以继续走,处理方式如下:
(1)递归调用postorder(root->left),往左走
(2)递归调用postorder(root->right),往右走
(3)处理目前结点
3.实验准备:熟悉二叉树的特点及基本操作。
4.实验步骤:
(1)审清题意,分析并理出解决问题的基本思路。
(2) 根据基本思路,设计好程序的算法。
(3)根据算法编写源程序。(
4) 在计算机上编译程序,检验程序的可运行性
- 实验报告:
(1)数据结构设计;
(2)程序框图;
(3)程序代码;
(4)程序调试过程和结果;
(5)总结
三、实验步骤
//TreeNode
typedef struct TreeNode{
int data;
struct TreeNode *Left,*Right;
}TreeNode,*Tree;
/ /前序顺序创建二叉树
void PlantTree(Tree &T){
int c;
cin>>c;
if(c==-1000){
T=NULL;
}else{
T=(TreeNode*)malloc(sizeof(TreeNode));
T->data=c;
PlantTree(T->Left);
PlantTree(T->Right);
}
}
//递归遍历部分*****************
void ProTraverseTree(Tree T){
if(T){
cout<<T->data<<" ";
ProTraverseTree(T->Left);
ProTraverseTree(T->Right);
};
}
void MidTraverseTree(Tree T){
if(T){
ProTraverseTree(T->Left);
cout<<T->data<<" ";
ProTraverseTree(T->Right);
};
}
void PostTraverseTree(Tree T){
if(T){
ProTraverseTree(T->Left);
ProTraverseTree(T->Right);
cout<<T->data<<" ";
};
}
//非递归遍历部分*******************
struct Node{
TreeNode* Data;//Data中放的是指针
struct Node* next;
Node(TreeNode *e):Data(e),next(NULL){}
Node(){next=NULL;}
};
//堆栈
struct Stack{
Node* base;
Stack(){base=new Node;/*头指针*/ }
void Push(TreeNode* e){//每次放入的是Node中Data类型的元素
Node* t=new Node(e);
t->next=base->next;
base->next=t;
}
Node* Pop(){//Pop出的是Node*
Node* temp=base->next;
base->next=temp->next;
return temp;
}
bool IsStackEmpty(){
if(base->next==NULL)
return 1;//空返回1
return 0;
}
};
//队列
struct Que{
Node* front,*rear;
Que(){front=new Node;rear=front;}
void EnQue(TreeNode* e){
Node* t=new Node(e);
rear->next=t;
rear=t;
}
Node* DeQue(){
Node* temp=front->next;//头结点
if(!temp){cout<<"出队失败,队列为空\n";exit(0);}
if(temp->next)
front->next=temp->next;
if(temp->next==NULL)// TAT
front=rear;
return temp;
}
bool IsQueEmpty(){
if(front->next==NULL)
return 1;//空返回1
return 0;
}
};
//主函数
int main(){
Tree T;
PlantTree(T);
cout<<"前序创建二叉树完成!"<<endl;
//递归前序遍历
cout<<"递归前序遍历";ProTraverseTree(T);cout<<endl;
//递归中序遍历
cout<<"递归前中遍历";MidTraverseTree(T);cout<<endl;
//递归后序遍历
cout<<"递归前后遍历";PostTraverseTree(T);cout<<endl;
/*非递归的前序遍历*/ cout<<"非递归前遍历";
Stack S;
S.Push(T);
while(!S.IsStackEmpty()){//栈不空
TreeNode* t=S.Pop()->Data;
cout<<t->data<<' ';
if(t->Right)S.Push(t->Right);
if(t->Left)S.Push(t->Left);
}
cout<<"\n---------------\n";
/*非递归层序遍历*/cout<<"非递归层序遍历";
Que Q;
Q.EnQue(T);
while(!Q.IsQueEmpty()){
TreeNode* t=Q.DeQue()->Data;
cout<<t->data<<' ';
if(t->Left) Q.EnQue(t->Left);
if(t->Right)Q.EnQue(t->Right);
}
cout<<"\n---------------\n";
return 0;
}
输入:
//5 4 2 1 -1000 -1000 3 -1000 -1000 -1000 6 -1000 8 7 -1000 -1000 9 -1000 -1000
输出: