LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1399|回复: 30

关于采用链栈实现递归消除二叉树的遍历

[复制链接]
发表于 2004-12-4 20:01:09 | 显示全部楼层 |阅读模式
采用链栈来递归消除二叉树的先根遍历,我遇到了一点问题。
主要的算法还是比较传统:
1.构造一个链栈
2.while(当前树结点不为NULL)
{
访问当前结点
如果存在右子树,则将右子树结点指针入栈
如果左子树为NULL时,出栈,然后将出栈的结点指针替换为当前指针,继续下一个循环
替换当前树结点为其左子树
}

按这个算法来编写C代码,没有问题,但这个栈链究竟如何能弹出结点指针呢?换句话说,如何能改变传递给出栈函数的当前结点这个参数呢?

给出完整代码,大家帮我看看。

stack.h

  1. #include <stdlib.h>

  2. /* Store per pointer of bitree */
  3. typedef void * lkstack_datatype;
  4. typedef struct lkstack_node * lkstack_pointer;
  5. struct lkstack_node
  6. {
  7.   lkstack_datatype data;
  8.   lkstack_pointer next;
  9. };
  10. typedef struct
  11. {
  12.   lkstack_pointer top;
  13. } lkstack;

  14. /* functions for lkstack */
  15. int push_lkstack(lkstack *ls,lkstack_datatype x)
  16. {
  17.   lkstack_pointer p=malloc(sizeof(lkstack_pointer));
  18.   p->data=x;
  19.   p->next=ls->top;
  20.   ls->top=p;
  21.   return 1;
  22. }

  23. [color=red]int pop_lkstack(lkstack *ls, lkstack_datatype *x)
  24. {
  25.   lkstack_pointer p;
  26.   if(ls->top==NULL) return 0;
  27.   p=ls->top;
  28.   x=p->data;
  29.   /* DEBUG start */
  30.   printf("*in stack* DEBUG -- %d\n",p->data);
  31.   printf("*in stack* DEBUG -- %c\n",*x);
  32.   /* DEBUG end */
  33.   ls->top=p->next;
  34.   free(p);
  35.   return 1;
  36. }[/color]

  37. void init_lkstack(lkstack *ls)
  38. {
  39.   ls->top=NULL;
  40. }
复制代码


bitree.c

  1. #include <stdlib.h>
  2. #ifndef RECURSION
  3. #include "stack.h"
  4. #endif

  5. typedef int datatype;
  6. typedef struct node *pointer;
  7. struct node
  8. {
  9.   datatype data;
  10.   pointer lchild,rchild;
  11. };
  12. typedef pointer bitree;

  13. bitree create_bitree (char Pre[],int ps,int pe,char In[],int is,int ie)
  14. {
  15.   bitree t;
  16.   int i;
  17.   if(ps>pe) return NULL;
  18.   t=(bitree *)malloc(sizeof(bitree));
  19.   t->data=Pre[ps];
  20.   i=is;
  21.   while(In[i]!=Pre[ps]) i++;
  22.   t->lchild=create_bitree(Pre,ps+1,ps+i-is,In,is,i-1);
  23.   t->rchild=create_bitree(Pre,ps+i-is+1,pe,In,i+1,ie);
  24.   return t;
  25. }

  26. int free_bitree(bitree t)
  27. {
  28.   if(t->lchild==NULL && t->rchild==NULL) {
  29.     free(t);
  30.     return 1;
  31.   }
  32.   free_bitree(t->lchild);
  33.   free_bitree(t->rchild);
  34.   free(t);
  35.   return 1;
  36. }

  37. #ifdef RECURSION

  38. void list_bitree_rlr(bitree t)
  39. {
  40.   if(t==NULL) {
  41.     printf("There is no data in this tree.\n");
  42.     return 0;
  43.   }
  44.   if(t->lchild==NULL && t->rchild==NULL) {
  45.     printf("%c ",t->data);
  46.     return;
  47.   }
  48.   printf("%c ",t->data);
  49.   list_bitree_rlr(t->lchild);
  50.   list_bitree_rlr(t->rchild);
  51. }

  52. #else

  53. void list_bitree_rlr(bitree t)
  54. {
  55.   lkstack mylkstack;
  56.   /* DEBUG start */
  57.   lkstack *debug=&mylkstack;
  58.   /* DEBUG end */
  59.   init_lkstack(&mylkstack);
  60.   pointer p=t;
  61.   while(p!=NULL){
  62.     printf("%c ",p->data);
  63.     if(p->rchild!=NULL) {
  64.       push_lkstack(&mylkstack,p->rchild);
  65.       /* DEBUG start */
  66.       if (debug->top==NULL) printf("empty error.\n");
  67.       printf("DEBUG tree -- %d\n",p->rchild);
  68.       printf("DEBUG stack -- %d\n",debug->top->data);
  69.       pop_lkstack(&mylkstack,p);
  70.       printf("DEBUG pop node -- %d\n",p);
  71.       return;
  72.       /* DEBUG end */
  73.     }
  74.     if(p->lchild==NULL) {
  75.       pop_lkstack(&mylkstack,p);
  76.       continue;
  77.     }
  78.     p=p->lchild;
  79.   }
  80. }

  81. #endif

  82. main()
  83. {
  84.   bitree t;
  85.   char Pre[6]="ABDEC";
  86.   char In[6]="DBEAC";
  87.   t=create_bitree(Pre,0,4,In,0,4);
  88.   list_bitree_rlr(t);
  89.   if(free_bitree(t)) printf("ok, the tree is free.\n");
  90. }
复制代码


运行调试:

  1. ibox@ibox ibox $ gcc -DRECURSION bitree.c
  2. bitree.c: In function `create_bitree':
  3. bitree.c:20: warning: assignment from incompatible pointer type
  4. bitree.c: In function `list_bitree_rlr':
  5. bitree.c:47: warning: `return' with a value, in function returning void
  6. ibox@ibox ibox $ ./a.out
  7. A B D E C ok, the tree is free.
  8. ibox@ibox ibox $ gcc bitree.c
  9. bitree.c: In function `create_bitree':
  10. bitree.c:20: warning: assignment from incompatible pointer type
  11. bitree.c: In function `list_bitree_rlr':
  12. bitree.c:76: warning: passing arg 2 of `pop_lkstack' from incompatible pointer type
  13. bitree.c:82: warning: passing arg 2 of `pop_lkstack' from incompatible pointer type
  14. ibox@ibox ibox $ ./a.out
  15. A DEBUG tree -- 134520976
  16. DEBUG stack -- 134520976
  17. *in stack* DEBUG -- 134520976
  18. *in stack* DEBUG -- C
  19. DEBUG pop node -- 134520912
  20. ok, the tree is free.
复制代码


1.关键在于pop_lkstack这个函数不能把弹出的结点指针传递出去,导致死循环。
2.如果采用递归方式来遍历树,倒是没有问题的。
3.如果采用顺序栈,也不会出现问题。

ps:构造树的算法是采用先根遍历和中根遍历序列结合生成的

所以,整个算法是正确的,但错就错在C语言本身的指针规范,我不太清楚,大家指点。尤其是kj501兄,帮帮忙,谢谢。
发表于 2004-12-4 20:11:19 | 显示全部楼层
  1. bitree.c: In function `create_bitree':
  2. bitree.c:20: warning: assignment from incompatible pointer type
复制代码
  1. bitree create_bitree (char Pre[],int ps,int pe,char In[],int is,int ie)
  2. {
  3.   bitree t;
  4.   int i;
  5.   if(ps>pe) return NULL;
  6.   t=(bitree *)malloc(sizeof(bitree));
复制代码
发表于 2004-12-4 20:13:02 | 显示全部楼层
  1. bitree.c: In function `list_bitree_rlr':
  2. bitree.c:47: warning: `return' with a value, in function returning void
复制代码

  1. void list_bitree_rlr(bitree t)
  2. {
  3.   if(t==NULL) {
  4.     printf("There is no data in this tree.\n");
  5.     return 0;
  6.   }
复制代码


不要忽视任何warning
 楼主| 发表于 2004-12-4 20:27:48 | 显示全部楼层
那些warnings和我说的问题是无关的。
我在上面用gcc -DRECURSION bitree.c来给出递归做法就是为了证实这个算法的正确性!

其实就是如何将指针传递出去的问题。
发表于 2004-12-4 20:44:31 | 显示全部楼层
  1. typedef struct lkstack_node * lkstack_pointer
复制代码
  1. int push_lkstack(lkstack *ls,lkstack_datatype x)
  2. {
  3.   lkstack_pointer p=malloc(sizeof(lkstack_pointer));
复制代码
 楼主| 发表于 2004-12-4 20:47:51 | 显示全部楼层
最初由 yangtou 发表
  1. typedef struct lkstack_node * lkstack_pointer
复制代码
  1. int push_lkstack(lkstack *ls,lkstack_datatype x)
  2. {
  3.   lkstack_pointer p=malloc(sizeof(lkstack_pointer));
复制代码

压栈是没有问题的,请看debug调试输出部分。
发表于 2004-12-4 20:53:21 | 显示全部楼层
教主对指针和malloc的理解有误,我上面所说和第一个的waning显然是有问题的
再好好看看那些warning吧
  1. warning: assignment from incompatible pointer type
  2. bitree.c: In function `list_bitree_rlr':
  3. bitree.c:47: warning: `return' with a value, in function returning void
  4. ibox@ibox ibox $ ./a.out
  5. A B D E C ok, the tree is free.
  6. ibox@ibox ibox $ gcc bitree.c
  7. bitree.c: In function `create_bitree':
  8. bitree.c:20: warning: assignment from incompatible pointer type
  9. bitree.c: In function `list_bitree_rlr':
  10. bitree.c:76: warning: passing arg 2 of `pop_lkstack' from incompatible pointer type
  11. bitree.c:82: warning: passing arg 2 of `pop_lkstack' from incompatible pointer type
复制代码


先把语法搞对,算法其实很简单,难搞的是语法
 楼主| 发表于 2004-12-4 22:01:15 | 显示全部楼层
我想问的就是语法问题啊~~~
这个输出就是给大家看的。

兄弟能帮我修正吗?
发表于 2004-12-4 22:20:20 | 显示全部楼层
T* p=(T*)malloc(size)
 楼主| 发表于 2004-12-4 22:45:38 | 显示全部楼层
最初由 yangtou 发表
T* p=(T*)malloc(size)

晕~~~
这个我知道阿。要不,递归算法也不会成功啊。

  1. lkstack_pointer p=malloc(sizeof(lkstack_pointer));
  2. bitree t;
  3. t=(bitree *)malloc(sizeof(bitree));
复制代码


请先看看我的代码好吗?或者帮忙调试一下也好啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表