二叉樹的幾個相關算法


#include "stdafx.h"
#include<string>
#include<iostream>
#define ERROR  0
#define OK  1
#define queuesize 20

using namespace std;

typedef struct BiTNode{
    int data;
    struct BiTNode *lchild,*rchild; 
}BiTNode,*BiTree;

typedef struct Queue{
     int front ,rear ;
     BiTree data[queuesize];
     int count;
}Queue;


/*======================================*\
|建立二叉樹
|@date 2012/11/27
\*======================================*/
//先序建立二叉樹
int create_BiTree(BiTree &T)
{		
	int ch;
	cout<<"請輸入一個根結點的值(如果爲空,則輸入0)\n";
	cin>>ch;
	if (ch==0) T= NULL;
	else 
	{
		T=new BiTNode;
		if (T== NULL)  return ERROR;
		T->data = ch; 
		create_BiTree(T->lchild);   // 構造左子樹
		create_BiTree(T->rchild);   // 構造右子樹
	}
	 return OK;
}

/*=========================================*\
|三種遍歷
|@author LiMing
|@date   2012/11/27
\*=========================================*/
int pre_order_traverse(BiTree T) //先序遍歷
{
    if(T!=NULL)
    {
        cout<<T->data<<" ";
        pre_order_traverse(T->lchild);
        pre_order_traverse(T->rchild);
    }
    return OK;
}
int in_order_traverse(BiTree T)//中序遍歷
{
    if(T!=NULL)
    {
        in_order_traverse(T->lchild);
        cout<<T->data<<" ";
        in_order_traverse(T->rchild);
    }
    return OK;
}
int past_order_traverse(BiTree T)//後序遍歷
{
	if(T!=NULL)
	{
		past_order_traverse(T->lchild);
		past_order_traverse(T->rchild);
		cout<<T->data<<"";
	}
	return OK;
}

/*===================================*\
|非遞歸遍歷
\*===================================*/
int pre_order_traverse2(BiTree T)  
{
   BiTree p,s[20];
   int top=0;
   p=T;
   while((p!=NULL)||(top>0))
   {
       while(p!=NULL)
       {
          cout<<p->data<<" ";
           s[++top]=p;
           p=p->lchild;
       }
       p=s[top--];
       p=p->rchild;
   }
   return OK;
}

int pre_order_traverse3(BiTree T) 
{
	BiTree p,stack[20];
	p=T;
	int top=-1;
	for(;;)
	{
		for(;p;p=p->lchild)
		{
			cout<<p->data<<"";
			stack[++top]=p;
		}
		if(top==-1)break;
		p=stack[top--];
		p=p->rchild;
	}
	return OK;
}

int in_order_traverse2(BiTree T)
{
	BiTree p, stack[20];
	p=T;
	int top=-1;
	for(;;)
	{
		for(;p;p=p->lchild)
			stack[++top]=p;	
		if(top==-1)break;	
		p=stack[top--];
		cout<<p->data<<" ";
		p=p->rchild;
	}
	return OK;
}

//非遞歸後序遍歷
int PastOrderTraverse2(BiTree T) 
{
	//此處省略一萬字啊啊啊,一般不用
	return 0;
}

/*======================================*\
|層次遍歷法1
|@author LiMing
|@date 2012/11/28
\*======================================*/
int level_order_traverse1(BiTree T)
{    Queue *q;
     BiTree p;
     int flag=0;				 //定義flag爲層號
	 q=new Queue;				 //申請循環隊列空間
     q->rear=q->front=q->count=0;		 //將循環隊列初始化爲空
     q->data[q->rear]=T;
     q->count++;
     q->rear=(q->rear+1)%queuesize;		 //將根結點入隊
     while (q->count)				 //若隊列不爲空,做以下操作
         if(q->data[q->front]){			 //當隊首元素不爲空指針,做以下操作
             p=q->data[q->front];                //取隊首元素*p
             cout<<p->data<<endl;                //打印*p結點的數據域信息
             ++flag;
             q->front=(q->front+1)%queuesize;
             q->count--;                         //隊首元素出隊
             if (q->count==queuesize)            //若隊列爲隊滿,則打印隊滿信息,退出程序的執行
                 cout<<"the queue full!\n";
             else{                               //若隊列不滿,將*p結點的左孩子指針入隊
                 q->count++;q->data[q->rear]=p->lchild;
                 q->rear=(q->rear+1)%queuesize;
             }                                   //enf of if
             if (q->count==queuesize)            //若隊列爲隊滿,則打印隊滿信息,退出程序的執行
                 cout<<"the queue full!\n";
             else{                               //若隊列不滿,將*p結點的右孩子指針入隊
                 q->count++;q->data[q->rear]=p->rchild;
                 q->rear=(q->rear+1)%queuesize;
             }                                   //end of if
         }                                       //end of if
         else{                                   //當隊首元素爲空指針,將空指針出隊
             q->front=(q->front+1)%queuesize;
             q->count--;
         }
         cout<<endl;
         return OK;
}      //end of LevelOrder
/*======================================*\
|層次遍歷法2
|@author LiMing
|@date 2012/11/29
\*======================================*/
int level_order_traverse2(BiTree T)
{
	Queue *temp;
	BiTree p;
	temp=new Queue;
	p=T;
	if(!temp) return 0;
	else
	{
		temp->count=0;
		temp->front=-1;
		temp->rear =-1;
	}
	temp->data[++temp->rear]=p;
	temp->count++;
	for(;temp->count;)
	{
		cout<<temp->data[++temp->front]->data<<" ";
		temp->count--;
		if(temp->data[temp->front]->lchild)
		{
			temp->data[++temp->rear]=temp->data[temp->front]->lchild;
			temp->count++;
		}
		if(temp->data[temp->front]->rchild)
		{
			temp->data[++temp->rear]=temp->data[temp->front]->rchild;
			temp->count++;
		}
	}
	return 1;
}


/*===========================================*\
|與二叉樹的性質有關的幾種算法
|@author LiMinng
|@date 2012/11/28
\*===========================================*/

/**
*遞歸是不好實現的
*採用輔助棧的形式
*利用先序遍歷的思想
*/

int get_all_node(BiTree T) 
{
   BiTree p,s[20];
   int num_node=0;
   int top=0;
   p=T;
   while((p!=NULL)||(top>0))
   {
       while(p!=NULL)
       {
           num_node++;
           s[++top]=p;
           p=p->lchild;
       }
       p=s[top--];
       p=p->rchild;
   }
   return num_node;
}
/**
*循環體部分化爲for()循環後
for(;;)
{
	for(;p;p=p->lchild)
	{
		num_node++;
        s[++top]=p;
	}
	if(top==0) break;
	 p=s[top--];
     p=p->rchild;
}
*/

/**
*利用遞歸算法得到度爲0的結點的個數
*不容易理解 效率也不高
*/

int get_node0_1(BiTree T)//
{
    int num1,num2;
    if(T==NULL)
        return 0;
    else
    {
        if((T->lchild==NULL)&&(T->rchild==NULL))
            return 1;
        else
        {
            num1=get_node0_1(T->lchild);
            num2=get_node0_1(T->rchild);
            return (num1+num2);
        }
    }
}
/**
*利用非遞歸算法得到度爲0的結點的個數
*容易理解 效率高
*/

int get_node0_2(BiTree T) 
{
    int num=0;
    BiTree p=T,s[20];
    int top=0;    
    while((p!=NULL)||(top>0))
    {
        while(p!=NULL)
        {
            s[++top]=p;
            p=p->lchild;
        }
		p=s[--top];
		if(p->rchild==NULL)
		{
			 ++num;
		}
		else
		 p=p->rchild;
    }
    return num;
}

int get_node1(BiTree T) //利用總的關係求出度爲1的結點的個數
{
    int num=get_all_node(T)-2*get_node0_1(T)+1;
    return num;
}
int get_node1_1(BiTree T)   //非遞歸算法,同時利用關係求度爲1的結點。
{
    int num=get_all_node(T)-2*get_node0_2(T)+1;
    return num;
}
int get_node2(BiTree T) //利用度爲2的結點個數與度爲0的結點個數的關係得到
{
    int num=get_node0_1(T)-1;
    return num;
}
int get_node2_1(BiTree T)   //非遞歸算法,同時利用關係求度爲2的結點。
{
    int num=get_node0_2(T)-1;
    return num;
}
int get_node(BiTree T)
{
   int get;
   cout<<"請輸入你要查找的結點的度\n"<<endl;
   cout<<"1.查詢度爲0的所有結點的個數\n"<<endl;
   cout<<"2.查詢度爲1的所有結點的個數\n"<<endl;
   cout<<"3.查詢度爲2的所有結點的個數\n"<<endl;
   cin>>get;
   switch(get){
   case 1:
      cout<<"度爲0的所有結點的個數是%d\n"<<get_node0_1(T)<<endl;
      break;
   case 2:
       cout<<"度爲1的所有結點的個數是%d\n"<<get_node1(T)<<endl;
       break;
   case 3:
       cout<<"度爲2的所有結點的個數是%d\n"<<get_node2(T)<<endl;
       break;
   }
   return OK;
}
int get_node_1(BiTree T)        //利用非遞歸算法的實現
{
   int get;
   cout<<"下面是用非遞歸算法來查詢\n"<<endl;
   cout<<"請輸入你要查找的結點的度\n"<<endl;
   cout<<"1.查詢度爲0的所有結點的個數\n"<<endl;
   cout<<"2.查詢度爲1的所有結點的個數\n"<<endl;
   cout<<"3.查詢度爲2的所有結點的個數\n"<<endl;
   cin>>get;
   switch(get){
   case 1:
      cout<<"度爲0的所有結點的個數是%d\n"<<get_node0_2(T)<<endl;
      break;
   case 2:
       cout<<"度爲1的所有結點的個數是%d\n"<<get_node1_1(T)<<endl;
       break;
   case 3:
       cout<<"度爲2的所有結點的個數是%d\n"<<get_node2_1(T)<<endl;
       break;
   }
   return OK;
}


/**
*求樹的深度
*/
int height(BiTree T)
{
    BiTree p=T;
    int a,b;
    if(p==NULL)
        return 0;
    else{
       if((p->lchild==NULL)&&(p->rchild==NULL))
            return 1;
		else{
				a=height(p->rchild);
				b=height(p->lchild);
				if(a>b)  
					return (a+1);
				else   
					return (b+1);
			}
		}
}

/**
*採用遞歸算法來實現判斷是否爲完全二叉樹
*/
int judge(BiTree T)   
{
      if(T ==NULL) 
          return   0; 
      if(T->lchild == NULL && T->rchild== NULL) 
          return   1;  
      if(T->lchild  == NULL  && T->rchild != NULL||T->lchild!=NULL &&T->rchild==NULL) 
          return   0; 
      return   judge(T->lchild) & judge(T->rchild); 

}

int exchange(BiTree T)
{
     BiTree p=T;
     int exch;
     if(p==NULL)
         return OK;
     else
     {
         if(p->lchild!=NULL && p->rchild!=NULL)
         {
             exch=p->lchild->data;
             p->lchild->data=p->rchild->data;
             p->rchild->data=exch;
             exchange(p->lchild);
             exchange(p->rchild);
         }
         else
         {
             if(p->lchild==NULL)
                 exchange(p->rchild);
             else
                 exchange(p->lchild);
         }
         return OK;
     }
}

void main()
{
	BiTree T=new BiTNode;         //定義一個指向BiTNode結點的指針
    int choice;
    do{
    cout<<"\n";
    cout<<"請選擇操作:\n";
    cout<<"1.按照先序的次序生成一顆二叉樹\n";
    cout<<"2.遞歸算法實現二叉樹的先序遍歷,輸出各結點值\n";
    cout<<"3.用非遞歸算法實現二叉樹的遍歷,輸出各結點值\n";
    cout<<"4.求度分別爲0、1、2的結點的數目(遞歸算法實現)\n";
    cout<<"5.求度分別爲0、1、2的結點的數目(非遞歸算法實現)\n";
    cout<<"6.按層次遍歷二叉樹\n";
    cout<<"7.求二叉樹的高度(深度)\n";
    cout<<"8.判斷是否爲完全二叉樹,輸出\"Yes!\"或\"No!\"\n";
    cout<<"9.交換每個結點的左右子樹\n";
    cout<<"10.對交換左右子樹後的二叉樹作中序遍歷\n";
    cout<<"11.退出\n";
    cin>>choice;
    switch(choice)
	{
		case 1:
			 create_BiTree(T);   
			 break;
		case 2:
			 pre_order_traverse3(T); 
			 break;
		case 3:
			in_order_traverse2(T);
			 break;
		case 4:
			 get_node(T); 
			 break;
		case 5:
			 get_node_1(T);  
			 break;
		case 6:
			level_order_traverse2(T);
		    break;
		case 7:
			 cout<<"二叉樹的高度爲%d\n"<<height(T)<<endl;
			 break;
		case 8:
			if(judge(T)==0)
				cout<<"No\n"<<endl;
			 else
				cout<<"Yes\n"<<endl;
			 break;
		case 9:
			exchange(T);
			break;
		case 10:
			in_order_traverse(T);
			break;
	 }   
    }while(choice!=11);   
}

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