数据结构《二叉树典型算法实现》课程设计

主要功能:输出二叉树、计算二叉树高度、查找节点是否存在、输出所有叶子结点、计算叶子节点个数、前序遍历输出二叉树、中序遍历输出二叉树 、后序遍历输出二叉树、计算结点个数、输出该树中结点最大值 、输出树中结点值为x的层、输出左右孩子结点值 、计算二叉树的各层的宽度、计算指定结点所在的层次、销毁释放二叉树 、先序非递归算法 、中序非递归算法 、后序非递归算法 、层次遍历(队列)算法

#include <fstream>
#include<iostream>
#include<stdlib.h>
#define MaxSize 100
using namespace std;
typedef char ElemType; 
typedef struct node{
ElemType data;
struct node *lchild,*rchild;//二叉树结构声明 
}BTNode;

typedef struct 
{	BTNode *data[100];			//存放栈中的数据元素
	int top;						//存放栈顶指针,即栈顶元素在data数组中的下标
} SqStack;

typedef struct
{
	BTNode *data[MaxSize];//存放队中元素
	int front,rear;//队头队尾指针 
}SqQueue; 

int width[10] = {0}; //存放各层宽度的数组
void TreeWidth(BTNode *b){
	int depth = 0; //遍历的层
    if (b== NULL){
        return;
    }
    if (depth == 0) {
        width[0] = 1;
    }
    if (b->lchild!= NULL) {
        width[++depth] ++;
        printf("往左子树,当前在第%d层,当前计算的宽度为%d\n",depth,width[depth]);
        TreeWidth(b->lchild);
    }
    if (b->rchild!= NULL) {
        width[++depth] ++;
        printf("往右子树,当前在第%d层,当前计算的宽度为%d\n",depth,width[depth]);
        TreeWidth(b->rchild);
    }
    depth--;
    printf("返回上一层,当前在第%d层,当前计算的宽度为%d\n",depth,width[depth]);
}
BTNode *LchildNode(BTNode *p) /*返回*p结点的左孩子结点指针*/ 
{ return p->lchild; } 
BTNode *RchildNode(BTNode *p) /*返回*p结点的右孩子结点指针*/
 { return p->rchild; }




void CreateBTree(BTNode *&b,char *str)
 {  

//创建二叉链
int MaxSize1=50;
BTNode *St[MaxSize],*p=NULL;
int top=-1,k,j=0; char ch=str[j]; 
b=NULL;
while(ch!='\0'){    //str未扫描完时循环
switch(ch){
case '(': top++; St[top]=p; k=1; break;  //可能有左孩子结点,进栈
case ')': top--;  break;
case ',': k=2;  break; 	//后面为右孩子
default:
p=(BTNode *)malloc(sizeof(BTNode));
p->data=ch;  
p->lchild=p->rchild=NULL;
if(b==NULL)
b=p;
else{ 
switch(k){
case 1:  St[top]->lchild=p; break;
case 2:  St[top]->rchild=p; break;
     }
 }
}

j++;  
ch=str[j];	//继续扫描str
 }
}
void Lchild(BTNode *b,ElemType x)
{
	if(b->lchild==NULL && b->rchild == NULL)
	cout<<"无左右孩子结点"<<endl; 
	else if(b->lchild!=NULL && b->rchild !=NULL)
 {		
if(b->data==x)
{
cout<<"左孩子为:"<<b->lchild->data<<endl;
cout<<"右孩子为:"<<b->rchild->data<<endl;	
}
Lchild(b->rchild,x);
Lchild(b->rchild,x);	
}
else if(b->lchild=NULL && b->rchild !=NULL)
{
if(b->data==x)
{
cout<<"无左孩子"<<endl;
cout<<"右孩子为:"<<b->rchild->data<<endl;	
}
Lchild(b->rchild,x);
Lchild(b->rchild,x);	
}
else if(b->lchild !=NULL && b->rchild ==NULL)
{
if(b->data==x)
{
cout<<"左孩子:"<<b->lchild->data<<endl;
cout<<"无右孩子"<<endl;	
}
Lchild(b->rchild,x);
Lchild(b->rchild,x);	
}
}

  int FindNode(BTNode *b,ElemType x) 
{
	int p;
	if (b==NULL)
	{return NULL;
		}	
	else if (b->data==x)
	{return  x;
		}	
	else  
	{
		p=FindNode(b->lchild,x);
		if (p!=NULL) 
		{return p;
			}	
		else 
			return FindNode(b->rchild,x);
	}
}
		 
     
///队列的有关操作
void InitQueue(SqQueue *&q)
{
	q=(SqQueue *)malloc(sizeof(SqQueue));
	q->front=q->rear=0;
 }

//判断队列是否为空
bool QueueEmpty(SqQueue *q)
{
	return (q->front==q->rear);
 }
 
 //进队列
 bool enQueue(SqQueue *q,BTNode *e)
 {
 	if((q->rear+1)%MaxSize==q->front)//队满溢出
	 return false;
	q->rear=(q->rear+1)%MaxSize;
	q->data[q->rear]=e;
	return true; 
 }
 
 //出队列
 bool deQueue(SqQueue *&q,BTNode *&e)
 {
 	if(q->front==q->rear)//判断是否队空
	 return false;
	q->front=(q->front+1)%MaxSize;
	e=q->data[q->front];
	return false; 
  } 
void DestoryBTree(BTNode *&b)
{
	if(b!=NULL)
	{
		DestoryBTree(b->lchild);
		DestoryBTree(b->rchild);
		free(b);
	}	
}

void DispBTree(BTNode *b)
{
	//输出单链表 
	if(b!=NULL)
	{
		cout<<(char)b->data<<" ";
		if(b->lchild!=NULL || b->rchild!=NULL)
		{
			cout<<"(";
			DispBTree(b->lchild);
			if(b->rchild!=NULL)
			cout<<",";
			DispBTree(b->rchild);
			cout<<")";		
		}	
	}
 } 
 
 int BTHeight(BTNode *b)
 {
 	//树的高度 
 int lchildh,rchildh;
 if(b==NULL)
 return(0);
 lchildh=BTHeight(b->lchild); 
 rchildh=BTHeight(b->rchild);
 return (lchildh>rchildh)?(lchildh+1):(rchildh+1);

 }
 void PreOrder(BTNode *b)
 {
 	//先序遍历 
 	if(b!=NULL)
 	{
 		cout<<(char)b->data;
 		PreOrder(b->lchild);
 		PreOrder(b->rchild);	
	}
	 	 
  } 
  void InOrder(BTNode *b)
  {
  	//中序遍历 
 	if(b!=NULL)
 	{
	    InOrder(b->lchild);
 		cout<<(char)b->data;
 		InOrder(b->rchild);	
	}
  }
  void PostOrder(BTNode *b)
  {
  	//后序遍历 
 	if(b!=NULL)
 	{
	    PostOrder(b->lchild);
 		PostOrder(b->rchild);	
		cout<<(char)b->data;
	}
  	
  	
  }
 void DispLeaf(BTNode *b)
{
//递归输出叶子节点
if(b!=NULL)
{
	if(b->lchild==NULL & b->rchild==NULL)
	cout<<(char)b->data;
	DispLeaf(b->lchild);
	DispLeaf(b->rchild);	
 } 
 } 
 int listleaf(BTNode *b)
     {
     	//输出叶子结点个数 
 	    int num1;
 	    if(b==NULL)
 	    return 0; 
		else if(b->lchild==NULL && b->rchild== NULL)
		return 1; 
		num1=listleaf(b->rchild)+listleaf(b->lchild);
		return num1;
		
	} 	 
 int listnode(BTNode *b)
 {
 	int num;
 	if(b==NULL)
 	return(0);
 	else
 	{
 		num=listnode(b->lchild)+listnode(b->rchild)+1;	
	 }
	 return num;
 }
 
int maxnode(BTNode *b)
{
	if(NULL == b)
		return 0;
	int maxLeft = maxnode(b->lchild);
	int maxRight = maxnode(b->rchild);
	int max = maxLeft > maxRight ? maxLeft : maxRight;
 
	return max > b->data ? max : b->data;
}
 int listfloor(BTNode *b,char x)
 {
 	int num2,m,n;
    if(b==NULL)
    num2=0;
    else if(b->data==x)
    num2=1;
    else 
    {
	m=listfloor(b->lchild,x);
	n= listfloor(b->rchild,x);
   if(m==0 && n==0)
    num2=0;
   else
   num2=((m>n)?m:n)+1;
	}
     return num2;
} 
/* 
int level(BTNode *b,char n)
{ //假设二叉树结点互不相同
 int d1,d2;
 if(b==NULL) 
 return 0;
 if((int)b->data==n) 
 return 1;
 d1=level(b->lchild,n);
 d2=level(b->rchild,n);
// if(d1*d2) 
 return 1+(d1>d2?d1:d2);d1*d2????
// return 0;
}
*/ 
int Level(BTNode *b,ElemType x,int h)
{
	int l;
	if(b==NULL)	
	return(0);	
	else if((char)b->data==(char)x)
	return(h);
	else
	{
	l=Level(b->lchild,x,h+1);//左子树中查找 
	if(l!=0)
	return(l);//在左子树中找到,返回l 
	else
	return(Level(b->rchild,x,h+1));//在左子树中未找到再在右子树中查找 
		
	}
	
	
}
//栈的所有操作如下 

void InitStack(SqStack *&s)			//初始化栈
{	s=(SqStack *)malloc(sizeof(SqStack));//分配一个是顺序栈空间,首地址存放在s中
	s->top=-1;						//栈顶指针置为-1
}
void DestroyStack(SqStack *&s)		//销毁栈
{
	free(s);
}
bool StackEmpty(SqStack *s)			//判断栈是否为空
{
	return(s->top==-1);
}
bool Push(SqStack *&s,BTNode *e)	//进栈
{	if (s->top==MaxSize-1)			//栈满的情况,即栈上溢出
		return false;
	s->top++;						//栈顶指针增1
	s->data[s->top]=e;				//元素e放在栈顶指针处
	return true;
}
bool Pop(SqStack *&s,BTNode *&e)	//出栈
{	if (s->top==-1)					//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top];				//取栈顶指针元素的元素
	s->top--;						//栈顶指针减1
	return true;
}
bool GetTop(SqStack *s,BTNode *&e)	//取栈顶元素
{	if (s->top==-1)					//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top];				//取栈顶元素
	return true;
}

void PreOrder1(BTNode *b)			//先序非递归遍历算法1
{
	BTNode *p;
	SqStack *st;					//定义一个顺序栈指针st
	InitStack(st);					//初始化栈st
	Push(st,b);					//根节点进栈
	while (!StackEmpty(st))		//栈不为空时循环
	{
		Pop(st,p);				//退栈节点p并访问它
		printf("%c ",p->data);	//访问节点p
		if (p->rchild!=NULL)	//有右孩子时将其进栈
			Push(st,p->rchild);
		if (p->lchild!=NULL)	//有左孩子时将其进栈
			Push(st,p->lchild);
	}
	printf("\n");
	DestroyStack(st);				//销毁栈
}

//中序非递归遍历 

void InOrder1(BTNode *b)				//中序非递归遍历算法
{
	BTNode *p;
	SqStack *st;						//定义一个顺序栈指针st
	InitStack(st);						//初始化栈st
	if (b!=NULL)
	{
		p=b;
		while (!StackEmpty(st) || p!=NULL)
		{
			while (p!=NULL)				//扫描节点p的所有左下节点并进栈
			{
				Push(st,p);				//节点p进栈
				p=p->lchild;			//移动到左孩子
			}
			if (!StackEmpty(st))		//若栈不空
			{
				Pop(st,p);				//出栈节点p
				printf("%c ",p->data);	//访问节点p
				p=p->rchild;			//转向处理其右子树
			}
		}
		printf("\n");
	}
	DestroyStack(st);				//销毁栈
}

void PostOrder1(BTNode *b)				//后序非递归遍历算法
{
	BTNode *p,*r;
	bool flag;
	SqStack *st;						//定义一个顺序栈指针st
	InitStack(st);						//初始化栈st
	p=b;
	do
	{
		while (p!=NULL)					//扫描节点p的所有左下节点并进栈
		{
			Push(st,p);					//节点p进栈
			p=p->lchild;				//移动到左孩子
		}
		r=NULL;							//r指向刚刚访问的节点,初始时为空
		flag=true;						//flag为真表示正在处理栈顶节点
		while (!StackEmpty(st) && flag)
		{
			GetTop(st,p);				//取出当前的栈顶节点p
			if (p->rchild==r)			//若节点p的右孩子为空或者为刚刚访问过的节点	
			{
				printf("%c ",p->data);	//访问节点p
				Pop(st,p);
				r=p;					//r指向刚访问过的节点
			}
			else
			{	
				p=p->rchild;			//转向处理其右子树
				flag=false;				//表示当前不是处理栈顶节点
			}
		}
	} while (!StackEmpty(st));			//栈不空循环
	printf("\n");
	DestroyStack(st);				//销毁栈
}

void LevelOrder(BTNode *b)
{
	BTNode *p;
	SqQueue *qu;
	InitQueue(qu);//初始化队列
	enQueue(qu,b);//根结点指针进入队列
	while(!QueueEmpty(qu))
	//队不为空时循环 
	{
		deQueue(qu,p);//出队结点p
		cout<<(char)p->data<<" ";
		if(p->lchild!=NULL)//有 
		{
			enQueue(qu,p->lchild); 
		 } 
		if(p->rchild!=NULL)//有右孩子进队 
		{
			enQueue(qu,p->rchild);
		}
		
	}
 } 
 
int main()
{
	system("cls");
	system("color 00a");
	BTNode *b;
	int i,n;	
	char x;
	cout<<"本程序为二叉树的操作"<<endl;
	/* 
	cout<<"请输入你的字符长度" <<endl; 
	cin>>n;
	cout<<"请输入你的二叉树"<<endl;
	char str[n];
	for(int k=0;k<n;k++)
	{
	cin>>str[k];
	}
	*/
	/*
    ifstream fileinput; 
	fileinput.open("E:\\input.txt");
 	char v[1];
	char str[14];
	fileinput>>v;
	for (int j=1;j<=14;j++)
	{	
	fileinput>>str[j];
	}
	fileinput.close();
	for(int k=1;k<=14;k++)
	{
	cout<<str[k]<<"  ";	
	}
	*/
	
	//char str[20]="A(B(D,E),C(F))";
	//int h;
//	cout<<"请输入你的二叉树字符的长度"<<endl;
//	cin>>h;
	char str[20]; 
	cout<<"请输入你的二叉树"<<endl;
	cin.getline(str, 20);
	CreateBTree(b,str);	
	cout<<"创建成功" ;
	cout<<"是否继续操作继续操作请输入1,否则输入0"<<endl;
	cin>>i; 
	while(i!=0)
	{
	cout<<"---------------------------------------"<<endl; 
	cout<<"--  输入【0】结束程序               ---"<<endl; 
	cout<<"--  输入【1】输出二叉树			   ---"<<endl; 
	cout<<"--  输入【2】计算二叉树高度 		   ---"<<endl;
	cout<<"--  输入【3】查找节点是否存在(数字)	   ---"<<endl;
	cout<<"--  输入【4】输出所有叶子结点	   ---"<<endl;
	cout<<"--  输入【5】计算叶子节点个数	   ---"<<endl;
	cout<<"--  输入【6】前序遍历输出二叉树	   ---"<<endl;
	cout<<"--  输入【7】中序遍历输出二叉树     ---"<<endl;
	cout<<"--  输入【8】后序遍历输出二叉树	   ---"<<endl;
	cout<<"--  输入【9】查找x是否在树中(该程序与3重复,跳过)        ---"<<endl;
	cout<<"--  输入【10】计算结点个数          ---"<<endl;
	cout<<"--  输入【11】输出该树中结点最大值  ---"<<endl;
	cout<<"--  输入【12】输出树中结点值为x的层 ---"<<endl;
	cout<<"--  输入【13】输出左右孩子结点值    ---"<<endl; 
	cout<<"--  输入【14】计算二叉树的各层的宽度---"<<endl;
	cout<<"--  输入【15】计算指定结点所在的层次---"<<endl;
	cout<<"--  输入【16】销毁释放二叉树        ---"<<endl;
	cout<<"--  输入【17】先序非递归算法        ---"<<endl;
	cout<<"--  输入【18】中序非递归算法        ---"<<endl;
	cout<<"--  输入【19】后序非递归算法        ---"<<endl;
	cout<<"--  输入【20】层次遍历(队列)算法  ---"<<endl;
	cout<<"--  请输入你的操作                  ---"<<endl;
	cout<<"---------------------------------------"<<endl; 
	cin>>i;
	if(i==0)
	{
		cout<<"程序已经退出"<<endl; 
		break;
	} 
	
	else if(i==1)
	{
		cout<<"二叉树输出为"<<endl; 
		DispBTree(b);	
	}
	else if(i==2)
	{
		int h;
		h=BTHeight(b);
		cout<<"二叉树高度为"<<endl; 
		cout<<h<<endl;
	 } 
	 else if(i==3)
	 {
	 	int y;
	 	ElemType x;
	 	cout<<"请输入你要查找的结点"<<endl;
	 	cin>>x; 
	 	y=FindNode(b,x);
	 	if(y==x) 
	 	cout<<"该结点存在"<<endl;
	 	else
		cout<<"该结点不存在"<<endl; 
	 }
	 else if(i==4)
	 { 
	 	cout<<"叶子结点显示如下:"<<endl; 
	 	DispLeaf(b); 
	 }
	 else if(i==5)
	 {
	 	int c;
	 	c=listleaf(b);
	 	cout<<"叶子结点个数为:"<<c<<endl;
	 }
	 else if(i==6)
	 {
	 	cout<<"前序遍历输出为"<<endl;
		PreOrder(b); 
	 }
	 else if(i==7)
	 {
	 	cout<<"中序遍历输出为"<<endl;
		InOrder(b); 
	 	
	  } 
	  else if(i==8)
	  {
	  	cout<<"后序遍历输出为"<<endl;
		PostOrder(b); 
	  }
	  
	 else if(i==9)
	 {
	 	cout<<"请输入你要查找的字符";
		cin>>x; 
		FindNode(b,x);
	  } 
	 else if(i==10)
	 {
	 	int c;
	 	cout<<"查询结点个数";
		c=listnode(b);
		cout<<"个数为"<<c<<endl; 
	 }
	 else if(i==11)
	{
		int d;
		d=maxnode(b);
		cout<<"最大值为"<<(char)d<<endl; 
	}
	else if(i==12)
	{
		int e;
		char x;
		cout<<"请输入你的结点"<<endl;
		cin>>x;
		e=listfloor(b,x);
		cout<<"该数在"<<e<<"层"<<endl; 
	}
	else if(i==13) 
	{

		cout<<"输入你要查找的结点"<<endl; 
	    cin>>x;
		Lchild(b,x);
	}
	else if(i==14)
	{
		cout<<"二叉树各层高度如下"<<endl;
		TreeWidth(b);
	}
	else if(i==15)
	{
		int l;
		ElemType x;
		cout<<"请输入结点(输入对应的ascii码67)"<<endl; 
		cin>>x; 
		l=Level(b,x,1);
		cout<<"结点所在层次为:"<<l<<endl;
		 
		
	}
	else if(i==16)
	{
		DestoryBTree(b);
		cout<<"二叉树释放完成" <<endl;
	}
	else if(i==17)
	{
		cout<<"先序非递归算法为:"<<endl;
		PreOrder1(b);	
	 } 
	 
	 			
	 else if(i==18)
	{
		cout<<"中序非递归遍历算法为:"<<endl;
		InOrder1(b); 
	 } 
	 else if(i==19)
	{
		cout<<"后序非递归遍历算法为:"<<endl;
		PostOrder1(b); 
	 } 
	 else if(i==20)
	{
		cout<<"基于队列的层次遍历算法为:"<<endl;
		LevelOrder(b); 
	 } 
	 
	 
	 
}}
 /*
 
 实验总结:
 方法一:
 将数字转化成ascii码只需要在数字前加上(char)
 方法二:#include <iostream>
#include "stdio.h"; 
using namespace std ;
int main()
{
int a=99;
printf("%c",a);
} 
 */
 /*
 字符串长度为:14 
 程序备用例子: A(B(D,E),C(F))
 */ 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值