需要实践先序遍历,我们先建立二叉树。这里采用先序序列建立二叉树,不为别的,因为简单。
typedef int ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}*BiTree, BiTNode;
void CreateBiTreePreOrder(BiTree &T){
ElemType data;
cin>>data;
if(data==-1){
T=NULL;
}else{
T = new BiTNode();//(BiTree)malloc(sizeof(BiTNode));
}
if(!T){
return;
}else{
T->data = data;
CreateBiTreePreOrder(T->lchild);
CreateBiTreePreOrder(T->rchild);
}
}
下面是对先序遍历的实现:
① 首先是最简单的先序递归算法
递归的思想就是将需要重复的步骤分离出来,反复调用,而且下一次的调用需要用到上一次调用的结果。(可以理解为有依赖关系存在)
//递归的先序遍历
void PreOrder(BiTree T){
if(T){
cout<<T->data<<" ";
PreOrder(T->lchild);
PreOrder(T->rchild);//这里的压栈,只是为了再一次调用上面的函数
}
}
②下面来对递归算法进行非递归实现
方法一:模拟递归算法的操作过程。
按照先序的思想,可以转化为循环控制。
- 入栈前,先输出本节点信息;
- 先左子树一次入栈,直到没有左子树的结点为止;
- 出栈栈顶元素,然后,找到右子树,继续①②操作,直到栈为空 且 结点为空。
在遍历的过程中,进栈、出栈可能会出现栈空的情况,但这时候遍历还没有结束, 故而采用双重判断。
//先序遍历非递归算法
void PreOrder(BiTree bt){
//需要用到栈,这里简单写作一个数组来用, 最好用链栈,定义好入栈、出栈的操作接口
BiTree T = bt;
BiTree ptr[20];
int top = -1;
while(T || top!=-1){
//按照上面的遍历,先输出数据,然后左子树入栈
while(T){
cout<<T->data<<" ";
ptr[++top]=T;
T=T->lchild;
}
if(top!=-1){
T = ptr[top--];
T = T->rchild;
}
}
}
方法二:分析先序遍历的特点。
充分考虑先序遍历的特点
- 1入栈。
- 1出栈(栈顶元素出栈),输出栈顶元素1,并将1的左右孩子节点入栈;其中右孩子4先入栈,然后左孩子2入栈。(因为,对左边孩子的访问先序遍历先于右孩子,后入栈的先访问)。
- 2出栈(栈顶元素出栈),输出栈顶元素2,并将2的左右孩子节点入栈,同理5先入栈,3后入栈。
- 3出栈(栈顶元素出栈),输出栈顶元素3,3为叶子结点,无孩子,本次无入栈。
- 5出栈(栈顶元素出栈),输出栈顶元素5
- 4出栈(最后的栈顶元素出栈),此时 栈空,遍历完毕。
void PreOrder(BiTree bt){
BiTree ptr[20];
int top = -1;
BiTree pt = bt;
ptr[++top] = pt;
while(top!=-1){
pt = ptr[top--];//每次栈顶元素出栈
cout<<pt->data<<" ";//输出
if(pt->rchild)
ptr[++top] = pt->rchild;
if(pt->lchild)
ptr[++top] = pt->lchild;
}
}
-----------------------------------------分割线------------------------------------------------------------
测试截图:
作者:无涯明月
发文时间:2018-11-16