数据结构实验一:树形结构

数据结构课实验一:树形结构

实验内容
树型结构的遍历是树型结构算法的基础,本实验要求编写程序演示二叉树的存储结构的建立方法和遍历过程。

  1. 编写建立二叉树的二叉链表存储结构(左右链表示)的程序,并以适当的形式显示和保存二叉树;
  2. 采用二叉树的二叉链表存储结构,编写程序实现二叉树的先序、中序和后序遍历的递归和非递归算法以及层序遍历算法,并以适当的形式显示和保存二叉树及其相应的遍历序列;
  3. 给定一个二叉树, 编写算法完成下列应用:(二选一)
    a) 判断其是否为完全二叉树;
    b) 求二叉树中任意两个结点的公共祖先。
#include<cstdio>
#include<iostream>
using namespace std;
int height=-1;//树的层高 
struct node
{
	node *lchild,*rchild;
    char data;
    bool Isfirst=true;
};
typedef node *BTREE;
//栈的型 
struct node1
{
	BTREE stackval;
	node1 *next;
};
typedef node1 * STACK;
//队列的型
struct celltype
{
	BTREE queueval;
	celltype *next;
};
struct QUEUE
{
 	celltype *front;
 	celltype *rear;
};
bool IsEmpty(BTREE &T)
{
	if (!T)
	  return true;//空 
	else return false;
 } 
/*BTREE CreatBT(int v,BTREE ltree,BTREE rtree)
{
	BTREE root=new node;
	root->data=v;
	root->lchild=ltree;
	root->rchild=rtree;
	return root;
}*/ 
//栈的基本操作 
void MakeNull(STACK &S)
{
	S=new node1;
	S->next=NULL;
}
BTREE Top(STACK S)
{
	if (S->next)
			return (S->next->stackval);
	else return NULL;///
}
void Pop(STACK &S)
{
	STACK STK;
	if (S->next)
	{
		STK=S->next;
		S->next=STK->next;
		delete STK;
	}
}
void Push(BTREE x,STACK S)
{
	STACK STK;
	STK=new node1;
	STK->stackval=x;
	STK->next=S->next;
	S->next=STK;
}
bool Empty(STACK S)
{
	if(S->next)
			return false;
	else return true;
}
//队列的基本操作
void MakeNullQueue(QUEUE &Q)
{
	Q.front=new celltype;
	Q.front->next=NULL;
	Q.rear=Q.front;
} 
BTREE Front(QUEUE Q) 
{
	if(Q.front->next)
			return Q.front->next->queueval;
	else 
		return NULL; //
}
void EnQueue(BTREE x,QUEUE &Q)
{
	Q.rear->next=new celltype;
	Q.rear=Q.rear->next;
	Q.rear->queueval=x;
	Q.rear->next=NULL;
}
bool EmptyQ(QUEUE Q)
{
	if (Q.front==Q.rear)
			return true;
	else 
			return false;
}
void DeQueue(QUEUE &Q)
{
	celltype *tmp;
	if (EmptyQ(Q))
			cout<<"Queue is Empty!"<<endl;
	else 
	{
		tmp=Q.front->next;
		Q.front->next=tmp->next;
		delete tmp;
		if (Q.front->next==NULL)
				Q.rear=Q.front;
	}
}
//构造一棵二叉树 
void DevelopBT(BTREE &BT,int h)
{
	char ch;
	cin>>ch;
		if (ch=='#')BT=NULL;
		else 
		{
			BT=new node;
			if (BT==NULL){printf("没有足够的内存!");exit(0);}
			BT->data=ch;
			DevelopBT(BT->lchild,h+1);
			DevelopBT(BT->rchild,h+1);
		}
	if(h>height)height=h;	
}
//前序遍历二叉树-递归 
void Preorder(BTREE &T)
{
	if (T==NULL)return ;
	cout<<T->data<<" ";
	Preorder(T->lchild);
	Preorder(T->rchild);
} 
//非递归- 先输出根节点,再将此时的右节点入栈,先遍历左节点后再让右节点出栈 
void NPreorder(BTREE &T)
{
	STACK S; BTREE BT;
	MakeNull(S);
	BT=T;
	while(!IsEmpty(BT)||!Empty(S))
	if (!IsEmpty(BT))
	{
		cout<<BT->data<<" ";
     if (BT->rchild)	
	 	Push(BT->rchild,S);
		BT=BT->lchild;
	}
	else 
	{
		BT=Top(S);Pop(S);
	}
} 
//中序遍历二叉树-递归 
void Inorder(BTREE &T)
{
	if (T==NULL)return ;
	Inorder(T->lchild);
	cout<<T->data<<" ";
	Inorder(T->rchild);
}
//非递归-先入栈,递归遍历左孩子后将根节点出栈,递归遍历右节点 
void NInorder(BTREE &T)
{
	STACK S; BTREE BT;
	MakeNull(S);
	BT=T;
	while(!IsEmpty(BT)||!Empty(S))
	if (!IsEmpty(BT))
	{
		Push(BT,S);
		BT=BT->lchild;
	}
	else 
	{
		BT=Top(S);Pop(S);
		cout<<BT->data<<" ";
		BT=BT->rchild;
	}
} 
//后序遍历二叉树-递归 
void Postorder(BTREE &T)
{
	if (T==NULL)return ;
	Postorder(T->lchild);
	Postorder(T->rchild);
	cout<<T->data<<" ";
} 

//非递归-第二次到栈口时才能出栈 
void NPostorder(BTREE &T)
{
	STACK S; BTREE BT;
	MakeNull(S);
	BT=T;
	while(!IsEmpty(BT)||!Empty(S))
	if (!IsEmpty(BT))
	{
		Push(BT,S);
		BT=BT->lchild;
	}
	else 
	{
		BT=Top(S);Pop(S);
		if (BT->Isfirst)
		{
			BT->Isfirst=false;
			Push(BT,S);
			BT=BT->rchild;
		}
		else
		{
			
		    cout<<BT->data<<" ";
		    BT=NULL;
		}
		
	}
}
//层序遍历,利用队列、
 
void  Levelorder(BTREE &T)
{
	QUEUE Q;BTREE BT;
	MakeNullQueue(Q);
	BT=T;
	EnQueue(BT,Q);
	do
	{
		if (EmptyQ(Q))break;
		BT=Front(Q);DeQueue(Q);
		cout<<BT->data<<" ";
		if (BT->lchild) 	
			EnQueue(BT->lchild,Q);
		if (BT->rchild) 	
			EnQueue(BT->rchild,Q);
	
	}while(1);
	 
} 
//判断是否为完全二叉树
/* 层序遍历先找到第一个不完全结点
	如果该不完全结点没有左子树只有右子树那么一定不是完全二叉树,否则需进一步判断
	在找到第一个不完全结点的前提下,如果之后的结点仍有左右子树则不是完全二叉树 
*/ 
bool Fully(BTREE &T)
{
	int Unfully=0;
	QUEUE Q;BTREE BT;
	MakeNullQueue(Q);
	BT=T;
	EnQueue(BT,Q);
	do
	{
		if (EmptyQ(Q))break;
		BT=Front(Q);DeQueue(Q);
		switch(Unfully)
			{
				case 0:
				{
					if (BT->lchild) 	
							EnQueue(BT->lchild,Q);
					else{	Unfully=1;EnQueue(BT->lchild,Q);}
						
						
					if (BT->rchild&&!BT->lchild) return false; 	
					else if (BT->rchild&&BT->lchild)
								EnQueue(BT->rchild,Q);
					else{	Unfully=1;EnQueue(BT->lchild,Q);}
				}
					break;
				case 1:
				{
					if (BT->lchild||BT->rchild)return false;
				}
					
			}
		
	
	}while(1);
} 
//寻找两个结点的最近公共祖先
/*
	把两个结点的所有祖先按从最年轻(自己)到最老(根节点)的顺序存储 
	设定两个指针一开始均指向根节点 
	当两节点指向不同的祖先时,上一个相同的结点即为最近的公共祖先 
*/ 
int flag=0;
char firstch[10001],secondch[10001];
// 把两个结点的所有祖先按从最年轻(自己)到最老(根节点)的顺序存储 
int Getancestor(BTREE &T,char ch,char cch[],int cnt)
{
	
	if (!T)return cnt;
	if (T->data==ch) {cch[++cnt]=T->data;flag=1;return cnt;}
	
	
	if (!flag)cnt=Getancestor(T->lchild,ch,cch,cnt);
	if (!flag)cnt=Getancestor(T->rchild,ch,cch,cnt);
	
	if (flag){cch[++cnt]=T->data;return cnt;}
	return cnt;
	 
}
//寻找最近公共祖先的主体部分 
void Ancestor(BTREE &T)    
{
	char ch1,ch2;
	cout<<"请输入要查找的两个结点!\n";
	cin>>ch1>>ch2;
	int cnt1=-1,cnt2=-1;
	cnt1=Getancestor(T,ch1,firstch,0);
	flag=0;
	cnt2=Getancestor(T,ch2,secondch,0);
	
	while(cnt1&&cnt2)
	{
		if(firstch[cnt1]==secondch[cnt2]){cnt1--;cnt2--;}
		else break;
	}
	
	cout<<endl<<ch1<<"和"<<ch2<<"最近的公共祖先为"<<firstch[++cnt1]<<endl;
	return ;
	
} 
//菜单栏 
void Menu(BTREE &T)
{
	cout<<"菜单:\n1、前序遍历(递归)\n2、前序遍历(非递归)\n3、中序遍历(递归)\n4、中序遍历(非递归)\n5、后序遍历(递归)\n6、后序遍历(非递归)\n";
	cout<<"7、层序遍历\n8、判断这棵树是否为完全二叉树\n9、求两个结点的最近的公共祖先\n10、退出程序\n"; 
	cout<<"请键入需要进行的操作的序号:\n"; 
	int x;
	while(1)
	{
		cin>>x;
		cout<<endl;
		switch(x)
		{
			case 1: Preorder(T);
				break;
			case 2: NPreorder(T);
				break;
			case 3: Inorder(T);
				break;
			case 4: NInorder(T);
				break;
			case 5:Postorder(T);
				break;
			case 6:NPostorder(T);
				break;
			case 7:Levelorder(T);
				break;
			case 8:
			{
				bool t= Fully(T);
				if (t)cout<<"此树是完全二叉树!\n";
				else cout<< "此树不是完全二叉树!\n";
			}
				break;
			case 9: Ancestor(T);
				break;
			case 10:
				return ;
		}
	}
	
}
int main()
{
	freopen("1.in","r",stdin);
	 node* root;
	 cout<<"请以前序遍历读入二叉树,用#表示二叉树每个结点的空子树";
     DevelopBT(root,1); 
     Menu(root);
     return 0;
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值