结构推理 假设二叉树采用链接存储结构进行存储,t指向根结点,p所指结点和q所指结点为二叉树中的两个结点,编写一个计算它们最近的共同祖先的函数。
【正确答案】(1)数据结构
   #defitie MAXNUM 100
   struct BinTreeNode;
   typedef struct BinTreeNode*PBinTreeNode;
   struct BinTreeNode{
       charinfo;
       PBinTreeNode llink;
       PBinTreeNode rlink;
   };
   typedef struct BinTreeNode*BinTree;
   typedef struct{
       PBinTreeNode ptr;
       int tag;
   }Elem;
   struct SeqStack{
       Elem s[MAXNUM];
       int t;
   };
   typedef struct SeqStack*PSeqStack;
   (2)思路
   注意到用栈的非递归后根周游二叉树时,遇到结点p时,栈中保存的即为p的所有祖先。
   利用这一点,在一次周游中分别找出p和q的所有祖先,然后再找它们最近的共同祖先就很容易了。
   (3)算法
   PBinTreeNode ancestor(BinTree t,PBinTreeNode p,PBinTreeNode q){
       Elem stnode;
       PSeqSta,tck st;
       PBinTreeNode pbnode,pstring[MAXNUM],qstring[MAXNUM];
                        /*分别用于存放p和g的祖先*/
       char continueflag;
       int i,findflag;    /*两个祖先均未找到*/
       findflag=0:
       if(t==NULL)return NULL;
       if((st=createEmptyStack())==NULL)return NULL;
       pbnode=t:
       do{
         while(ipbnode!=NULL){
           stnode.ptr=pbnode;
           stnode.tag=1;
           push(st,stnode);
           pbnode=pbnode->llink;
         }
         continueflag='t':
         while((continueflag=='t')&&(!isEmptyStack(st))){
           stnode=pop(st);
           pbnode=stnode.ptr;
           if(stnode.tag==1){
             stnode.tag=2:
             push(st,stnode);
             continueflag='f':
           pbnode==pbnode->rlink;
       }
       else{
         if(pbnode==p){
           for(i=0;i<=st->t;i++)
               pstring[i]=st->s[i].ptr;  /*保存p的祖先*/
           pstring[i]=NULL;
           findflag++;    /*找到一个祖先*/
         }
         if(pbnode==q){
           for(i=0;i<=st->t;i++)
               qstring[i]=st->s[i].ptr;
           qstring[i]=NULL;
           findflag++;    /*找到一个祖先*/
         }
         if(findflag==2){    /*两个祖先均已找到*/
           i=0:
           while((pstring[i]==qstring[i])&&(pstring[i]!=NULL))
               i++:    /*确定最近的公共祖先*/
           if(pstring[i]==NULL){
               free(st);
               return pstring[i-1];
           }
           else{
               free(st);
               return qstring[i-1];
           }
         }
         }
       }
   }while(!isEmptyStack(st));
   return NULL;
   }
   (4)代价分析
   时间代价和后根周游一次二叉树相等,即O(n)。空间代价为O(h),h为二叉树的高度。
【答案解析】