數據結構複習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  */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章