633 PROGRAM ancestor(input,output); {本程序判断结点j 是否是结点i 的子孙}

{假定结点数据是结点编号,否则设结点结构为

{RECORD lch,rch:integer; dada:datatype END;将结点置于向量中}

CONST    n=9;

VAR   L,r,t:ARRAY[1..n] OF integer;

  {L[1..n]R[1..n] 是二叉树的存储结构}

        {L[i]R[i] 分别指示结点i的左孩子和右孩子,0 表示空}

   i,j,k,ll,rr,j1: integer; flag:boolean;

{FUNCTION  f(i,j:integer):integer;

    {这是递归算法, j 是否是i的子孙}

   VAR k:integer;

   BEGIN

     IF NOT flag AND (i<>0)

        THEN IF j=i THEN flag:=true

                    ELSE BEGIN k:=f(L[i],j);

                               IF NOT flag THEN k:=f(r[i],j );

                         END;

   END;

BEGIN

  FOR i:=1 TO n DO read(L[i]);  FOR i:=1 TO n DO read(r[i]);{读入左右子女}

  flag:=false;  read (i,j);

  k:=f(i,j);  {调用递归子程序}

  IF flag THEN writeln(j,’ ’ ,i, ‘的子孙’)

          ELSE writeln(j,’ 不是’ ,i, ‘的子孙’);

END.}

{以下是非递归程序,先由L[1..n]R[1.n] 建立其双亲向量T[1..n]}

BEGIN

   FOR i:=1 TO n DO READ(L[i],r[i]);  FOR i:=1 TO n DO t[i]:=0;

   FOR i:=1 TO n DO {建立其双亲向量}

      BEGIN

       LL:=L[i]; IF LL<>0 THEN t[LL]:=i;

       rr:=r[i]; IF rr<>0 THEN t[rr]:=i;

     END;

      read(i,j); j1:=j;{给定结点j, 其双亲t[j], 直到找到祖先i, 或到根失败}

   WHILE (j<>i) AND (j<>0) DO j:=t[j];

   IF j<>0 THEN writeln(i,'  is ancestor of  ',j1)

           ELSE writeln(i,'  is NOT ancestor of  ',j1);

END.


 

6.37

PROC  preorder(bt:bit;var ss:string);

      {本算法非递归前序遍历二叉树,遍历序列置于ss中,ss初值为空,串联接符用’+’ }

   IF bt<>NIL THEN { 若二叉树为空,则空操作}

      [initstack(s);{栈初始化,栈中元素为二叉树结点指针}

       PUSH(s,bt);

       WHILE NOT empty(s) DO

         [ p:=POP(s);{初退栈}

          ss:=ss+p^.data;

          IF  p^.rchild<>NIL THEN  PUSH(s,p^.rchild); {右子树非空,则右子树进栈}

          IF  p^.lchild<>NIL THEN  PUSH(s,p^.lchild);

         ]

       FOR  i:=1 TO LENGTH(ss)  DO  write(ss[i]:4);]

ENDP

       IF bt<>NIL THEN  {以下为非递归中序遍历算法}

       [ p;=bt,  initstack(s);

        REPEAT

           WHILE  p<>nil  DO  [PUSH(s,p);  p:=p^.lchild ]

            IF NOT EMPTY(s)  THEN

               [p:=POP(s);  ss:=ss+p^.data;  p:=p^.rchild]]

        UNTIL  (p=nil)  AND  EMPTY(s)

       ]

6.38

TYPE bnode=RECORD

             ht:bitree;   tag:  char;{‘l’表示左分支,’r’表示右分支}

            END

PROC  postorder(ht:bitree);

    {本算法非递归遍历二叉树,由于最后访问根结点,必须先把根结点指针进栈,以后序遍}

{历方式,访问完左子树和右子树后,才能将根从栈中退出并访问。为了区分从左子树回}

{来还是从右子树回来,加一标记tag.s存放bnode型元素, qbnode型变量;}

IF ht<>NIL THEN

[initstack(s); p:=ht;{初始化}

     REPEAT

      WHILE p<>nil  DO  [ q.ht:=p; q.tag:=’l’; push(s,q);  p:=p^.lchild]

         {根结点及左子树进栈}

IF  NOT  EMPTY(s) THEN

    [ q:=pop(s);  p:=q.ht;

     IF q.tag=’r’{右子树已遍历,访问根结点}

THEN [write(p^.data);  p:=nil;{不再进左子树} ]

       ELSE[q.tag=’r’; PUSH(s,q); p:=p^.lchild]{右子树根进栈,再去遍历该根的左子树}

    ]

UNTIL  (p=nil)  AND  EMPTY(s)

6.43

PROC  exchange (VAR ht:bitree);

{ht是二叉树的根结点的指针,本算法递归交换二叉树中的所有结点的左右子树}

IF  ht<>nil THEN

     [ p:=ht^.lchild;   ht^.lchild:=ht^.rchild;  ht^.rchild:=p; ] {交换根结点的左右子树}

  IF  ht^.lchild<>nil

THEN  exchange (ht^.lchild); {递归交换左子树中所有结点的左右子树}

  IF  ht^.rchild<>nil

THEN  exchange (ht^.rchild); {递归交换右子树中所有结点的左右子树}

ENDP

6.47

PROC  levelorder (ht:bitree; VAR ss:string);

{本算法按层次遍历二叉树htss 返回遍历序列,串的联接运算用‘+}

IF  ht<>nil  THEN

    [ iniqueue(q);  {处始化队列,队列元素为二叉树节点的指针}

     assign(ss,’’);  {初始化遍历序列,SS为空}

     enqueue(q,ht);  {根节点指针入队列}

     while not empty(q) do

        [ p:=delqueue(q);

         ss:=ss+p^.data;

         IF  p^.lchild<>nil then enqueue(q,p^.lchild);

            {若左子女非空,则左子女入队列}

         IF  p^.rchild<>nil then enqueue(q,p^.rchild)

           {若右子女非空,则右子女入队列}

        ]

 FOR  i:=1 to length(ss)  do  write (ss[i]:4);

]

ENDP;


649

FUNC  completree (ht:bitree):boolean;

{本算法判别二叉树ht是否为完全二叉树,如是,返回TRUE,否则返回FALSE。根据}

{完全二叉树的定义,其叶子节点最多出现在最下两层上,且任何结点左子树高度均与}

{其右子树的高度或者相等,或者多1。本算法仿照层次遍历思想。}

IF ht=nil  THEN  completree:=TRUE

       ELSE [ iniTqueue(q);  enqueue(q,ht);  flag:=true;

             while  not  empty(q)  and  flag  DO

               [ p:=delqueue(q);

                IF p<>NIL THEN [ enqueue(p^.lchild); enqueue(p^.rchild) ]

                          else while not empty(q) AND flag  DO

                               [p:=delqueue(q);  IF q<>NIL THEN flag:=FALSE]

            ]

completree:=flag;

ENDF;

6.54

PROC  BuildBiTree (sa:sqbitree;VAR bt:bitree; i:1..n);

{sa是含有n个结点的完全二叉树的顺序存储结构,bt是由sa建立的以二叉链表表示的}

{二叉树根结点的指针 i为完全二叉树结点在顺序存储中的序号,初始调用时i=1}

 IF I<=sa.last THEN

  [ new(bt); bt^.data:=sa.elem[i];  {建立根结点}

IF  2*i>sa.last  then bt^.lchild:=NIL

               ELSE BuildBiTree (sa, bt^.lchild,2*i) ;  {递归建立左子树}

IF 2*i+1>sa.last  then bt^.rlchild:=NIL

ELSE BuildBiTree (sa,bt^.rlchild,2*I+1) ; {递归建立右子树}

]

ENDP

   {以下是非递归算法,用队列。由此可看出队列和栈可用于同一问题中}

PROC  BuildBiTree (sa:sqbitree;VAR bt:bitree; n:integer);

  IF n=0 THEN bt:=NIL {完全二叉树有0个结点,二叉树为空}

ELSE [INITQUEUE(q); ENQUEUE(q,bt); I:=1;

      WHILE NOE EMPTY(q) DO

         [bt:=DELQUEUE(q);

          new(bt); bt^.data:=sa[I]; bt^.lchild:=NIL; bt^.rchild:=NIL;

          IF  2*i<=n  THEN bt^.lchild:=NIL

ELSE ENQUEUE ( q,bt^.lchild); {为左子女分配空间}

IF 2*i+1<=n THEN bt^.rlchild:=NIL

ELSE ENQUEUE ( q,bt^.rchild); {为右子女分配空间}

          i:=i+1;

         ]

ENDP;


6.65

PROC CreateBiTree(VAR bt:bitree;pre,ino:arr;L1,h1,L2,h2:0..n);

   {本算法由二叉树前序遍历序列和中序遍历序列建立其二叉链表的存储结构.bt是建立}

{的二叉树的根结点的指针.二叉树前序遍历序列和中序遍历序列,分别存于向量pre}

{和向量ino,其下标范围分别是L1..h1L2..h2,初始调用本过程时L1=L2=1;h1=h2=n}

IF L1<=h1 THEN  {二叉树建立尚未完成}

    [ new(bt); bt^.data:=pre[L1];  {前序遍历第一元素肯定是根}

     i:=L2;

     WHILE  ino[i]<>pre[L1] DO  i:=i+1;  {在中序遍历序列中找根}

IF  i=L2  THEN  bt^.lchild=NIL {pre[L1]为根的二叉树无左子树}

ELSE CreateBiTree (bt^.lchild,pre,ino,L1+1,L1+(i-L2),L2,i-1);

     {inoino[L2..i-1]为以pre[L1]为根的二叉树的左子树}

      IF i=h2  THEN  bt^.rchild:=NIL {pre[L1]为根的二叉树无右子树}

        ELSE  CreateBiTree (bt^.rchild,pre,ino,L1+(i-L2)+1,h1,i+1,h2)

           {inoino[i+1..h2]为以pre[L1]为根的二叉树的右子树}

]

ENDP;

6.66

PROC CreateCSTreel (VAR t:CSTree; pt:PTree);

 {t是树的孩子兄弟链表表示法的根结点指针,pt是树的双亲表示法的向量,本算法已知pt,}

{求建立t,,不失一般性,设向量中第一个元素为根,编号为1,其双亲为0,且树至少有一结点。}

new(t); t^.data:=pt[1].data; t^.fch:=nil; t^.nsib:=nil; {建立根结点}

initqueue(q); enqueue(q,t);{树根入队列}

while not empty(q) DO

    [ p:=delqueue(q);

     i:=2;查双亲为p的结点}

WHILE  (i<=n)  DO

    IF  pt[pt[i].parent].data<>p^.data  THEN  i:=i+1

      ELSE {找到p的第一子女,在孩子兄弟链表中建立该结点,并插入队列}

        [ new(p^.lchild); s:=p^.lchild; s ^.data;=pt[I].data;  s ^.fch:=nil; s ^.nsib:=nil;

enqueue(q, s); i:=i+1;

         WHILE I<=n  DO {找结点的p的兄弟}

            IF pt[pt[I].parent].data<>p^.data  THEN  i:=i+1

               ELSE  {找到s的兄弟,建立结点,并入队列}

                  [new(s^.nsib); s ^.fch:= s ^.nsib:=NIL; s ^.data;=pt[i].data; s:= s ^.nsib;

                   Enqueue(q, s) ;

                  ]

        ]

]

ENDP;


6.66_1

PROC  CreatePTree(VAR pt:PTree; t:CSTree);

  {本算法将n个结点的树由孩子兄弟链表表示法,转化为双亲表示法.算法的基}

{本思想是,设孩子兄弟链表t非空,则根结点为双亲表示法pt中第一元素,且无}

{双亲.t入队列,进入循环:删除队头元素,确定其在pt中的下标i,若其有子女}

{则子女依次存入向量pt, 并入队列,其双亲均为i,之后再回到循环开始:出队,…..,}

{直至队列为空.}

initqueue(q);enqueue(q,t);{队列初始化,队列元素为二叉树中结点的指针}

pt[1].data:=t^.data;  pt[1].parent;=0;

k:=1;{k为已转到pt中的结点数}

WHile  not  empty(q)  do

  [ p:=delqueue(q);

  i:=index(p^.data); { index函数查p^.datapt中的位序}

   IF p^.fch<>nil  then {p有子女 }

[s:=p^.fch; pt[k+1].data;=s^.data; pt[k+1].parent;=i; {子女的双亲为p}

 k:=k+1;enqueue(q,s);{pt中元素增1, s入队列}

 s:=s^.nsib;{查第一子女有无兄弟}

 WHILE  s<>nil do  {兄弟的双亲均为i,存入pt,并入队列}

    [ pt[k+1].data:= s^.data; pt[k+1].parent:=I;  k:=k+1;enqueue(q,s);]

     ]

   ]

ENDP;

func index(x:datatype):integer;

  found:=false; j:=1;

  WHILE  (j<=k) AND NOT found DO

     IF  pt[j].data<>x  THEN j:=j+1  ELSE  found:=true;

  INDEX:=j;

ENDF;


 

6.66_2

PROC CreatePTree(VAR pt:Ptree;t:CSTree);

  {本算法同6.66_1,但使用栈.按前序遍历原则}

INITSTACK(S); PUSH(S,t);

pt[1].data:=t^.data;  pt[1].parent:=0;

k:=1;{k为已转到pt中的结点数}

WHILE  NOT  EMPTY(S)  DO

  [p:=POP(S);

REPEAT

   IF p^.nsib<>NIL THEN  PUSHS,p^.nsib;

IF p^.fc<>NIL THEN { 处理左子女}

   [ I:=INDEX(p^.data); {确定p^.data  pt 中的位序}

  p:=p^.fch;  pt[k+1].data:=p^.data;  pt[k+1].parent:=I;  k:=k+1

       ]

      ELSE {处理本结点}

    [ I:=PARENT(p^.data); {确定p^.data     的双亲在pt 中的位序}

   pt[k+1].data:=p^.data;  pt[k+1].parent:=I;  k:=k+1

  ]

UNTIL p^.fch=NIL

   ]

ENDP;

FUNC parent(x:datatype):integer;

found:=false; j:=1;

  WHILE  (j<=k) AND NOT found  DO

     IF  pt[j].data<>x  THEN j:=j+1  ELSE  found:=true;

  parent:=pt[j].parentj;

ENDF;