數據結構實驗 二叉樹實驗(括號表示法的合法性檢查)

數據結構實驗課之二叉樹實驗(一)

該博客待完善,編者目前爲大二學生水平較差,內容僅供參考

實驗內容:

以括號表示法作爲輸入字符串構造一棵二叉樹,完成下列實驗要求:

(1)如果輸入字符串不符合規範,顯示錯誤信息:“輸入錯誤”。

(2)分別顯示該二叉樹的先序、中序和後序遍歷。

(3)求出該二叉樹的高度。

(4)輸出該二叉樹所有的葉子結點。

(5)找出二叉樹中的最大、最小值結點,並寫出他們的所在層數

 

令人心碎,其中(2)(3)(4)(5)教材上都有對應類似代碼實現起來並不難,個人覺得難點主要在(1)中檢查輸入是否合法,即括號表示法合法性檢查這一塊內容。

我一共想到了以下幾種非法輸入(因個人能力有限,肯定還有沒想到的點,希望大家能指正包含)。

1.一對括號中逗號數超過兩個,例如A(B,C,D) ,非法

2. 形如 (B,C) 即在第一個左括號前少一個字符,非法

3.形如AA(B,C) ,即數據超過一個字符,非法。  注:本例中我默認數據元素只有一個字符

4.形如 A())   A)))(((   ,類似左右括號不匹配,非法。

5.形如A(B,C)D ,類似錯誤

實現代碼如下

#include<bits/stdc++.h>
#define Max 100000 
using namespace std;
char Tmax;//最大值節點
char Tmin;//最小值節點 
int k1,k2;
struct node
{
	char data;
	node * lchild;
	node * rchild;
};

bool CreateBTree(node * &b,string str)
{
	stack<char>q; //判斷輸入合法性用的棧 
	bool flag=true;//是否合法標記 
	//bool zm=true;// 輸入節點名之後一定要跟一個左括號  如:AA非法 
	//bool jm=false;//在左括號前是否缺少節點元素判斷  如:(A,B) 非法 。false表示還未輸入數據元素,true表示已輸入節點元素 
	node *St[Max],*p;
	int top=-1,k,j=0;
	int Dnum=0;//逗號數量 
	char ch;
	b=NULL;
	ch=str[j];
	while(ch!='\0' && flag)
	{
		switch(ch)
		{
			case '(':
				//if(!jm)flag=false; 
				//jm=false;//輸入左括號後一定要跟一個節點元素  A(B,C)
				if(q.empty()){cout<<"左括號前缺少數據元素"<<endl;flag=false;break;}//如果棧爲空,即左括號前沒有數據元素時,非法輸入				 
				top++;
				St[top]=p;
				k=1;
				q.push(ch);
				Dnum=0;//輸入右括號後逗號數初始化0 
				break;
			case ')':
				//cout<<"test1"<<endl;
				//if(q.empty())cout<<'1'<<endl;
				top--;
				while(!q.empty() && q.top()!='(')
				{
					if(q.top()==',' && Dnum>0)Dnum--; 
					q.pop();
				}	
				if(q.empty())    //在獲取棧頂元素前一定要判斷棧是否爲空,如果爲空強行獲取棧頂元素程序會報錯 
				{
					flag=false;
					cout<<"左右括號不匹配"<<endl; 
					break;	
				} 
				else if(q.top()=='(')
				{
					q.pop();
				}
				break;
			case ',':
				k=2;
				Dnum++;
				q.push(ch);
				if(Dnum>=2)
				{
					flag=false;
					cout<<"逗號數量大於1個"<<endl;
				}
				break;
			default:  
					p=new node;
					p->data=ch;
					p->lchild=p->rchild=NULL;
					if(q.empty() ||  q.top()=='(' || q.top()==','||ch==',')//如果棧爲空或者棧頂元素爲'('將數據元素入棧 
					{
						q.push(ch);
					}
					else //否則非法 
					{
						flag=false;
						cout<<"數據元素輸入過多(數據元素只允許一個字符)或某數據元素前一個字符不是左括號"<<endl;
						//cout<<"test4"<<endl;
						//cout<<q.top()<<endl;//test
						//cout<<ch<<endl;//test 
						break;
					}
					if(b==NULL)
						b=p;
					else
					{
						switch(k)
						{
								case 1:St[top]->lchild=p;break;
								case 2:St[top]->rchild=p;break;
						}
					}
		}
		
		if(flag==false)
		{
			//cout<<"輸入不合法,括號失配"<<endl;
			return flag;
		}
		j++;
		ch=str[j];
					
	}
	if(q.size()!=1)
	{
		flag=false;
		cout<<"棧剩餘元素大於1,左右括號匹配失敗或其他未滿足格式情況"<<endl; 
		//int tmp=q.size(); test
		//cout<<tmp<<endl;
	}
	return flag;
}

void PreOrder(node *b)//先序遍歷 
{
	if(b!=NULL)
	{
		cout<<b->data<<' ';
		PreOrder(b->lchild);
		PreOrder(b->rchild);
	}
}

void InOrder(node *b)//中序遍歷 
{
	if(b!=NULL)
	{
		InOrder(b->lchild);
		cout<<b->data<<' ';
		InOrder(b->rchild);
	
	}
}

void PostOrder(node *b)//後序遍歷 
{
	if(b!=NULL)
	{
		PostOrder(b->lchild);
		PostOrder(b->rchild);
		cout<<b->data<<' ';
	}
}

int BTHeight(node *b)//獲得樹高度的函數 
{
	int lchildh,rchildh;
	if(b==NULL)return 0;
	else
	{
		lchildh=BTHeight(b->lchild);
		rchildh=BTHeight(b->rchild);
		return (lchildh>rchildh)?(lchildh+1):(rchildh+1);
	}
}

void Dischild(node *b)//輸出葉子節點 
{
	if(b!=NULL)
	{
		if(b->lchild==NULL && b->rchild ==NULL)
			cout<<b->data<<' ';
		Dischild(b->lchild);
		Dischild(b->rchild);	
	}
}

void getMaxMin(node *b,int k)
{
	if(b==NULL)  //空樹直接返回 
		return ;
	else
	{
		char temp=b->data ;
		k++;
		if(temp>Tmax){Tmax=temp;k1=k;}
		if(temp<Tmin){Tmin=temp;k2=k;}
		getMaxMin(b->lchild ,k);
		getMaxMin(b->rchild ,k);
	} 
	
}

int main()
{
	string s;
	bool flag;
	node *b;
	cin>>s; 
	while(!CreateBTree(b,s))
	{
		cout<<"輸入錯誤"<<endl;
		cout<<endl; 
		flag=true;//合法標記重置 
		b=NULL;//指針重置 
		cin>>s;//重新輸入括號表達式 
	}
	int height=BTHeight(b);
	
	cout<<"先序遍歷:"<<endl; 
	PreOrder(b);
	cout<<endl;
	 
	cout<<"中序遍歷:"<<endl;
	InOrder(b);
	cout<<endl;
	
	cout<<"後序遍歷:"<<endl;
	PostOrder(b);
	cout<<endl;
	 
	cout<<"二叉樹的高度爲:"<<height<<endl;
	cout<<"二叉樹的葉子節點爲:";
	Dischild(b);
	cout<<endl;
	
	Tmax='0';
	Tmin='z'+1;
	getMaxMin(b,0);

	cout<<"最大值節點爲:"<<Tmax<<" 其所在層數爲:"<<k1<<endl;
	cout<<"最小值節點爲:"<<Tmin<<" 其所在層數爲:"<<k2<<endl;
		
	return 0;
}

測試結果圖片

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