不用栈实现二叉树非递归中序遍历源代码说明

来源:互联网 发布:西古德森实况数据 编辑:程序博客网 时间:2024/05/21 09:16

偶尔看到这样一个问题:

 

有个二叉树,每个节点除了左右指针外,还有一个指向父节点的指针。
要求不用递归,中序遍历这棵树。另要求空间复杂度是O(1).

 

空间复杂度为O(1),摆明就是不让用堆栈模拟递归,所以想了想思路,也请教过好几个朋友,大家都基本想法都差不多,由于有指向父节点的指针,必定可以回溯,从而可以不需要堆栈来做记录.

但是实现起来,却发现很多细节需要完善,比如遍历的终止条件,现在我是用预先遍历到最后一个右子树,用这个指针作为终止条件.

昨天大体实现了一下.

 

贴出来,期待达人改进.

 

view pl/*思路: 
  1.     关于终止条件:中序遍历终止于最后的rchild,只能先遍历一遍,将该节点作为终止条件。 
  2.     对遍历时候的 cur节点设置一个状态(0,1,2) 
  3.     0标识其左,右节点情况尚未处理 
  4.     1标识其左节点被处理(包括左节点不存在的情况) 
  5.     2标识从右节点返回(包括右节点不存在的情况) 
  6.      
  7.     3种状态的判断用(post->parent->lchild == post)这样的方法判断。 
  8. */  
  9. void inorder_norecursive(LinkTree *root)  
  10. {  
  11.     LinkTree * cur=root, * post, *fin;    
  12.     int cur_state = 0;  
  13.     while(cur != NULL)                //查找终止条件  
  14.     {  
  15.         post = cur;  
  16.         cur = cur->rchild;     
  17.     }  
  18.     fin = post;  
  19.     cur = root;  
  20.     post = NULL;  
  21.     printf("fin data :%d /n",fin->data);  
  22.     while( !(cur == fin && cur_state >=1) )  
  23.     {  
  24.   
  25.         while(cur != NULL && cur->lchild != NULL && cur_state != 2)          //搜索:每次遍历,当前状态清零,找到可以打印的点,从右节点返回不应该继续向下遍历               
  26.         {  
  27.             cur_state = 0;  
  28.             cur = cur->lchild;     
  29.         }  
  30.         if( (cur == NULL && cur_state == 1) ||  cur_state == 2)            //返回:右节点为空,返回的情况或者从右节点返回  
  31.         {  
  32.             cur = post;  
  33.             if(cur->parent->lchild == cur)  
  34.                 cur_state = 1;  
  35.             else if(cur->parent->rchild == cur)  
  36.                 cur_state = 2;  
  37.             cur = cur->parent;  
  38.         }  
  39.         if( cur->lchild == NULL && cur_state == 0)     
  40.             cur_state = 1;  
  41.         post = cur;                             //post针对cur遍历到NULL时候返回,记录有效节点  
  42.         if( cur_state == 1)                     //中序打印  
  43.         {  
  44.             printf(" %d ",cur->data);  
  45.             if(cur == fin)                    //打印最后一个,显式退出  
  46.                 break;  
  47.         }  
  48.         else if(cur_state == 2)                 //节点的2个子节点已被处理,向上返回  
  49.             continue;  
  50.         if(cur->rchild == fin)                //如果是fin节点的父节点,提前设置cur_state状态,防止while退出  
  51.             cur_state = 0;    
  52.         cur = cur->rchild;  
  53.     }     
  54. }  

原创粉丝点击