二叉树实验

二叉树实验

(一)用到的结构体

typedef struct node 
{
	char info;
	struct node* lchild;
	struct node* rchild;
}tree;
typedef struct stack_1
{
	tree* a[MAX];
	int tag[MAX];
	int top;
}stack;

(二)对栈的操作

void push(stack* st, tree* t)
{
	st->a[st->top] = t;
	st->top++;
}
tree* pop(stack* st)
{
	if (st->top != 0)
	{
		st->top--;
		return st->a[st->top];
	}
	else
		return NULL;
}
tree* top(stack* st)
{
	if (st->top != 0)
	{
		return st->a[st->top - 1];
	}
	else
	{
		return NULL;
	}
}

(三)递归建树

tree *creat()//递归建树
{
	tree *root;
	char ch;
	scanf_s("%c", &ch,1);
	if (ch == '#')
		return NULL;
	else
	{
		root = (tree*)malloc(sizeof(tree));
		root->info = ch;
		root->lchild = creat();
		root->rchild = creat();
	}
	return root;
}

(四)非递归建树

tree *creat_1()//非递归建树
{
	stack_1 A;
	stack_1 *st;
	st = &A;
	tree *root;
	tree *p1, *p2;
	int i = 0;
	char ch[MAX];
	//0---左孩子为空,1---右孩子为空,2建树完成
	scanf_s("%s", ch, MAX);
	getchar();
	st->top = 0;//栈初始化
	while (ch[i] != '\0')
	{
		if (i == 0)//建立根节点
		{
			root = (tree*)malloc(sizeof(tree));
			root->info = ch[i];
			root->lchild = NULL;
			root->rchild = NULL;
			p1 = root;
			push(st, root);
			st->tag[st->top - 1] = 0;

		}
		else//非根节点
		{
			if (ch[i] != '#'&&st->tag[st->top - 1] == 0)//建左树
			{
				p2 = (tree*)malloc(sizeof(tree));
				p2->info = ch[i];
				p2->lchild = NULL;//一定要有,不然会和下面的代码冲突
				p2->rchild = NULL;
				push(st, p2);//入栈
				p1->lchild = p2;//连接新建左孩子
				p1 = p2;//指针下移
				st->tag[st->top - 1] = 0;//0表示此节点没有左孩子
			}
			else if (ch[i] == '#'&&st->tag[st->top - 1] == 0)//左树完成
			{
				p1->lchild = NULL;
				st->tag[st->top - 1] = 1;//左子树构建完成
			}
			else if (ch[i] == '#'&&st->tag[st->top - 1] == 1)//右树完成
			{
				p1->rchild = NULL;
				st->tag[st->top - 1] = 2;//右子树构建完成
			}
			else if (ch[i] != '#'&&st->tag[st->top - 1] == 1)//建右树
			{
				p2 = (tree*)malloc(sizeof(tree));
				p2->info = ch[i];
				p2->lchild = NULL;
				p2->rchild = NULL;
				push(st, p2);
				p1->rchild = p2;
				p1 = p2;
				st->tag[st->top - 1] = 0;
			}
			while (st->tag[st->top - 1] == 2)//是否出栈操作,当左右子树都已建立时,出栈
			{
				st->tag[st->top - 1] = 0;
				p1 = pop(st);
				if (st->top != 0)//避免最后一个节点误操作,如果没有此句,会导致栈的top越界
					p1 = st->a[st->top - 1];
				else
					break;
				if (st->tag[st->top - 1] == 1)//说明此时结点的左子树已存在,并且当前指针是从下一右子树返上来的结点,即:右子树也存在;
				{
					st->tag[st->top - 1] = 2;
				}
			}
			if (p1->lchild != NULL || st->tag[st->top - 1] == 1)//对返上来的结点进行判断,有左子树则改变标记为1
			{
				st->tag[st->top - 1] = 1;
			}

		}
		i++;
	}
	return root;

}

完整代码:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define MAX 1000
typedef struct node 
{
	char info;
	struct node* lchild;
	struct node* rchild;
}tree;
typedef struct stack_1
{
	tree* a[MAX];
	int tag[MAX];
	int top;
}stack;
void push(stack* st, tree* t)
{
	st->a[st->top] = t;
	st->top++;
}
tree* pop(stack* st)
{
	if (st->top != 0)
	{
		st->top--;
		return st->a[st->top];
	}
	else
		return NULL;
}
tree* top(stack* st)
{
	if (st->top != 0)
	{
		return st->a[st->top - 1];
	}
	else
	{
		return NULL;
	}
}
tree *creat()//递归建树
{
	tree *root;
	char ch;
	scanf_s("%c", &ch,1);
	if (ch == '#')
		return NULL;
	else
	{
		root = (tree*)malloc(sizeof(tree));
		root->info = ch;
		root->lchild = creat();
		root->rchild = creat();
	}
	return root;
}
tree *creat_1()//非递归建树
{
	stack_1 A;
	stack_1 *st;
	st = &A;
	tree *root;
	tree *p1, *p2;
	int i = 0;
	char ch[MAX];
	//0---左孩子为空,1---右孩子为空,2建树完成
	scanf_s("%s", ch, MAX);
	getchar();
	st->top = 0;//栈初始化
	while (ch[i] != '\0')
	{
		if (i == 0)//建立根节点
		{
			root = (tree*)malloc(sizeof(tree));
			root->info = ch[i];
			root->lchild = NULL;
			root->rchild = NULL;
			p1 = root;
			push(st, root);
			st->tag[st->top - 1] = 0;

		}
		else//非根节点
		{
			if (ch[i] != '#'&&st->tag[st->top - 1] == 0)//建左树
			{
				p2 = (tree*)malloc(sizeof(tree));
				p2->info = ch[i];
				p2->lchild = NULL;//一定要有,不然会和下面的代码冲突
				p2->rchild = NULL;
				push(st, p2);//入栈
				p1->lchild = p2;//连接新建左孩子
				p1 = p2;//指针下移
				st->tag[st->top - 1] = 0;//0表示此节点没有左孩子
			}
			else if (ch[i] == '#'&&st->tag[st->top - 1] == 0)//左树完成
			{
				p1->lchild = NULL;
				st->tag[st->top - 1] = 1;//左子树构建完成
			}
			else if (ch[i] == '#'&&st->tag[st->top - 1] == 1)//右树完成
			{
				p1->rchild = NULL;
				st->tag[st->top - 1] = 2;//右子树构建完成
			}
			else if (ch[i] != '#'&&st->tag[st->top - 1] == 1)//建右树
			{
				p2 = (tree*)malloc(sizeof(tree));
				p2->info = ch[i];
				p2->lchild = NULL;
				p2->rchild = NULL;
				push(st, p2);
				p1->rchild = p2;
				p1 = p2;
				st->tag[st->top - 1] = 0;
			}
			while (st->tag[st->top - 1] == 2)//是否出栈操作,当左右子树都已建立时,出栈
			{
				st->tag[st->top - 1] = 0;
				p1 = pop(st);
				if (st->top != 0)//避免最后一个节点误操作,如果没有此句,会导致栈的top越界
					p1 = st->a[st->top - 1];
				else
					break;
				if (st->tag[st->top - 1] == 1)//说明此时结点的左子树已存在,并且当前指针是从下一右子树返上来的结点,即:右子树也存在;
				{
					st->tag[st->top - 1] = 2;
				}
			}
			if (p1->lchild != NULL || st->tag[st->top - 1] == 1)//对返上来的结点进行判断,有左子树则改变标记为1
			{
				st->tag[st->top - 1] = 1;
			}

		}
		i++;
	}
	return root;

}
void preprint(tree* t)//递归前序输出
{
	tree* p1;
	p1 = t;
	if (!p1)
		return;
	else
	{
		printf("%c->", p1->info);
		preprint(p1->lchild);
		preprint(p1->rchild);

	}
}
void inorprint(tree* t)
{
	tree* p1;
	p1 = t;
	if (!p1)
		return;
	else
	{
		inorprint(p1->lchild);
		printf("%c->", p1->info);
		inorprint(p1->rchild);

	}
}
void postprint(tree* t)
{
	tree* p1;
	p1 = t;
	if (!p1)
		return;
	else
	{
		postprint(p1->lchild);
		postprint(p1->rchild);
		printf("%c->", p1->info);

	}
}
void preprint_1(tree* t)//非递前序输出;
{
	stack A;
	stack* st;
	st = &A;
	tree* p1;
	p1 = t;
	st->top = 0;
	
	while (p1 || st->top != 0)
	{
		if (p1)
		{
			printf("%c->", p1->info);
			push(st, p1);
			p1 = p1->lchild;
		}
		else {
			p1 = pop(st);
			p1 = p1->rchild;

		}
	}
}
void inorprint_1(tree* t) //非递归中序输出
{
	stack B;
	stack* st;
	st = &B;
	st->top = 0;
	tree *p1;
	p1 = t;
	while (p1 || st->top != 0)
	{
		if (p1)
		{
			push(st, p1);
			p1 = p1->lchild;
		}
		else
		{
			p1 = pop(st);
			printf("%c-->", p1->info);
			p1 = p1->rchild;
		}
	}
}
void postprint_1(tree* t)//非递归后序遍历
{
	stack C;
	stack* st;
	st = &C;
	st->top = 0;
	tree* p1;
	p1 = t;
	while (p1 || st->top != 0)
	{
		if (p1)
		{
			push(st, p1);
			st->tag[st->top-1] = 0;
			p1 = p1->lchild;
		}
		else//空
		{
			if (st->tag[st->top-1] == 0)
			{
				p1 = st->a[st->top - 1];
				st->tag[st->top - 1] = 1;
				p1 = p1->rchild;
			}
			else if (st->tag[st->top-1] == 1)
			{
				p1 = st->a[st->top - 1];
				printf("%c***->", p1->info);
				st->tag[st->top - 1] = 0;
				st->top--;
				p1=NULL;//避免多次入栈
			}
		}
	}
}
void fun()//输出递归菜单
{
	
	printf("\n**************二叉树递归操作菜单***********\n");
	printf("****“A”--------前序遍历二叉树--------****\n");
	printf("****“B”--------中序遍历二叉树--------****\n");
	printf("****“C”--------后序遍历二叉树--------****\n");
	printf("****“D”---------本次执行结束---------****\n");
	printf("*******************************************\n\n");
}
void fun_1()//输出非递归菜单
{

	printf("\n*************二叉树非递归操作菜单**********\n");
	printf("****“1”--------前序遍历二叉树--------****\n");
	printf("****“2”--------中序遍历二叉树--------****\n");
	printf("****“3”--------后序遍历二叉树--------****\n");
	printf("****“4”---------本次执行结束---------****\n");
	printf("*******************************************\n\n");
}
void fun2()
{
	printf("\n*************二叉树操作菜单**********\n");
	printf("****“d”--------递归操作--------****\n");
	printf("****“f”-------非递归操作-------****\n");
	printf("****“@”--------退出程序--------****\n");
	printf("*************************************\n\n");
}
void fun3()
{
	printf("\n*************二叉树建立菜单**********\n");
	printf("****“q”--------递归建立--------****\n");
	printf("****“w”-------非递归建立-------****\n");
	printf("*************************************\n\n");
}
int getnode(tree *root)
{
	if (root == NULL)
		return 0;
	else if (root->lchild == NULL&&root->rchild == NULL)
		return 1;
	else
		return getnode(root->lchild) + getnode(root->rchild);
}
int getnode_1(tree *root)
{
	stack A;
	stack *st;
	st = &A;
	st->top = 0;
	int sum = 0;
	while (root || st->top != 0)
	{
		if (root)
		{
			if (root->lchild == NULL&&root->rchild == NULL)
				sum++;
			push(st, root);
			root = root->lchild;
			
		}
		else
		{
			root = pop(st);//往上返一层
			root = root->rchild;
		}
	}
	return sum;
}
tree* getlastnode(tree * root)
{
	tree *p;
	p = root;
	while (p&&p->rchild)
	{
		p = p->rchild;
	}
	return p;
}
tree* getfather(tree* t,char x,char y) 
{  stack  s; 
tree *antor;
   tree* data[100]={0}; 
   int i=0,j; 
   s.top=-1; 
   while(t || s.top>-1) 
   {   while(t) 
		{ 
			s.a[++s.top]=t; 
		  s.tag[s.top]=0; 
		  t=t->lchild;  
		 } 
		while(s.top>-1 && s.tag[s.top]) 
		 {   
			t=s.a[s.top]; 
			 if(t->info==x) 
			 while(i<=s.top)  //记录x结点的所有祖先结点  
			{ 
				 data[i] = s.a[i];
            i++; 
       } 
          else if(t->info==y)  
    { 
               while(s.top>-1) 
       { 
        j=i-1; 
        while(j>=0&&t!=data[j])//查找y与x的最近公共祖先结点  
        j--; 
        if(j>=0) 
        {  
     antor=data[j]; //返回公共祖先结点地址  
     return antor; 
        }  
        t=s.a[--s.top]; 
       } 
        } 
       --s.top; 
   }    
   if(s.top>-1) 
   { 
     t=s.a[s.top]; 
              s.tag[s.top]=1; 
              t=t->rchild; 
   } 
   else  t=NULL; 
  } 
} 
int main()
{
	tree* T=NULL;
	char A, B;
	tree* root;
	char u;
	char a;
	root = NULL;
	fun3();
	printf("请选择以何种方式建立二叉树(递归和非递归):");
	u = getchar();
	getchar();
	if (u == 'q')
	{
		printf("输入一组数据(以#分隔):\n");
		root = creat();
		getchar();
	}
	else if(u=='w')
	{
		printf("输入一组数据(以#分隔):\n");
		root = creat_1();
	}
	int k = getnode_1(root);
	printf("\n叶子节点:%d\n", k);
	tree * p4 = getlastnode(root);
	printf("中序的最后一个节点是:%c\n", p4->info);
	printf("查找共同祖先(输入两个结点值):\n");
	scanf_s("%c%c", &A, 1, &B, 1);
	getchar();
	tree* P=getfather(root, A, B);
	printf("%c和%c的共同祖先是:", A, B);
	printf("%c\n", P->info);
	while (1)
	{
		char p;
		printf("\n     -----请选择操作类型-----\n");
		fun2();
		scanf_s("%c", &p, 1);
		getchar();
		if (p == 'd')
		{
			fun();
			while (1)
			{
				a = getchar();
				getchar();
				if (a == 'A') 
				{
					printf("前序遍历:"); preprint(root); printf("\n"); 
				}
				else if (a == 'B')
				{
					printf("中序遍历:"); inorprint(root); printf("\n");
				}
				else if (a == 'C')
				{
					printf("后序遍历:"); postprint(root); printf("\n");
				}
				else if(a=='D'){
					break;

				}
			}
		}
		else if (p == 'f')
		{
			fun_1();
			while (1)
			{
				a = getchar();
				getchar();
				if (a == '1')
				{
					printf("前序遍历:"); preprint_1(root); printf("\n");
				}
				else if (a == '2')
				{
					printf("中序遍历:"); inorprint_1(root); printf("\n");
				}
				else if (a == '3')
				{
					printf("后序遍历:"); postprint_1(root); printf("\n");
				}
				else if(a=='4') {
					break;

				}

			}
		}
		else if (p == '@')
		{
			break;
		}
		else {
			printf("********\n");
			printf("**警告**:非法字符,请重新操作!\n");
			printf("********\n");
		}
	}
	return 0;
}

输入数据:

ABDH#K###E##CFI###G#J##

二叉树:
在这里插入图片描述
输出如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值