⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree_structure.h

📁 二叉排序树的所有功能
💻 H
字号:
#include "iostream.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "common.h"
#define M 10
//学生节点
struct student{
	int _Mark;
	char _Name[10];
	char _Number[10];
};
//节点
struct tree {
	int key;//关键码
	int sum;//学生总数
//	<50,50-59,60-65, 66-69,70-75,76-79,80-85,86-89,90-95,96-100
//		E, D,   C,   C+,   B-,   B,   B+,   A,  AA,  AA+
//	key=0,  1,    2,    3,     4,     5,    6,     7,   8,     9
	struct student stu[20];
	struct tree *left,*right;
};

//插入节点函数,节点的关键值是成绩段
//参数:根节点,插入节点,插入位置
//返回:根节点
//调试成功:5-1 17:46
struct tree* _add_tree(struct tree*root,struct tree*r,int mark,int key){
	if (r==NULL) {
		r=new struct tree;
		r->key=key;
		r->sum=0;
		r->stu->_Mark=mark;
		cout<<"请输入姓名"<<endl;
		fflush(stdin);
		gets(r->stu->_Name);
		cout<<"请输入学号"<<endl;
		gets(r->stu->_Number);
		r->left=NULL;
		r->right=NULL;		
		if(!root){
			return r;
		}
		else if(r->key>root->key){
			root->right=r;
		//	root->left=NULL;
		}
		else {
			root->left=r;
		//	root->right=NULL;
		}
		return root;

	}
	else{
		if (key>(r->key))_add_tree(r,r->right,mark,key);
		else if(key<(r->key))_add_tree(r,r->left,mark,key);
		else{//插入到本节点
			int i=0;
			while (r->stu[i]._Mark<mark && i<=r->sum) i++;
			(r->sum)++;
			if(i==r->sum) r->stu[i]._Mark=mark;
			else{
				int j;
				for(j=r->sum;j>i;j--)
					r->stu[j]=r->stu[j-1];//全部后移
				r->stu[i]._Mark=mark;
			}
	
			cout<<"请输入姓名"<<endl;
			fflush(stdin);
			gets(r->stu[i]._Name);
			cout<<"请输入学号"<<endl;
			gets(r->stu[i]._Number);
			
		}return r;
	}

}

//初始化函数,把二叉树的结构进行搭建
//形成按照成绩段排布的二叉树结构
//参数:无
//返回:根节点
//调试成功:5-1 17:46
struct tree *_init_tree(){
	int i=0,mark=0;
	struct tree *p=NULL;
	struct tree *root=NULL;
	for (;i<20;i++){
		cout<<"请输入成绩(0就退出)"<<endl;
		cin>>mark;
		if(!mark)return root;
		root=_add_tree(root,root,mark,mark2key(mark));

	}
	return root;
}
//删除辅助函数
//参数:跟节点
//
struct tree*deletemin(struct tree*&root){
	struct tree*temp;
	if(!root)return 0;
	if(root->left)return deletemin(root->left);
	else{
		temp=root;
		root=root->right;
		return temp;
	}
}
//删除节点函数
//指定关键码
struct tree*removehelp(struct tree*root,int key)
{
	struct tree*p,*temp;
	if(!root)return NULL;
	if(root->key==key){
		if(root->left==root->right){
			free(root);
			return NULL;
		}
		else{
			if(root->left==NULL){
				p=root->right;
				free(root);
				return p;
			}
			else{
				if(root->right==NULL){
					p=root->left;
					free(root);
					return p;
				}
				else{
					temp=deletemin(root->right);
					root->key=temp->key;
					root->sum=temp->sum;
					for(int i=0;i<=temp->sum;i++){
						root->stu[i]=temp->stu[i];

					}
					return root;
				}
			}
		}
	}
	else{
		if(root->key<key)root->right=removehelp(root->right,key);
		else root->left=removehelp(root->left,key);
		return root;
	}

}

//学生删除
//参数:指定学号
//
struct tree*remove_stu (struct tree *root,char *num)
{	
	struct tree **vec,*r=root;
	int front=0,rear=0,i,j,flag=0;
	vec=(struct tree**)malloc(11*(sizeof(struct tree *)));//把所有节点都装载在这个数组里边
	*(vec+rear)=r;
	rear++;
	while (front<rear)	//考虑了可能重名的情况
	{
		r=*(vec+front);
		front++;
		if (r->left)
		{
			*(vec+rear)=r->left;
			rear++;
		}
		if (r->right)
		{
			*(vec+rear)=r->right;
			rear++;
		}
		i=0;
		while (i<=r->sum && flag==0)
		{
			if (strcmp(num,r->stu[i]._Number)==0)
			{
				(r->sum)--;
				for (j=i;j<=r->sum;j++)
					r->stu[j]=r->stu[j+1];				
				flag=1;//可以跳出循环
			}
			i++;
		}
		if (r->sum==-1)		//若节点中已无任何学生,则可以删除节点
			root=removehelp(root,r->key);
	};
	//if(!flag)return NULL;//如果没有找到,就返回0;
	return(root);
}




//辅助输出函数
//参数:节点地址
//功能:输出所有信息
int  _print (struct tree *root)
{
	if(!root)return 0;
	key2char(root->key);
	cout<<": "<<endl;
	for (int i=0;i<=root->sum;i++)	//输出格式为"学号 姓名 成绩"
		cout<<root->stu[i]._Number<<"\t"<<root->stu[i]._Name<<"\t"<<root->stu[i]._Mark<<endl;
	return 1;
}
//中序遍历并输出函数
//中序遍历
struct tree*inorder(struct tree*root){
	if(!root){
		return 0;
	}
	inorder(root->left);
	_print(root);
	inorder(root->right);
	return 0;

}
//学生总数统计函数
//返回学生总数
//参数:根节点
int _get_sum(struct tree*root){
	//这样设计数据是否合适
	int sum=0;
	if(!root)return 0;

	sum=sum+_get_sum(root->left);
	sum=sum+_get_sum(root->right);
	sum=root->sum+1+sum;
	return sum;
}
//求所有分数之和
int total_mark(struct tree*root){
	if (root)
	{
		int temp=0;
		int i;
		for (i=0;i<=root->sum;i++)
			temp=temp+root->stu[i]._Mark;
		return(temp+total_mark(root->left)+total_mark(root->right));
	}
	else return 0;
}
//层次遍历函数
//参数:根节点
//
int inorder_layer(struct tree*root){
	if(!root)return 0;
	struct tree**vec;
	struct tree*r=root;
	int front=0,rear=0;
	vec=(struct tree**)malloc(11*sizeof(struct tree*));//指向指针的指针
	*vec=root;
	if(root)_print(root);
	rear++;
	while(front<rear){
		r=*(vec+front);
		front++;
		if(r->left){
			*(vec+rear)=r->left;
			rear++;
			_print(r->left);
		}
		if(r->right){
			*(vec+rear)=r->right;
			rear++;
			_print(r->right);
		}
		//cout<<"这一层已经完毕"<<endl;
	}
	return 1;
	
}
//检索函数
//功能:按照关键码检索
int search_key(struct tree*root,int key){
	if(!root)return 0;
	if(root->key==key){
		_print(root);
		return 1;
	}
	if((root->key)>key)search_key(root->left,key);
	else search_key(root->right,key);
	return 1;
}
//检索函数
//功能:按照姓名检索
int search_name(struct tree*root,char name[10]){
	if(!root)return 0;
		int flag=0;
		if((search_name(root->left,name)||search_name(root->right,name)))flag=1;
		for(int i=0;i<=root->sum;i++){
				if(!strcmp(name,root->stu[i]._Name)){
					cout<<root->stu[i]._Number<<"\t"<<root->stu[i]._Name<<"\t"<<root->stu[i]._Mark<<endl;
					flag=1;
			}

		}
		if(flag)return 1;
		return 0;//0表示这部分没有检索到
}
//检索函数
//功能:按照分数检索
int search_mark(struct tree*root,int mark){
	int key=mark2key(mark),flag=0;
	if(!root)return 0;
	if(root->key==key){
		for(int i=0;i<=root->sum;i++){
			if(mark==root->stu[i]._Mark){
				cout<<root->stu[i]._Number<<"\t"<<root->stu[i]._Name<<"\t"<<root->stu[i]._Mark<<endl;
				flag=1;
			}
		}
		if(!flag){
			cout<<"检索失败,没有这个分数"<<endl;
			return 0;
		}
		return 1;
	}
	if((root->key)>key)search_mark(root->left,mark);
	else search_mark(root->right,mark);
	return 1;
}
//检索函数
//按照学号检索
//返回有无检索到
int search_num(struct tree*root,char num[10]){
	if(!root)return 0;
	int flag=0;
	if((search_num(root->left,num)||search_num(root->right,num)))flag=1;
	for(int i=0;i<=root->sum;i++){
			if(!strcmp(num,root->stu[i]._Number)){
				cout<<root->stu[i]._Number<<"\t"<<root->stu[i]._Name<<"\t"<<root->stu[i]._Mark<<endl;
				flag=1;
			
		}

	}
	if(flag)return 1;
	return 0;//0表示这部分没有检索到
}
//检索入口
//参数:跟节点
//功能:根据选择调用不同的函数
void search_path(struct tree*root){
	
	int _flag=1,choice=0;
	do{
		cout<<"请选择你要检索的方式"<<endl;
		cout<<"1 按照学号检索他的成绩"<<endl;
		cout<<"2 按照姓名检索她的成绩"<<endl;
		cout<<"3 指定一个分数检索同一成绩有多少学生"<<endl;
		cout<<"4 指定一个分数范围(按成绩段整合)"<<endl;
		cout<<"其他 退出"<<endl;
		cin>>choice;
		switch (choice)
		{
		case 1:
			char num[10];
			cout<<"请输入学号"<<endl;
			cin>>num;
			search_num(root,num);
			break;
		case 2:
			char name[10];
			cout<<"请输入姓名"<<endl;
			cin>>name;
			search_name(root,name);
			break;
		case 3:
			int mark;
			cout<<"请输入分数"<<endl;
			cin>>mark;
			search_mark(root,mark);
			break;
		case 4:
			int key;
			cout<<"请输入分数范围"<<endl;
			cout<<"0	分数<50"<<endl;
			cout<<"1	分数50-59"<<endl;
			cout<<"2	分数60-65"<<endl;
			cout<<"3	分数66-69"<<endl;
			cout<<"4	分数70-75"<<endl;
			cout<<"5	分数76-79"<<endl;
			cout<<"6	分数80-85"<<endl;
			cout<<"7	分数86-89"<<endl;
			cout<<"8	分数90-95"<<endl;
			cout<<"9	分数96-100"<<endl;
			cin>>key;
			if((key<0)||(key>9)){
				cout<<"没有这个分数段"<<endl;
				break;
			}
			search_key(root,key);
			break;
		default:
			fflush(stdin);
			_flag=0;
			break;
		}
	}while(_flag);

}


//求平均值函数
//参数:节点
double average(struct tree*root){

	double _sum=0,_mark=0;
	if(!(_sum=(double)_get_sum(root))){
		cout<<"总数为零"<<endl;
		return 0;
	}
	_mark=(double)total_mark(root);
	

	return _mark/_sum;
}

//求方差辅助函数
//返回值:各分数与平均值的平方和
double fch_help(struct tree*root){
	if (root)
	{
		double temp=0;
		int i;
		double average_root=average(root);
		for (i=0;i<=root->sum;i++)
			temp+=((double)root->stu[i]._Mark-average_root)*((double)root->stu[i]._Mark-average_root);
		return(temp+fch_help(root->left)+fch_help(root->right));
	}
	else return 0;
}
//求方差函数
//参数:节点
double fch(struct tree*root){
	double temp1=fch_help(root);
	double temp2=(double)_get_sum(root);
	return temp1/temp2;
}
//求最大值最小值
//
void _Max_Min(struct tree*root){
	struct tree *p=root,*q=root;
	while (p)
	{
		q=p;
		p=p->right;
	}
	if (q) cout<<"成绩最小值为: "<<q->stu[q->sum]._Mark<<endl;
	else cout<<"树为空!"<<endl;
	p=q=root;
	while (p)
	{
		q=p;
		p=p->left;
	};
	if (q) cout<<"成绩最大值为: "<<q->stu[0]._Mark<<endl;
	else cout<<"树为空!"<<endl;

}
//二叉树存盘辅助韩素
int save_tree_help(struct tree*root,FILE *fp){
	if(!root)return 0;
	fwrite(root,sizeof(struct tree),1,fp);
	save_tree_help(root->left,fp);
	save_tree_help(root->right,fp);
	return 1;
}

//二叉树存盘
//参数:根节点
int save_tree(struct tree*root){
	char location[10];
	cout<<"请输入所要保存的文件名"<<endl;
	cin>>location;
	FILE *fp;
	if(!(fp=fopen(location,"wt"))){cout<<"文件无法打开"<<endl;return 0;}
	save_tree_help(root,fp);
	fclose(fp);
	return 1;
}
//二叉树恢复辅助函数
//
struct tree*load_tree_help(FILE*fp){
	struct tree*root=(struct tree*)malloc(sizeof(struct tree));
	
	fread(root,sizeof(struct tree),1,fp);
	if(!root)return 0;
	if(root->left)root->left=load_tree_help(fp);
	if(root->right)root->right=load_tree_help(fp);
	return root;
}
//二叉树恢复函数
//
struct tree* load_tree(struct tree*root){
	char location[10];
	cout<<"请输入所要恢复的文件名"<<endl;
	cin>>location;
	FILE *fp;
	if(!(fp=fopen(location,"rt"))){cout<<"文件无法打开"<<endl;return 0;}
	root=load_tree_help(fp);
	fclose(fp);
	return root;//绝对必要的
}
//建堆函数
//push
int push(struct tree*p[M],struct tree*x,int top){
//	struct tree*r=p;
	if(top==M-1)printf("Overflow");
	else{
		top++;	
//		r=p+top;
//		*r=*x;
		*(p+top)=x;
		//*(p+top)=x;
	}
	return top;
}
//弹出函数
int pop(struct tree*p[M],struct tree*&x,int top){
	if(top<0)printf("Overflow");
	else{
		x=*(p+top);
		top--;
	}
	return top;
}

//中序线索化树之后的节点遍历函数
struct tree*clewprintf(struct tree*root){
	struct tree*q,*p;
	long ia;
	q=root;p=q;
	while(q){p=q;q=q->left;}
	while(1){
		_print(p);
		if(!p->right)return 0;
		if((long)p->right<0){
			ia=-(long)p->right;
			p=(struct tree*)ia;
		}
		else{
			p=p->right;
			while((long)p->left>0)p=p->left;
		}
	}
}

//中序线索化函数
struct tree*inorder_clew(struct tree*root)
{
	struct tree*p,*&rp=p,*pr=NULL,*s[M],*temp;
	int top=-1;
	long ia;
	p=root;
	temp=(struct tree*)s;//课本上的BUG
	for(;;){
		while(p){top=push(s,rp,top);p=p->left;}
		if(top==-1)break;
		else{
			top=pop(s,rp,top);
			if(pr){
				if(!pr->right){
					ia=-(long)p;
					pr->right=(struct tree*)ia;
				}
				else if(!p->left){
					ia=-(long)pr;
					p->left=(struct tree*)ia;
				}
			}
			pr=p;
			p=p->right;
		}
	}
	clewprintf(root);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -