数组存储二叉树森林,实现构建遍历查插删

#include <stdio.h>
#include <stdlib.h>


typedef struct Bnode{
    //存储结点的父结点,子结点数目,自身(同时也是其序号)以及所在树的根结点
    int father,son_num,self;
    struct Bnode *Lson,*Rson;//左儿子和右儿子
} Bnode,*Bptr;//用于定义结构体变量和指针

//定义结构体数组用于存树
Bnode tree[10000];
//定义根结点为空,即树为空
Bptr root=NULL;
//定义一个数组用来存根结点序号
int roots[100];


void creat(){
	int x, y, i;
	i=0;
	printf("建立二叉树\n请输入(x y↙):");
	scanf("%d %d",&x,&y);
	//进入循环
	while(x!=0||y!=0){
		//若x,y都不在树中
		if((!tree[x].self)&&(!tree[y].self)){
			tree[x].self=x;
			tree[x].father=-1;//根结点没有父亲,赋-1
			tree[x].son_num=1;
			tree[x].Lson=&tree[y];
			tree[x].Rson=NULL;
			roots[i]=x;
			i++;
			tree[y].self=y;
			tree[y].father=x;
			tree[y].son_num=0;
			tree[y].Lson=tree[y].Rson=NULL;
		}
		//若y已存在树中
		else if(tree[y].self==y){
			printf("输入错误,%d已存在!\n",y);
		}
		//若x已存在树中,y不在
		else if((tree[x].self==x)&&(!tree[y].self)){
			switch(tree[x].son_num){
				case(0):{
					tree[x].son_num=1;
					tree[x].Lson=&tree[y];
					tree[x].Rson=NULL;
					tree[y].self=y;
					tree[y].father=x;
					tree[y].son_num=0;
					tree[y].Lson=tree[y].Rson=NULL;
					break;}
				case(1):{
					tree[x].son_num=2;
					tree[x].Rson=&tree[y];
					tree[y].self=y;
					tree[y].father=x;
					tree[y].son_num=0;
					tree[y].Lson=tree[y].Rson=NULL;
					break;}
				case(2):{
					printf("%d儿子已满!\n",x);
					break;}
			}
		}
		//输入下一组(x y)
		printf("请输入(x y↙):");
		scanf("%d %d",&x,&y);
	}
	if(x==0&&y==0){
		printf("输入结束!\n");
	}
}


//单棵树的先序遍历
void preorder_1(Bptr p){
    if(p==NULL||p->self==0)
        return;
    printf("%d\t",p->self);
    preorder_1(p->Lson);
    preorder_1(p->Rson);
}
//先序遍历
void preorder(){
    Bptr p;
	int k,m;
	m=0;
	//若根集为空,不存在任何树,则k值为空(或0)
	if(!roots[0]){
		printf("空树!");
	}
	else
		while(roots[m]){
				k=roots[m];
				p=&tree[k];//把第一棵树的根指针赋给p
				preorder_1( p);
				m++;
		}
}


//单棵树的中序遍历
void inorder_1(Bptr p){
    if(p==NULL||p->self==0)
        return;
    preorder_1(p->Lson);
    printf("%d\t",p->self);
    preorder_1(p->Rson);
}
//中序遍历
void inorder(){
    Bptr p;
	int k,m;
	m=0;
	//若根集为空,不存在任何树,则k值为空(或0)
	if(!roots[0]){
		printf("空树!");
	}
	else
		while(roots[m]){
				k=roots[m];
				p=&tree[k];//把第一棵树的根指针赋给p
				inorder_1( p);
				m++;
		}
}


//单棵树的后序遍历
void postorder_1(Bptr p){
    if(p==NULL||p->self==0)
        return;
    preorder_1(p->Lson);
    preorder_1(p->Rson);
	printf("%d\t",p->self);
}
//后序遍历
void postorder(){
    Bptr p;
	int k,m;
	m=0;
	//若根集为空,不存在任何树,则k值为空(或0)
	if(!roots[0]){
		printf("空树!");
	}
	else
		while(roots[m]){
				k=roots[m];
				p=&tree[k];//把第一棵树的根指针赋给p
				postorder_1( p);
				m++;
		}
}


//插入操作
void insert(){
	int m,n;
	int j=0;
	//输入插入关系
	printf("\n请输入要插入的结点,例如在m后面插入n(m n↙),输入(0 0↙)结束:");
	scanf("%d %d",&m,&n);
	//进入循环
	while(m!=0||n!=0){
		//若m不在现有的序列中
		if(tree[m].self!=m){
			tree[m].self=m;
			tree[m].father=-1;//根结点没有父亲,赋-1
			tree[m].son_num=1;
			tree[m].Lson=&tree[n];
			tree[m].Rson=NULL;
			//将m放入根序列
			for(j=0;j<100;j++){
				if(!roots[j]){
					roots[j]=m;
					break;
				}
			}
			tree[n].self=n;
			tree[n].father=m;
			tree[n].son_num=0;
			tree[n].Lson=tree[n].Rson=NULL;
		}
		else{
			//若n已存在于现有序列
			if(tree[n].self==n)
				printf("\n %d已存在!\n",n);
			else{
				switch(tree[m].son_num){
					//n具体插入位置与m已有的儿子数有关
				case(0):{
						tree[m].son_num=1;
						tree[m].Lson=&tree[n];
						tree[m].Rson=NULL;
						tree[n].self=n;
						tree[n].father=m;
						tree[n].son_num=0;
						tree[n].Lson=tree[n].Rson=NULL;
						break;}
				case(1):{
						tree[m].son_num=2;
						tree[m].Rson=&tree[n];
						tree[n].self=n;
						tree[n].father=m;
						tree[n].son_num=0;
						tree[n].Lson=tree[n].Rson=NULL;
						break;}
				case(2):{
						printf("%d儿子已满!\n",m);
						break;}
				}
			}
		}
	printf("请输入要插入的结点,例如在m后面插入n(m n↙),输入(0 0↙)结束:");
	scanf("%d %d",&m,&n);
	}
	if(m==0&&n==0){
		printf("插入结束!");
	}
}


//删除,由于delete为库函数,故重新命名delete_1
void delete_1(){
	int x;
	int j=0;
	//输入删除结点
	printf("\n请输入要删除的结点(输入-1结束):");
	scanf("%d ",&x);
	//进入循环
	while(x!=-1){
		//若x为根结点(即父亲为-1):x结点的子树成为独立的树
		if(tree[x].father==-1){
			switch(tree[x].son_num){
				//具体操作与其儿子数有关
			case(0):
				{
					//将x结点置空
					tree[x].son_num=0;
					tree[x].self=0;
					tree[x].Lson=tree[x].Rson=NULL;
					//将x从根序列中删除
					for(j=0;j<100;j++){
						if(roots[j]==x){
							roots[j]=roots[j+1];
							break;
						}
					}
					while(roots[++j]){
						roots[j]=roots[j+1];
					}
					break;
				}
			case(1):
				{
					//将根序列中x的位置用其左儿子替代
					for(j=0;j<100;j++){
						if(roots[j]==x){
							roots[j]=tree[x].Lson->self;
							break;
						}
					}
					//将x结点置空
					tree[x].son_num=0;
					tree[x].self=0;
					tree[x].Lson=tree[x].Rson=NULL;
					break;
				}
			case(2):{
					//将根序列中x的位置用其左儿子替代
					for(j=0;j<100;j++){
						if(roots[j]==x){
							roots[j]=tree[x].Lson->self;
							break;
						}
					}
					//将右儿子也放入根序列
					for(j=0;j<100;j++){
						if(!roots[j]){
							roots[j]=tree[x].Rson->self;
							break;
						}
					}
					break;}
			}
		}
		//否则x为一普通结点,删除x后其子树也为独立树
		else{
			switch(tree[x].son_num){
				//具体操作与其儿子数有关
			case(0):{
					//将x结点置空
					tree[x].son_num=0;
					tree[x].self=0;
					tree[x].father=-1;
					tree[x].Lson=tree[x].Rson=NULL;
					break;}
			case(1):{
					//将x的子树独立
					for(j=0;j<100;j++){
						if(!roots[j]){
							roots[j]=tree[x].Lson->self;
							break;
						}
					}
					//将x结点置空
					tree[x].son_num=0;
					tree[x].self=0;
					tree[x].father=-1;
					tree[x].Lson=tree[x].Rson=NULL;
					break;}
			case(2):{
					//将x的子树独立
					for(j=0;j<100;j++){
						if(!roots[j]){
							roots[j]=tree[x].Lson->self;
							roots[j+1]=tree[x].Rson->self;
							break;
						}
					}
					//将x结点置空
					tree[x].son_num=0;
					tree[x].self=0;
					tree[x].father=-1;
					tree[x].Lson=tree[x].Rson=NULL;
					break;}
			}
		}
	}
}


void main(){
	int i=0;
	//构建
	creat();
	//输出根结点目录
	printf("\n森里中各树的根结点目录:");
	while(roots[i]){
		printf("%d \t  ",roots[i]);
		i++;
	}
	//三种遍历
	printf("\n先序遍历:");
	preorder();
	printf("\n中序遍历:");
	inorder();
	printf("\n后序遍历:");
	postorder();
	printf("\n");
	
	//插入
	insert();
	//三种遍历
	printf("\n先序遍历:");
	preorder();
	printf("\n中序遍历:");
	inorder();
	printf("\n后序遍历:");
	postorder();
	printf("\n");

	//删除
	delete_1();
	//三种遍历
	printf("\n先序遍历:");
	preorder();
	printf("\n中序遍历:");
	inorder();
	printf("\n后序遍历:");
	postorder();
	printf("\n");
}

删除可能还存在部分问题,但是,暂时先这样吧。。。

猜你喜欢

转载自blog.csdn.net/goodboydan/article/details/78433810