自己编了一道有关数据结构二叉树的遍历非递归遍历的题,但有很多错误,想请您给改改,行么?谢谢~

您的位置: &
数据结构中二叉树的生成及遍历非递归算法浅析
摘 要:本文主要介绍数据结构中二叉树的生成,以及二叉树的先序、中序和后序的非递归算法。
优质期刊推荐数据结构c语言版&二叉树的建立及前序,中序,后序非递归(栈)遍历
#define num
typedef char
typedef struct
&struct node * lchild,*
typedef BinTNode
BinTNode *p;
void NodePath(BinTree
bt,BinTNode *ch);
BinTree CreateBinTree(BinTree bt);
void Preorder(BinTree bt);
void Inorder(BinTree bt);
BinTNode * FindX(BinTree bt, DataType x);
void Postorder(BinTree bt);
int main()
&BinTree bt = NULL;
&int xz = 1;
&char ch1;
&while(xz)
&&printf("二叉树的遍历\n");
&&printf("=============================\n");
&&printf("1,建立二叉树存储结构!\n");
&&printf("2,求二叉树的前序遍历!\n");
&&printf("3,求二叉树的中序遍历!\n");
&&printf("4,求二叉树的后序遍历!\n");
&&printf("5,求指定节点的路径\n");
&&printf("0,退 出 系 统 \n");
&&printf("============================\n");
&&printf("请选择:0 -
&&scanf("%d",&xz);
&&getchar();
&&switch(xz)
&&&case 1:
&&&&printf("输入二叉树按层次节点值(按完全二叉树):\n");
= CreateBinTree(bt);
&&&&printf("二叉树创建完成!\n");
&&&case 2:
&&&&printf("该二叉树的前序遍历序列是:");
&&&&Preorder(bt);
&&&&printf("\n");
&&&case 3:
&&&&printf("该二叉树的中序遍历序列是:");
&&&&&&&&&&&&&&&
Inorder(bt);
&&&&printf("\n");
&&&case 4:
&&&&Postorder(bt);
&&&case 5:
&&&case 0:
&&&&return
&&&default:
&&&&printf("wrong
input!\nplease input again!!!!!!\n");
&return 0 ;
BinTree CreateBinTree(BinTree bt)
&BinTNode *Q[num];
&BinTNode *s;
&int front,
&ch = getchar();
&getchar();
&bt = NULL;
&front = 1;
&rear = 0;
&while(ch != '#')
&&s = NULL;
&&if(ch != )
&&&s = (BinTNode
*)malloc(sizeof(BinTNode));
&&&s-&data =
&&&s-&lchild=s-&rchild=NULL;
&&Q[rear] =
&&if(rear == 1)
&&&if(s!=NULL
&& Q[front]!=NULL)
&&&&if(rear%2
&&&&&Q[front]-&lchild
&&&&&Q[front]-&rchild
&&&if(rear%2
&&&&front++;
&&ch = getchar();
&&getchar();
// the pre-
void Preorder(BinTree bt)
&BinTNode * stack[num];
&int top = 0;
&BinTNode *
&stack[top] =
&while(top &= 0)
&&s = stack[top];
&&if(s!=NULL)
&&&printf("&
%c",s-&data);
&&&stack[top] =
&&&stack[top]=
void Inorder(BinTree bt)
{&& BinTNode * stack[num];
&BinTNode *s;
&stack[top] =
&while(top&=0){
&&s = stack[top];
&&if(s!=NULL){
&&while(s-&lchild!=NULL){&&
&&stack[top]= s-&
&&s = stack[top];
&printf("& %c",s-&data);
&&&if(s-&rchild!=NULL){&
&&&&stack[top]=s-&&&
&&if(top&0)
&&s=stack[top];
&&printf("&
%c",s-&data);&&&&&&&
&stack[top]=s-&
&printf("\n中序遍历结束!\n");
void Postorder(BinTree bt)
&BinTNode * stack[num];
top=0,i=0;
&int sigal[20];
&BinTNode *s;
&stack[top] =
for(i=0;i&20;i++){
&sigal[top]=0;
&while(top&=0){
&&s=stack[top];
&&if(s!=NULL){
&&&while(s-&lchild!=NULL||s-&rchild!=NULL){
&&&&&&&&&&&&&&&
while(s-&lchild!=NULL&&sigal[top]==0){
&stack[top]= s-&
&s = stack[top];
&while(s-&lchild!=NULL&&sigal[top]==0){
&&stack[top]= s-&
&s = stack[top];
&&&printf("%c",s-&data);
&&&sigal[top]=1;
&&s=stack[top];&&&&&&
&stack[top]=s-&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。数据结构之二叉树的非递归兑现及“狡猾”的指针
&来源:读书人网&【读书人网():综合教育门户网站】
数据结构之二叉树的非递归实现及“狡猾”的指针先说说我实现二叉树的方法,才能开始讲述我被指针搞得晕头晕脑
数据结构之二叉树的非递归实现及“狡猾”的指针先说说我实现二叉树的方法,才能开始讲述我被指针搞得晕头晕脑的痛苦经历。/****************二叉树非递归的总体分析*****************/(1)建立二叉树栈的应用:用空格键表示空指针,我们利用栈来保存左右孩子指针未都被赋值的节点,空指针不允许入栈开始建立:以循环遍历用户输入的字符串来建立二叉树,如:&AB#D##CE###&(这里先用#代替空格,方便查看)我们以先序建立二叉树,按上面例子中的字符串建立的二叉树如下:(visio不怎么会用,这图看着。。。忍耐一下)从图中可以清晰的发现一个规律:字符串中,任意一个字符的前一个(即i-1)字符若不为空格的话,这个字符一定是前一个非空格字符的左子树在由先序这个条件还可以发现,我们始终是从左向右建立子树的,所以,如果第i-1个字符为空格,第i个字符就一定是前一个刚建立的子树的右子树(2)遍历二叉树栈的应用:我们从二叉树顶端开始走的时候,将未遍历的节点的数据入栈,遍历一个节点从栈中弹一个出来中序遍历:我们采用中序遍历二叉树,在非递归算法中,根据中序的定义,我们也需要让第一个取得的头节点A从右开始向下走,一直往右边走(途中遇到的节点依次入栈),直到走到第一个左子树为空的节点,这里显然是B,然后访问B,然后B退栈,若B右指针非空,则遍历往右走一步(为空的时候下面讨论),然后B的右子树入栈,继续循环以B的右子树为头节点走到最左端,直到把节点都走完,这里走到D 的时候就已经结束了,直接访问D,D退栈,根据栈顶元素A,访问A,A退栈,这是往右走,C入栈,走到最左端E,E入栈,访问E,E退栈,这时和D的情况一样了,已经是一个叶子节点了,就根据栈顶C,访问C,C退栈,栈空,表明遍历结束特殊情况:当我们遍历完最左端的节点之后,会向右走一步,如果此节点的右子树本为空,就不能往右走了,依据中序的定义,如果已经访问到了右子树并且为空,说明这个双亲节点已经被访问过了,那么我们就要去访问栈顶数据,弹出栈顶元素,如果新的栈顶元素的右子树依旧为空并且此时栈还非空,就继续这种循环,直到找到一个右子树为被访问过的栈顶元素,或者栈以为空(这种情况表明遍历结束)(3)销毁二叉树栈的应用:从头节点依次入栈,从栈顶开始销毁节点后序销毁:需要从叶子节点开始销毁,并且要修改其双亲节点的指针值。首先,依旧要走到最左端B,依次入栈A、B,发现B右子树非空,往右走一步,D入栈,这个时候,以D为头节点走到D的最左端行不通了,因为D的左子树为空,就看能不能往D的右边走一步,发现D的右子树也为空,就说明D为叶子节点,弹出它,并将新的栈顶元素的右指针设为空,freeD,(这里有个疑问:怎么确定当前的节点是双亲节点的左孩子还是右孩子呢?根据后序的定义,如果一个节点的右指针为空的话,就说明这个节点为叶子节点,如果它的双亲节点左孩子还不为空,就说明这个节点对应的是左指针,如果双亲节点的左孩子已经为空,说明它本身就是空或者已经被释放了,则这个节点就一定是右指针。)释放了D之后,根据栈顶指示,销毁B,再跳到C,跳到E,释放E、C、A,最后栈空,表明销毁结束。/****************指针的误用*****************/从上面的设计过程来看,建立和遍历中对栈的使用是大不同的。遍历二叉树的时候,我们只需要访问节点的数据即可,但在建立二叉树的时候,我们需要节点的准确地址来连接这个树。一开始我并没有注意到这个巨大的区别,依然用遍历时采用的栈的使用来建立二叉树,结果可想而知,“灵活”的指针肯定已经失控了。栈的指针误区:栈里面是申请的一块连续的动态内存空间,每一次压入或弹出的元素其实都不是你真正想用的数据,因为数据的位置变了。栈中存放的每一个数据都是放到了你申请的这块空间上,但你实际的数据是放到另一块内存空间上的。一开始我就直接从栈中弹出节点,将新建的节点连到里面,额。。。情况具体是这样的(就以前两个节点为例吧):&实际的内存地址栈中的内存地址A0x0xB(A的左子树)0x0x0085354c很显然,B实际应该连到A的左子树上,但是,如果先把A入栈,根据栈顶指示发现应该将B连到栈顶元素(A)的左子树上,于是便直接获取栈顶地址0x,将0x处的内容连上,然后B再入栈,遇到B的左子树应该为空的时候,获取栈顶元素(B)的地址0x0085354c,将0x给连上,没有调试程序的话,是很难发现这里的所谓“连上”其实根本就是断的。因为我们用的是正确的子树地址,但是却把它连到了栈里面去了,相当于从栈那棵“笔直的大树”里长了许多叶子出来。。。而原本的“根”却只是孤零零的一片小叶子而已。以前总听牛人说指针经常是C的双刃剑,如果没有足够的功力是无法驾驭它的,现在也是深有体会了,因为这个错误我调试了不下十次才发现。指针误区的解决:为了解决指针指向错误的问题,我想了很多方法,甚至还想将建立二叉树的算法来个大转变,我试过这种方法:将入栈、出栈的语句改为:int DIY_ThreadBinaryTree(ThreadBinaryTree **Root,char *str)最初的RootPtr使用的类型是ThreadBinaryTree *。我们的先序建立二叉树中动态申请了每个节点所需的内存,并且已经按要求连接到了一块儿,现在他们是一个整体,领头的就是头节点A,我们需要将A节点的地址传出去,大家都知道子函数里面定义的内容是会随着子函数的结束而释放的,如果我们只是简单的想把RootPtr这个指针传入二叉树建立的函数的话,当函数结束时,我们真正的头节点确实没有被释放,因为它需要我们认为释放,但是保存它地址的RootPtr是不会正确保存它的地址的,因为函数的参数传递终究是相当于赋值的,也就是函数的参数Root和我们传入函数的RootPtr不是同一个东西,Root中有我们需要的地址,但是它会随着函数的结束而被销毁,也就是不会把正确的地址传回给RootPtr。我们要怎么样才能将地址正确返回?答案就是我们要将参数设为指向指针的指针的,这样,当我们传入一个*RootPtr的时候,我们就需要用&RootPtr传入,传给函数的参数**Root,解释出来就是**(&RootPtr),这样就相当于*RootPtr,实现了对Root地址的间接传递,保护了其实际内容。释放的方法在最开始的算法分析中已经解释过了。/****************编程总结******************/在学习C的时候,一定要深入底层,从内存地址着手,不然真的会被指针给耍得团团转。(二叉树的建立、遍历、销毁的实现代码放代码分享里了)请教大家一题有关数据结构的题:编写递归算法,计算二叉树中叶子结点的数目。
请教大家一题有关数据结构的题:编写递归算法,计算二叉树中叶子结点的数目。
算法:
void childExchange(Node t){
N
if(t.left!=null){
childExchange(t.left);
}
if(t.right!=null){
childExchange(t.right);
}
n=t.
t.right=t.
t.left=n;
}
的感言:谢谢。不知对不对!呵呵
相关知识等待您来回答
编程领域专家急!!!数据结构C语言版,分别编写一个后序遍历和一个中序遍历二叉树的递归算法_百度知道
急!!!数据结构C语言版,分别编写一个后序遍历和一个中序遍历二叉树的递归算法
status preordertravers(bitree t,status(* visit)(telemtype e)){沪唬愤剿莅济缝汐俯搂
status printelement(telemtype e){
if(visit(t-&data))
if(preordertraverse(t-&lchild.visit))
if(preordertraverse(t-&rchild.visit))
提问者采纳
//.中序遍历二叉树:递归算法。void zhbianli(BiTree T){ if(!T) zhbianli(T-&lchild); printf(&%c &,T-&data); zhbianli(T-&rchild );}//.后序遍历二叉树:递归算法。void houbianli(BiTree T){ if(!T沪唬愤剿莅济缝汐俯搂)
houzhbianli(T-&lchild); houzhbianli(T-&rchild );
printf(&%c &,T-&data);}上述算法中将 visit函数功能简单实现为printf
其他类似问题
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 二叉树的遍历算法 的文章

 

随机推荐