數組存儲二叉樹森林,實現構建遍歷查插刪

#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");
}

刪除可能還存在部分問題,但是,暫時先這樣吧。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章