C++ AVL树管理系统(可作为数据结构课程设计参考下)

C++ AVL树管理系统

C++ AVL树管理系统使用平衡二叉树AVL来进行写一个管理系统

  • 没有平衡二叉树基础的同学可以先去了解一下,这里不多讲
  • 这里说一下平衡二叉树的特点:AVL树中任何节点的两个子树的高度最大差别为1,想要了解更多可以先去学习

话不多说,直接上代码:

//**********************************头文件
#include <iostream>		//标准输入输出流
#include <cstdlib>		//system函数
#include <iomanip>		//输出格式控制
#include <stack>		//C++ STL中的 栈结构
using namespace std;	//标准名称空间

//**************************************类声明、函数声明

//二叉平衡树
class AVLTree
{
public:
	//学生信息
	typedef struct Student
	{
		long long id;//学号
		char sex[5];//性别
		char name[20];//姓名
		char grade[20];//班级
	}Student;
	//二叉树结点
	typedef struct node
	{
		Student data;//学生信息
		int height;//结点高度
		struct node* lchild;//左子树
		struct node* rchild;//右子树
	}node;
public:
	AVLTree();//空构造函数
	~AVLTree();//析构函数

	void Push(Student data);//插入
	void Pop(Student data);//删除
	void Show();//中序遍历
	node* Search(Student data);//搜索数据
	bool Empty();//是否为空

	friend ostream& operator<<(ostream& os, Student& data);//输出流重载
	friend bool operator>(Student& data1, Student& data2);//大于号重载
	friend bool operator<(Student& data1, Student& data2);//小于号重载
	friend bool operator!=(Student& data1, Student& data2);//不等号重载
	friend bool operator==(Student& data1, Student& data2);//等号重载
private:
	node* root;//根结点
	int getHeight(node* target);//获取结点高度
	void Adjust(stack<node*>& nodestack);//结点调整
	node* LLrotate(node* cur);//左左旋转
	node* RRrotate(node* cur);//右右旋转
	node* LRrotate(node* cur);//左右旋转
	node* RLrotate(node* cur);//右左旋转
};
//系统类
class System
{
public:
	System() :input(0) {}//构造函数
	void Main();//系统主进程
private:
	void Menu();//菜单
	void Push();//插入
	void Pop();//删除
	void Search();//查找
	void Show();//浏览
	void Message(const char* msg);//消息提示框
	void HeadLine();//打印表头
	int input;//用户的输入
	AVLTree tree;//平衡二叉树结构 存储数据
};

//**************************************主函数
int main()
{
	System sys;
	sys.Main();
	return 0;
}

//**************************************类实现、函数实现
//------------------------------System------------

//菜单
void System::Menu()
{
	{
		cout << "|------------------------------------------------|" << endl;
		cout << "|                  学籍管理系统                  |" << endl;
		cout << "|------------------------------------------------|" << endl;
		cout << "|                 1.添加学生信息                 |" << endl;
		cout << "|                 2.查找学生信息                 |" << endl;
		cout << "|                 3.浏览全部信息                 |" << endl;
		cout << "|                 4.删除学生信息                 |" << endl;
		cout << "|                 5.退出管理系统                 |" << endl;
		cout << "|------------------------------------------------|" << endl;
		cout << "                 请输入您的选择:";
	}
}
//系统主进程
void System::Main()
{
	while (1)//程序主循环
	{
		Menu();//打印菜单
		cin >> input;
		switch (input)
		{
		case 1://添加
			Push();
			break;
		case 2://查找
			Search();
			break;
		case 3://浏览
			Show();
			break;
		case 4://删除
			Pop();
			break;
		case 5://退出
			Message("欢迎下次使用!");
			return;//退出主进程
			break;
		default:
			cin.clear();//重置输入流
			cin.ignore(1024, '\n');//清空输入流
			Message("输入格式有误!");
			break;
		}
		system("pause");//按任意键继续
		system("cls");//清屏
	}
}
//插入学生
void System::Push()
{
	Message("1.添加学生信息");
	AVLTree::Student data = { 0 };
	cout << "请输入学生学号:";
	cin >> data.id;//输入学号
	cout << "请输入学生姓名:";
	cin >> data.name;//输入姓名
	cout << "请输入学生性别:";
	cin >> data.sex;//输入性别
	cout << "请输入学生班级:";
	cin >> data.grade;//输入班级
	if (cin.fail())
	{
		cout << endl;
		Message("输入格式错误!");
		cin.clear();//重置输入流
		cin.ignore(1024, '\n');//清空输入流
		return;
	}
	tree.Push(data);//插入数据
	Message("学生添加成功!");
}
//删除学生
void System::Pop()
{
	Message("4.删除学生信息");
	AVLTree::Student target = { 0 };
	cout << "请输入需要删除的学生学号:";
	cin >> target.id;//输入目标学生学号
	if (cin.fail())
	{
		cout << endl;
		Message("输入格式错误!");
		cin.clear();//重置输入流
		cin.ignore(1024, '\n');//清空输入流
		return;
	}
	AVLTree::node* result = tree.Search(target);//接收查找到的数据
	if (result == nullptr)//未找到
	{
		Message("该学生不存在!");
		return;
	}
	HeadLine();//打印表头
	cout << result->data;//提示信息
	tree.Pop(target);//删除学生
	cout << endl;
	Message("学生删除成功!");
}
//查找学生
void System::Search()
{
	Message("2.查找学生信息");
	AVLTree::Student target = { 0 };
	cout << "请输入学生学号:";
	cin >> target.id;//输入目标学生学号
	if (cin.fail())
	{
		cout << endl;
		Message("输入格式错误!");
		cin.clear();//重置输入流
		cin.ignore(1024, '\n');//清空输入流
		return;
	}
	AVLTree::node* result = tree.Search(target);//接收查找结果
	if (result == nullptr)//未找到学生
	{
		Message("未找到该学生!");
		return;
	}
	else//找到学生
	{
		//打印数据
		HeadLine();//打印表头
		cout << result->data << endl;
	}
}
//浏览学生
void System::Show()
{
	Message("3.浏览全部信息");
	if (tree.Empty())
	{
		Message("没有学生信息!");
		return;
	}
	HeadLine();//打印表头
	tree.Show();//打印数据
}
//消息提示框
void System::Message(const char* msg)
{
	cout << "|-----------------" << msg << "-----------------|" << endl;
}
//打印表头
void System::HeadLine()
{
	cout << "|------------|--------|----|---------------------|" << endl
		<< std::left
		<< setw(13) << "|    学号" << setw(9) << "|  姓名"
		<< setw(5) << "|性别" << setw(21) << "|        班级         |"
		<< endl
		<< "|------------|--------|----|---------------------|" << endl;
}

//------------------------------AVLTree-----------

//空构造函数
AVLTree::AVLTree()
{
	root = nullptr;
}
//析构函数
AVLTree::~AVLTree()
{
	if (root == nullptr)//空树
		return;//退出函数
	stack<node*> nodestack;
	node* cur = root;
	nodestack.push(cur);
	while (!nodestack.empty())
	{
		cur = nodestack.top();//获取栈顶元素
		nodestack.pop();//出栈
		if (cur->lchild != nullptr)
			nodestack.push(cur->lchild);//左子树不为空则入栈
		if (cur->rchild != nullptr)
			nodestack.push(cur->rchild);//右子树不为空则入栈
		delete cur;
		cur = nullptr;
	}
}
//插入
void AVLTree::Push(Student data)
{
	if (root == nullptr)//空树
	{
		root = new node;
		if (root == nullptr)//创建结点失败
			return;
		root->data = data;
		root->height = 1;//根结点高度为1
		root->lchild = nullptr;
		root->rchild = nullptr;
	}
	else//非空树
	{
		node* cur = root;
		stack<node*> nodestack;
		while (cur != nullptr)
		{
			nodestack.push(cur);//记录路径
			if (data > cur->data)//学号大  向右走
				cur = cur->rchild;
			else if (data < cur->data)//学号小  向左走
				cur = cur->lchild;
			else
				return;//数据相等  退出函数
		}
		cur = nodestack.top();//获取栈顶元素
		nodestack.pop();//出栈
		node* newnode = new node;//创建新结点
		if (newnode == nullptr)//结点创建失败
			return;
		newnode->data = data;//数据迁移
		newnode->height = 1;//新结点的高度为1
		newnode->rchild = nullptr;//左右子树置为空
		newnode->lchild = nullptr;
		if (data > cur->data)//将新结点连接至树上
			cur->rchild = newnode;
		else if (data < cur->data)
			cur->lchild = newnode;
		cur->height = max(getHeight(cur->lchild), getHeight(cur->rchild)) + 1;//重置当前结点高度
		Adjust(nodestack);//沿路径调整
	}
}
//删除
void AVLTree::Pop(Student data)
{
	if (root == nullptr)//空树
		return;
	node* cur = root;
	stack<node*> nodestack;//创建结点栈  记录路径
	while (cur->data != data)
	{
		nodestack.push(cur);//记录路径
		if (data > cur->data)
		{
			if (cur->rchild != nullptr)
				cur = cur->rchild;
			else
				return;//未找到
		}
		else if (data < cur->data)
		{
			if (cur->lchild != nullptr)
				cur = cur->lchild;
			else
				return;//未找到
		}
	}
	//找到了
	if (cur->lchild == nullptr && cur->rchild == nullptr)//叶子结点
	{
		if (nodestack.empty())//栈为空  说明是根结点
		{
			delete root;
			root = nullptr;
			return;
		}
		node* parent = nodestack.top();//获取栈顶元素
		if (parent->lchild == cur)
			parent->lchild = nullptr;
		else if (parent->rchild == cur)
			parent->rchild = nullptr;
		delete cur;//删除结点
	}
	else if (cur->lchild == nullptr || cur->rchild == nullptr)//其中一颗子树为空
	{
		if (cur->lchild == nullptr)//左子树为空
		{
			if (nodestack.empty())//栈为空  说明是根结点
			{
				root = cur->rchild;//更结点变更
				delete cur;//删除结点
				return;//退出函数
			}
			node* parent = nodestack.top();//获取栈顶元素  父结点
			if (parent->lchild == cur)
				parent->lchild = cur->rchild;//断开连接
			else if (parent->rchild == cur)
				parent->rchild = cur->rchild;
			delete cur;//删除结点
		}
		else if (cur->rchild == nullptr)//右子树为空
		{
			if (nodestack.empty())//栈为空  说明是根结点
			{
				root = cur->lchild;
				delete cur;
				return;
			}
			node* parent = nodestack.top();
			if (parent->lchild == cur)
				parent->lchild = cur->lchild;
			else if (parent->rchild == cur)
				parent->rchild = cur->lchild;
			delete cur;//删除结点
		}
	}
	else//两颗子树都存在的情况
	{
		nodestack.push(cur);//当前结点入栈  记录路径
		node* precursor = cur->lchild;//寻找前驱结点
		node* pre = cur;//前驱结点父结点
		if (cur->lchild->rchild == nullptr)//前驱结点在子树上
		{
			cur->data = precursor->data;//数据迁移
			cur->lchild = precursor->lchild;//断开连接
			delete precursor;//删除结点
			cur->height = max(getHeight(cur->lchild), getHeight(cur->rchild)) + 1;//重新计算结点高度
		}
		else//前驱结点不在子树上
		{
			while (precursor->rchild != nullptr)
			{
				nodestack.push(precursor);//放入栈  记录路径
				pre = precursor;//记录前驱结点父结点
				precursor = precursor->rchild;//前驱结点向右移动
			}
			cur->data = precursor->data;//数据迁移
			pre->rchild = nullptr;//断开连接
			delete precursor;//删除结点
		}
	}
	Adjust(nodestack);//沿路径回栈调整结点
}
//中序遍历  数据升序
void AVLTree::Show()
{
	if (root == nullptr)
		return;
	stack<node*> nodestack;
	node* cur = root;
	while (cur != nullptr || !nodestack.empty())
	{
		while (cur != nullptr)
		{
			nodestack.push(cur);
			cur = cur->lchild;
		}
		if (!nodestack.empty())
		{
			cur = nodestack.top();
			nodestack.pop();
			cout << cur->data << endl;
			cur = cur->rchild;
		}
	}
}
//查找数据
AVLTree::node* AVLTree::Search(Student data)
{
	node* cur = root;
	while (cur != nullptr)
	{
		if (cur->data == data)//学号匹配  返回数据
			return cur;
		else if (data > cur->data)
			cur = cur->rchild;
		else if (data < cur->data)
			cur = cur->lchild;
	}
	return nullptr;//没找到
}
//是否为空
bool AVLTree::Empty()
{
	return root == nullptr;
}
//获取结点高度
int AVLTree::getHeight(node* target)
{
	if (target == nullptr)//空结点
		return 0;
	else
		return target->height;
}
//沿路径调整结点
void AVLTree::Adjust(stack<node*>& nodestack)
{
	node* result = nullptr;//调整结果
	node* cur = nullptr;
	while (!nodestack.empty())
	{
		cur = nodestack.top();//获取栈顶元素
		nodestack.pop();//出栈
		cur->height = max(getHeight(cur->lchild), getHeight(cur->rchild)) + 1;//调整高度
		if (abs(getHeight(cur->lchild) - getHeight(cur->rchild)) >= 2)//平衡因子大于2 需要调整
		{
			if (getHeight(cur->lchild) > getHeight(cur->rchild))//左子树大于右子树
			{
				if (getHeight(cur->lchild->lchild) > getHeight(cur->lchild->rchild))//LL旋转
					result = LLrotate(cur);
				else if (getHeight(cur->lchild->lchild) < getHeight(cur->lchild->rchild))//LR旋转
					result = LRrotate(cur);
			}
			else if (getHeight(cur->lchild) < getHeight(cur->rchild))//右子树大于左子树
			{
				if (getHeight(cur->lchild->lchild) > getHeight(cur->lchild->rchild))//RL旋转
					result = RLrotate(cur);
				else if (getHeight(cur->lchild->lchild) < getHeight(cur->lchild->rchild))//RR旋转
					result = RRrotate(cur);
			}
			//将调整结果连接至树中
			if (nodestack.empty())//路径为空  没有父结点
				root = result;
			else if (nodestack.top()->lchild == cur)//连接至左子树
				nodestack.top()->lchild = result;
			else if (nodestack.top()->rchild == cur)//连接至右子树
				nodestack.top()->rchild = result;
		}
	}
}
//LL旋转
AVLTree::node* AVLTree::LLrotate(node* cur)
{
	//旋转
	node* curLeft = cur->lchild;
	cur->lchild = curLeft->rchild;
	curLeft->rchild = cur;
	//高度调整
	cur->height = max(getHeight(cur->lchild), getHeight(cur->rchild)) + 1;
	curLeft->height = max(getHeight(curLeft->lchild), getHeight(curLeft->rchild)) + 1;
	//返回子树根结点
	return curLeft;
}
//RR旋转
AVLTree::node* AVLTree::RRrotate(node* cur)
{
	//旋转
	node* curRight = cur->rchild;
	cur->rchild = curRight->lchild;
	curRight->lchild = cur;
	//高度调整
	cur->height = max(getHeight(cur->lchild), getHeight(cur->rchild)) + 1;
	curRight->height = max(getHeight(curRight->lchild), getHeight(curRight->rchild)) + 1;
	//返回子树根结点
	return curRight;
}
//LR旋转
AVLTree::node* AVLTree::LRrotate(node* cur)
{
	cur->lchild = RRrotate(cur->lchild);
	return LLrotate(cur);
}
//RL旋转
AVLTree::node* AVLTree::RLrotate(node* cur)
{
	cur->rchild = LLrotate(cur->rchild);
	return RRrotate(cur);
}

//------------------------------运算符重载---------

//输出流重载
ostream& operator<<(ostream& os, AVLTree::Student& data)
{
	return os << std::left
		<< '|' << setw(12) << data.id << '|' << setw(8) << data.name
		<< '|' << setw(4) << data.sex << '|' << setw(21) << data.grade
		<< '|' << endl
		<< "|------------|--------|----|---------------------|";
}
//大于号重载
bool operator>(AVLTree::Student& data1, AVLTree::Student& data2)
{
	return data1.id > data2.id;
}
//小于号重载
bool operator<(AVLTree::Student& data1, AVLTree::Student& data2)
{
	return data1.id < data2.id;
}
//不等号重载
bool operator!=(AVLTree::Student& data1, AVLTree::Student& data2)
{
	return data1.id != data2.id;
}
//等号重载
bool operator==(AVLTree::Student& data1, AVLTree::Student& data2)
{
	return data1.id == data2.id;
}

运行效果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值