二叉树递归非递归遍历Word文档下载推荐.docx

上传人:b****5 文档编号:21368271 上传时间:2023-01-30 格式:DOCX 页数:42 大小:270.70KB
下载 相关 举报
二叉树递归非递归遍历Word文档下载推荐.docx_第1页
第1页 / 共42页
二叉树递归非递归遍历Word文档下载推荐.docx_第2页
第2页 / 共42页
二叉树递归非递归遍历Word文档下载推荐.docx_第3页
第3页 / 共42页
二叉树递归非递归遍历Word文档下载推荐.docx_第4页
第4页 / 共42页
二叉树递归非递归遍历Word文档下载推荐.docx_第5页
第5页 / 共42页
点击查看更多>>
下载资源
资源描述

二叉树递归非递归遍历Word文档下载推荐.docx

《二叉树递归非递归遍历Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《二叉树递归非递归遍历Word文档下载推荐.docx(42页珍藏版)》请在冰豆网上搜索。

二叉树递归非递归遍历Word文档下载推荐.docx

PreOrder(TreeNode*t)//protected先序遍历输出树中所有的值

{

if(t)

{

cout<

<

t->

data;

PreOrder(t->

LeftChild);

RightChild);

}//if

}//PreOrder

voidTree:

PreOrder(boolenter)//public先序遍历

PreOrder(Root);

if(enter)cout<

endl;

调用代码:

#defineElemTypeint

intmain()

{

ElemTypedata[9]={1,2,NULL,3,NULL,NULL,4,NULL,NULL};

TreeT1;

TreeNode*t;

T1.MakeNode(t,5,true,NULL);

T1.InitTree(data,9);

//根据data和数组长度为9建立二叉树

T1.insertLeftChild(5,t);

//在编号为5的树结点的左孩子插入数字5

T1.MakeNode(t,6,true,NULL);

T1.insertRightChild(5,t);

//在编号为5的树结点的右孩子插入数字6

T1.MakeNode(t,9,true,NULL);

T1.insertLeftChild(10,t);

//在编号为10的树结点的左孩子插入数字9

T1.PreOrder(true);

return0;

}

代码分析:

代码的访问顺序:

访问1,输出1;

访问2,输出2;

访问NULL(2的左孩子);

访问3,输出3;

访问5,输出5;

访问9,输出9;

访问NULL(9的左孩子);

访问NULL(9的右孩子);

访问NULL(5的右孩子);

访问6,输出6;

访问NULL(6的左孩子),访问NULL(6的右孩子);

访问4,输出4;

访问NULL(4的左孩子),访问NULL(4的右孩子);

输出1235964

运行结果:

算法2.先序遍历的非递归实现

Non_Recursive_PreOrder(TreeNode*T)//protected非递归先序遍历

/*——————————————————————————

首先进行p的输出。

存储的内容基本上是右结点。

遍历左边缘不断输出,然后转到右结点入栈,继续

左边缘不断输出。

等到再无左边缘的时候逆向输出

所有右孩子。

———————————————————————————*/

stack<

TreeNode*>

s;

TreeNode*p=T,*q;

s.push(p);

//把Root推入栈内

while(!

s.empty())//如果s不空

p->

q=p->

RightChild;

if(q)s.push(q);

//如果q(p的右孩子)不空则将q推入栈

p=p->

LeftChild;

if(!

p)//如果p(p的左孩子)为空则回到(p的右孩子)

{

p=s.top();

s.pop();

}//if

}//while

}//Non_recursive_PreOrder

StatusTree:

Non_Recursive_PreOrder(boolenter)//非递归先序遍历

Non_Recursive_PreOrder(Root);

returnOK;

//根据data和数组长度为9建立二叉树

//在编号为10的树结点的左孩子插入数字9

T1.Non_Recursive_PreOrder(true);

不断遍历左孩子,如果有右孩子就入栈。

遍历到NULL的时候就读取栈首元素(即最近的一个右结点)。

然后重复以上过程。

访问1,输出1,4入栈;

访问2.输出2,3入栈;

访问NULL,3出栈;

访问3,输出3,6入栈;

访问5,输出5;

访问9;

输出9;

访问NULL,6出栈;

访问NULL,4出栈;

访问4,输出4;

算法3中序遍历的递归实现

InOrder(boolenter)//public中序遍历

InOrder(Root);

}//InOrder

InOrder(TreeNode*t)//protected中序遍历输出树中所有的值

InOrder(t->

//在编号为5的树结点的右孩子插入数字6

T1.InOrder(true);

访问1;

访问3;

访问5;

算法4中序遍历的非递归实现

Non_Recursive_IndexOrder(boolenter)//非递归中序遍历

Non_Recursive_IndexOrder(Root);

}//Non_recursive_IndexOrder

Non_Recursive_IndexOrder(TreeNode*T)//protected非递归中序遍历

/*————————————————————————————

首先不断遍历左边缘但不输出只入栈,

直到碰到NULL后(此时p=NULL)返回父结点输出父结点。

然后转到右结点入栈,继续遍历左边缘不输出

只入栈。

一直遍历到某个度为0的右结点的右孩子的时候

结束一支分支的遍历。

另一支分支的遍历相同。

这一支分支的遍历

结束后中序遍历结束。

—————————————————————————————*/

TreeNode*p=T;

s.push(NULL);

while

(1)

while(p)

s.push(p);

//栈是回溯法的主要工具

p=p->

}//while遍历左边缘直到NULL

s.top())break;

//如果栈到达栈底则跳出

p=s.top();

//p=NULL的时候返回其父结点或爷结点

s.pop();

//弹出父结点

//输出父结点

//调用父结点的右孩子

//在编号为5的树结点的左孩子插入数字5

T1.Non_Recursive_IndexOrder(true);

入栈,访问左孩子,入栈,访问左孩子。

重复进行,一直到访问NULL。

获得父节点(即栈首元素),并输出值,然后访问右结点,如果有,则重复以上过程。

如果为NULL,则再次出栈输出值,继续访问右结点。

访问1,入栈;

访问2,入栈;

访问NULL(2的左孩子),2出栈,输出2;

访问3,入栈;

访问5,入栈;

访问9,入栈;

访问NULL(9的左孩子),9出栈,输出9;

访问NULL(9的右孩子),5出栈,输出5;

访问NULL(5的右孩子),3出栈,输出3;

访问6,入栈;

访问NULL(6的左孩子),6出栈,输出6;

访问NULL(6的右孩子),1出栈,输出1;

访问4,入栈;

访问NULL(4的左孩子),4出栈。

输出4;

访问NULL(4的右孩子),栈空,跳出循环;

算法5后序遍历的递归实现

PostOrder(boolenter)//public后序遍历

PostOrder(Root);

}//PostOrder

PostOrder(TreeNode*t)//protected后序遍历输出树中所有的值

PostOrder(t->

T1.PostOrder(true);

访问2;

访问NULL(9的左孩子),访问NULL(9的右孩子),输出9;

访问5,访问NULL(5的右孩子),输出5;

访问3,访问6,访问NULL(6的左孩子),访问NULL(6的右孩子),输出6;

访问1,访问4,访问NULL(4的左孩子),访问NULL(4的右孩子),输出4;

算法6后序遍历的非递归实现

Non_Recursive_PostOrder(boolenter)//非递归后序遍历

Non_Recursive_PostOrder(Root);

}//Non_Recursive_PostOrder

Non_Recursive_PostOrder(TreeNode*T)//protected非递归后序遍历

先进行左边缘遍历,入栈,并记载访问次数为1(tag=0)。

直到p=NULL,然后返回父结点,父结点访问次数为2(tag=1)。

p转到父结点的右孩子。

重复以上步骤。

如果栈顶结点被第三次访问,则输出该结点,弹出。

//用于存储树结点

bool>

s1;

//用于存储结点暂离状态

//没有此句函数直接结束

while

(1)//如果s不空

s1.push(false);

}//while用于存储左边缘树结点,全部暂离

if(s1.top())

s1.pop();

cout<

p=NULL;

}//if第二次访问结点结点已待命,将结点和状态全部弹出,输出结点。

令p=NULL,避免第四次读取结点。

else

s1.push(true);

p=s.top()->

}//else如果结点是暂离,让其准备,当第二次碰见它时就输出。

此时访问右孩子

}//Non_recursive_PostOrder

T1.Non_Recursive_PostOrder(true);

(第一次访问结点入栈状态为false,第二次访问结点将状态改成true,第三次访问结点输出结点数据,避免出现第四次访问结点。

(为什么是这样?

访问父节点的时候设置状态为false,访问左孩子回到父节点状态改成true,从右孩子回到父节点的时候输出父节点,共三次。

非递归后序遍历的步骤:

①定义两个栈,第一个栈类型为<

第二个栈类型为<

,以及树节点指针p,将NULLpush进栈。

②循环,如果p不为空,则(树节点栈)p入栈,(状态栈)false入栈,表示还没进行第二次访问。

然后不断遍历左孩子。

③如果状态栈首元素为true(此时为第三次访问树节点),获得栈首树节点然后输出数据,出栈。

 

否则状态栈首元素为false(此时为第二次访问树节点),将状态改成false,然后访问其右孩子。

④如果到达栈底(NULL)就跳出无限循环。

①循环:

访问1,1入栈,false入栈;

访问2,2入栈,false入栈;

访问NULL,跳出循环;

由于栈首元素为false,false出栈,true入栈,然后访问2的右孩子;

②循环:

访问3,3入栈,false入栈;

访问5,5入栈,false入栈;

访问9,9入栈,false入栈;

访问NULL,跳出循环。

由于栈首元素为false,false出栈,true入栈,然后访问9的右孩子

③循环:

NULL(9的右孩子),跳出循环

由于栈首元素为true,9出栈,true出栈,输出9,然后(TreeNode*)p赋值为NULL;

④循环:

p为NULL,跳出循环。

由于栈首元素是false,false换成true,访问5的右孩子;

⑤循环:

访问NULL(5的右孩子),跳出循环;

由于栈首元素是true,5出栈,true出栈,输出5,p=NULL;

⑥循环:

由于栈首元素是false,false换成true,访问3的右孩子;

⑦循环:

访问6,6入栈,false入栈;

访问NULL(6的左孩子),跳出循环;

由于栈首元素是false,false换成true,访问6的右孩子;

⑧循环:

访问NULL(6的右孩子),跳出循环;

由于栈首元素是true,6出栈,true出栈,输出6,p=NULL;

⑨循环:

NULL,跳出循环。

由于栈首元素是true,3出栈,true出栈,输出3,p=NULL;

⑩循环:

由于栈首元素是true,2出栈,true出栈,输出2,p=NULL;

十一:

循环:

NULL,跳出循环;

false换成true;

访问4

十二:

4入栈,false入栈;

NULL(4的左孩子),跳出循环;

False换成true;

访问NULL;

十三:

4出栈,true出栈,输出4,p=NULL;

十四:

NULL,跳出循环;

1出栈,true出栈,输出1,p=NULL;

到达栈底,退出遍历。

算法7层次遍历

LevelOrder(TreeNode*t)//protected层次遍历

/*——————————————————

读取每一层的时候把下一层存进队列中。

———————————————————*/

TreeNode*p=t;

queue<

q;

do

if(p)

q.push(p->

p=q.front();

q.pop();

}//do

q.empty());

}//LevelOrder

LevelOrder(boolenter)//public层次遍历

LevelOrder(Root);

//根据data和数组长度为9建立二叉树

T1.insertLeftChild(10,t)//在编号为10的树结点的左孩子插入数字9

T1.LevelOrder(true);

完整代码:

#include<

iostream>

string>

stack>

qu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1