C语言平衡二叉排序树:学生管理系统

这个程序实现了二叉搜索树的插入、查找、删除操作,并通过旋转方法保持树的平衡。用户可以进行学生成绩管理,包括添加、查找、显示所有成绩和删除成绩。程序使用C语言编写,适用于VS2019编译器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#define MAX(A, B)   ((A)>(B)?(A):(B)) 
#define Malloc(type) (type*)malloc(sizeof(type)) 

struct stu_grade
{
	char stu_name[15];//姓名
	float grade;//成绩
	char number[15];//编号(学号)
};

typedef struct student_list
{
	struct student_list* lchild;//左孩子
	struct student_list* rchild;//右孩子
	int height;
	struct stu_grade perfor_info;//学生结构体类型的数据
}student_node;

void tree_for_each(student_node* root);//所有结点数据,递归
int get_tree_height(student_node* root);//得到二叉树高度,递归
void ui();//菜单提示信息 
void menu(int choose);//根据输入决定程序去向 

student_node* remove_tree_node(student_node* root, char rm_value[]);//删除节点 ,递归
student_node* request_student_node(stu_grade* value);//申请二叉树节点 
student_node* tree_node_rotate_right(student_node* root);//左左不平衡 
student_node* tree_node_rotate_left(student_node* root);//右右不平衡
student_node* tree_node_rotate_left_right(student_node* root);//左右不平衡 
student_node* tree_node_rotate_right_left(student_node* root);//解决右左不平衡
student_node* insert_node_to_tree(student_node* root, student_node* new_node);//插入学生数据,递归
student_node* find_tree_node(student_node* root, char input_value[]);//查找节点 ,递归

char input_value[15];
stu_grade input_student_data;
student_node* root = NULL;
student_node* new_node, * find_node;
bool sign = false;//标记是否找到结点

int main()
{
	int choose;
	while (1)
	{
		sign = false;
		system("cls");
		ui();
		scanf_s("%d", &choose);
		menu(choose);
		system("pause");
	}
	return 0;
}

int get_tree_height(student_node* root)
{
	if (root == NULL)	return 0;
	return MAX(get_tree_height(root->lchild), get_tree_height(root->rchild)) + 1;//递归
}

student_node* request_student_node(stu_grade* value)
{
	student_node* new_node;
	new_node = Malloc(student_node);
	if (new_node == NULL)
	{
		printf("没有申请到二叉树节点,学生系统异常\n");
		return NULL;
	}
	if (value != NULL)
	{
		new_node->perfor_info = *value;
		new_node->lchild = NULL;
		new_node->rchild = NULL;
	}
	return new_node;
}


student_node* tree_node_rotate_right(student_node* root)//左左不平衡 
{
	student_node* tmp;
	tmp = root->lchild;
	root->lchild = tmp->rchild;
	tmp->rchild = root;
	tmp->height = get_tree_height(tmp);
	root->height = get_tree_height(root);
	return tmp;
}

student_node* tree_node_rotate_left(student_node* root)//右右不平衡
{
	student_node* tmp;
	tmp = root->rchild;
	root->rchild = tmp->lchild;
	tmp->lchild = root;
	tmp->height = get_tree_height(tmp);
	root->height = get_tree_height(root);
	return tmp;
}

student_node* tree_node_rotate_left_right(student_node* root)//左右不平衡 
{
	root->lchild = tree_node_rotate_left(root->lchild);
	root = tree_node_rotate_right(root);
	return root;
}


student_node* tree_node_rotate_right_left(student_node* root)//右左不平衡
{
	root->rchild = tree_node_rotate_right(root->rchild);
	root = tree_node_rotate_left(root);
	return root;
}


student_node* insert_node_to_tree(student_node* root, student_node* new_node)//插入学生数据
{
	if (root == NULL)	return new_node;
	if (strcmp(root->perfor_info.number,new_node->perfor_info.number)>0)	root->lchild = insert_node_to_tree(root->lchild, new_node);
	else	root->rchild = insert_node_to_tree(root->rchild, new_node);

	if (get_tree_height(root->lchild) - get_tree_height(root->rchild) == 2)
	{
		if (strcmp(new_node->perfor_info.number,root->lchild->perfor_info.number)<0)	root = tree_node_rotate_right(root);
		else	root = tree_node_rotate_left_right(root);
	}
	else if (get_tree_height(root->rchild) - get_tree_height(root->lchild) == 2)
	{

		if (strcmp(new_node->perfor_info.number,root->rchild->perfor_info.number)>=0)
		{
			root = tree_node_rotate_left(root);
		}
		else	root = tree_node_rotate_right_left(root);
	}
	root->height = get_tree_height(root);
	return root;
}


student_node* find_tree_node(student_node* root, char input_value[])//递归过程 
{
	if (root == NULL)	return NULL;
	if (strcmp(root->perfor_info.number,input_value)>0)	return find_tree_node(root->lchild, input_value);
	else if (strcmp(root->perfor_info.number,input_value)<0)	return find_tree_node(root->rchild, input_value);
	return root;
}


void tree_for_each(student_node* root)
{
	if (root == NULL)	return;
	tree_for_each(root->lchild);
	sign = true;
	printf("编号:%s,学生姓名:%s,学生成绩:%.2f\n", root->perfor_info.number, root->perfor_info.stu_name, root->perfor_info.grade);
	tree_for_each(root->rchild);
}


student_node* remove_tree_node(student_node* root, char rm_value[])
{
	student_node* tmp;
	if (root == NULL)	return NULL;
	if (strcmp(root->perfor_info.number,rm_value)==0)
	{
		if (root->lchild == NULL && root->rchild == NULL)
		{
			free(root);
			return NULL;
		}
		else if (root->lchild != NULL)//如果有左子树
		{
			for (tmp = root->lchild; tmp->rchild != NULL; tmp = tmp->rchild);
			strcpy_s(root->perfor_info.number, tmp->perfor_info.number);
			root->lchild = remove_tree_node(root->lchild, tmp->perfor_info.number);
		}
		else//如果只有右子树
		{
			for (tmp = root->rchild; tmp->lchild != NULL; tmp = tmp->lchild);
			strcpy_s(root->perfor_info.number, tmp->perfor_info.number);
			root->rchild = remove_tree_node(root->rchild, tmp->perfor_info.number);
		}
	}
	else if (strcmp(rm_value,root->perfor_info.number)<0)
	{
		root->lchild = remove_tree_node(root->lchild, rm_value);
	}
	else
	{
		root->rchild = remove_tree_node(root->rchild, rm_value);
	}

	if (get_tree_height(root->lchild) - get_tree_height(root->rchild) == 2)//左不平衡
	{
		if (get_tree_height(root->lchild->lchild) - get_tree_height(root->lchild->rchild) == 1)
		{			//左左不平衡
			root = tree_node_rotate_right(root);
		}
		else
		{											//否则则是插入到root->lchild的右边去,出现了左右不平衡
			root = tree_node_rotate_left_right(root);
		}
	}
	else if (get_tree_height(root->rchild) - get_tree_height(root->lchild) == 2)//右不平衡
	{
		if (get_tree_height(root->rchild->rchild) - get_tree_height(root->rchild->lchild) == 1)//右右不平衡
		{
			root = tree_node_rotate_left(root);
		}
		else//右左不平衡
		{
			root = tree_node_rotate_right_left(root);
		}
	}
	root->height = get_tree_height(root);

	return root;
}

void ui()
{
	printf("****************************************************\n");
	printf("****************欢迎来到学生成绩管理系统************\n");
	printf("****************请输入数字选择相应的指令************\n");
	printf("*****************1、增加插入学生的成绩**************\n");
	printf("*****************2、搜索学生成绩********************\n");
	printf("*****************3、打印所有学生的成绩**************\n");
	printf("*****************4、删除学生的成绩******************\n");
	printf("*****************5、退出管理系统********************\n");
	printf("****************************************************\n");
}

void menu(int choose)
{
	switch (choose)
	{
	case 1:									//创建一个新的二叉树 
		student_node * root3;
		root3 = root;
		printf("请您输入学生的编号:\n");
		scanf_s("%s", input_student_data.number,15);
		root3 = find_tree_node(root3, input_student_data.number);
		if (root3 != NULL)
		{
			printf("这个学生已经存在于这个系统中\n");
			break;
		}

		printf("请您输入学生的姓名:\n");
		scanf_s("%s", input_student_data.stu_name,15);

		printf("请您输入学生的成绩:\n");
		scanf_s("%f", &input_student_data.grade);

		new_node = request_student_node(&input_student_data);

		root = insert_node_to_tree(root, new_node);
		break;

	case 2:									//查找 
		printf("请输入学生的编号来查询学生成绩信息\n");
		scanf_s("%s", &input_value,15);

		find_node = find_tree_node(root, input_value);
		if (find_node == NULL)
		{
			printf("找不到该学生的信息\n");
			break;
		}
		printf("编号:%s,学生姓名:%s,学生成绩:%.2f\n", find_node->perfor_info.number, find_node->perfor_info.stu_name, find_node->perfor_info.grade);
		break;

	case 3:									//输出所有节点信息 
		printf("所有的学生的成绩信息为\n");
		tree_for_each(root);
		if (sign == false)	printf("系统中没有学生的信息\n");
		break;

	case 4:									//删除一个节点信息 
		student_node * root2;
		root2 = root;
		printf("请输入学生的编号来删除学生成绩信息\n");
		scanf_s("%s", &input_value,15);
		root2 = find_tree_node(root2, input_value);
		if (root2 == NULL)
		{
			printf("错误:没有找到这个学生:%.2f\n", input_value);
			break;
		}
		root = remove_tree_node(root, input_value);
		break;

	case 5:									//退出系统 
		exit(0);

	}
}

编译器:VS2019

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值