数据结构复习2:树的算法实现常考点

算法实现方面要求,

1,熟练掌握二叉树的递归和非递归遍历

递归遍历

void preorder(BiTnode *p)

{ if (p!=NULL)

   { printf ("%6c",p->data); /*访问根结点*/

      preorder(p->lchild);  

/*按先根次序遍历左子树*/

      preorder(p->rchild);  

/*按先根次序遍历右子树*/

    }

 }/* preorder  */



void  inorder( BiTnode  *p)

{  if (p!=NULL)

  { inorder(p->lchild);    

/*中根遍历左子树*/

     printf("%6c",P->data);

/*访问根结束*/

     inorder(p->rchild);    

/*中根遍历右子树*/

    }

 }/* inorder */



Void postorder( BiTnode *p)

{ if (p!=NULL)

   { postorder(p->lchild);   

/*后根遍历左子树*/

      postorder(p->rchild);  

/*后根遍历右子树*/

      printf("%6c",p->data);

/*访问根结点*/

    }

 }  /* postorder  */



非递归遍历

void preOrder(TreeNode t) {  //先序遍历

     Stack<TreeNode> s = new Stack<>();

        while(t != null || !s.isEmpty()) {

            while(t != null) {

                printf(t.val);  

//第一次碰到就访问结点

                s.push(t);                

//压栈保存,左边访问完了再访问右节点

                t = t.left;

            }

            if(!s.isEmpty()) {

                t = s.pop();

                t = t.right;      

//当上述循环推出,说明左子树全访问完了,

则把父结点弹出,准备访问右子树            

}

        }

    }



 void inOrder(TreeNode t) {  

//中序,与先序很像,只是在第二次碰到结点才访问

        Stack<TreeNode> s = new Stack<>();

        while(t != null || !s.isEmpty()) {

            while(t != null) {

                s.push(t);      

//第一次碰到不访问,只保存

                t = t.left;

            }

            if(!s.isEmpty()) {

                t = s.pop();

                printf(t.val);    

//左子树访问完了,弹出父结点,第二次碰到则访问

                t = t.right;           

 //准备访问右子树            

}

        }

    }





  void lastOrder(TreeNode t) {  //后序与上述两种方式有区别,只有左右结点都被访问,当前结点才能被访问

        TreeNode preNode = null;         //记录上一次访问结点

        Stack<TreeNode> s = new Stack<>();

        s.push(t);    //压入根节点,这货铁定最后访问,万年栈底元素

        while(!s.isEmpty()) {

            TreeNode current = s.peek(); //获取栈顶元素

 //当前结点左右结点均为空,或左右结点不都为空但已经都被访问则当前结点可以访问了

(即上次访问结点preNode == 左/右结点)

 //由于压栈顺序是先右后左,所以当前结点的孩子们访问时必然是先左后右. preNode == left说明当前结点只有左孩子且已被访问,==right说明有两个孩子且左右均已访问

            if((current.left==null&¤t.right==null)||(preNode!=null&&(preNode==current.left||preNode==current.right))){

                System.out.println(current.val);

                s.pop();  

                preNode = current;  

//每访问一个结点都记录一下,以便下次判断结点的左右孩子是否已被访问           

 }

else if(current.right != null)  

//若不满足上述条件,则把当前结点的孩子以先右后左的顺序压栈,这样访问时就是先左后右了                 s.push(current.right);

else if(current.left != null)

            s.push(current.left);

        }

    }

 

2,解决实际问题

1)计算树的层数/深度/树高

int  Depth(BiTree *t)

{ //*t为指向二叉树根结点的的指针

if(t=NULL)  ruturn (0); //若树为空,则高度为0

else

  { hl=depth(t->lchild);       //求左子树高度

    hr=depth(t->rchild);        //求右子树高度

    if(hl>hr)       //树高为左右子树高度大者加1

         return(hl+1);

    else

         return(hr+1);

   }//else

 }//PreTreeDepth

2)节点的度/节点的分叉数   

变相求一个父节点的节点个数。同3)

3)查找满足条件的节点/叶子节点的个数

Void injishu( BiTnode *t)

{ if (t!=NULL)

   { injishu(t->lchild);      /*中根遍历左子树*/

      printf("%6c",t->data);      /*访问根结点*/

      m++;                  /*结点计数,m为全局变量*/

      if((t->lchild==NULL)&&(t->rchild==NULL))

           n0++;/*叶结点计数*/

      injishu(t->rchild);         /*中根遍历右子树*/

     }

 } /* injishu  */

发布了38 篇原创文章 · 获赞 20 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_40165004/article/details/103072121