数据结构大型实验——用户登录系统
一、实验内容分析
1.实验目的
【问题描述】
在登录服务器系统时,都需要验证用户名和密码,如 telnet 远程登录服务器。用户输入
用户名和密码后,服务器程序会首先验证用户信息的合法性。由于用户信息的验证频率很高,
系统有必要有效地组织这些用户信息,从而快速查找和验证用户。另外,系统也会经常会添
加新用户、删除老用户和更新用户密码等操作,因此,系统必须采用动态结构,在添加、删
除或更新后,依然能保证验证过程的快速。请采用相应的数据结构模拟用户登录系统,其功
能要求包括用户登录、用户密码更新、用户添加和用户删除等。
【基本要求】
1. 要求自己编程实现二叉树结构及其相关功能,以存储用户信息,不允许使用标准模
板类的二叉树结构和函数。同时要求根据二叉树的变化情况,进行相应的平衡操作,
即 AVL 平衡树操作,四种平衡操作都必须考虑。测试时,各种情况都需要测试,并
附上测试截图;
2. 要求采用类的设计思路,不允许出现类以外的函数定义,但允许友元函数。主函数
中只能出现类的成员函数的调用,不允许出现对其它函数的调用。
3. 要求采用多文件方式:.h 文件存储类的声明,.cpp 文件存储类的实现,主函数 main
存储在另外一个单独的 cpp 文件中。如果采用类模板,则类的声明和实现都放在.h
文件中。
4. 要求源程序中有相应注释;
5. 不强制要求采用类模板,也不要求采用可视化窗口;
6. 要求测试例子要比较详尽,各种极限情况也要考虑到,测试的输出信息要详细易懂,
表明各个功能的执行正确;
7. 要求采用 Visual C++ 6.0 及以上版本进行调试;
2.实验中的基本数据结构
使用了平衡树(AVL)来存储用户信息,通过在插入和删除节点时左平衡和右平衡操作能
使树始终保持平衡。以下为实验中涉及到的类。
类名称
成员变量及成员函数
private:
//用户名
//密码
string name;
string password;
int h;
int bf;
UserNode *left;
UserNode *right;
UserNode *parent;
//以该节点为根的子树高度
//平衡因子:左树高度减去右树高度
//指向左子树的指针
//指向右子树的指针
//指向父亲节点的指针
UserNode
(用户信息类)
public:
friend class AVL;
1
数据结构大型实验——用户登录系统
//左子树高度
//右子树高度
UserNode();
UserNode(string n="",string p="");
int Lh();
int Rh();
void geth(); //更新以当前节点为根结点的子树高度
void getbf(); //更新当前节点的平衡因子
string getpswd();
void setpswd(string); //修改密码
friend void save(UserNode*,ostream&);
//获取密码
//输出数据
private:
public:
UserNode *root;
//查找节点
//左旋
//右旋
AVL():root(NULL){}
//构造函数
bool empty() const;
//判空
UserNode* find(string item);
void LRotate(UserNode*,UserNode*);
void RRotate(UserNode*,UserNode*);
void LRRotate(UserNode*,UserNode*,UserNode*);//左右旋
void RLRotate(UserNode*,UserNode*,UserNode*);//右左旋
void update(UserNode*);
void insert(string,string); //插入节点
bool Delete(UserNode*);
void printNode(UserNode* ,int ); //打印一个节点
void print(); //打印树
friend istream& operator >> (istream&,AVL&);
friend ostream& operator << (ostream&,AVL&);
//删除节点
//调整平衡
//输入文件
//输出文件
private:
public:
AVL user;
//主菜单
//构造函数
Menu();
void mainmenu();
void show();
void load();
void regist();
void Change(UserNode*);
void Del(UserNode*);
void close();
//查看所有用户
//登陆
//注册
//删除用户
//将用户保存到 txt 中
//修改密码
AVL(功能类)
Menu
(界面菜单类)
2
数据结构大型实验——用户登录系统
3.程序流程图
主菜单
登陆
查看所有用户
退出
注册
更
改
密
码
删
除
用
户
查
看
所
有
用
户
返
回
主
菜
单
返
回
主
菜
单
退
出
退
出
登
陆
重
新
注
册
查
看
所
有
用
户
退
出
4.类及类间关系
UserNode
AVL
menu
3
数据结构大型实验——用户登录系统
5.主要函数间调用关系
Main()
Menu menu
Menu()
Close()
menu.mainmenu()
Load()
①
AVL::find()
①Yes
Change()
regist
②
其他
②No
Del()
UserNode::setpswd(string)
AVL::Delete(UserNode
show()
close()
AVL::insert(string,string
Insert(string na, string pswd)
插入函数,参数为
用户名、密码
UserNode *item=new
定义用户节点
update(item->parent)
更新 插入 节点 路径 上
的节点
LRotate(UserNode*A ,UserNode*
RRotate(UserNode*A,UserNode*
LRRotate(UserNode*A ,UserNode*
RLRotate(UserNode*A ,UserNode*
四种旋转方式判断:
4
数据结构大型实验——用户登录系统
Delete(UserNode* )(删除函数)删除节点后更新树方式相同,但是删除方式为将要删除的
节点与其右子树中最小的节点交换,所以要分右子树是否为空两种情况讨论。
二、实验验证分析
1.输入的形式和输入值的范围
密码类型:string
用户名类型:string
2.输出的形式
输出的形式都是字符串,并通过换行符(‘\n’),水平制表符(‘\t’)等来规范输出,实现美观性.下
面截图演示.(如图一)
(图一)
3.程序所能达到的功能
b.用户密码更新;
a.用户登录;
c 用户添加(注册)
d.用户删除;
e.查看所有用户
5
数据结构大型实验——用户登录系统
4.测试数据(包括正确的输入及其输出结果和含有错误的输入及
其输出结果)
在主菜单输入 1(如图二)
则进入登陆界面(如图三)
(图二)
6
数据结构大型实验——用户登录系统
当输入数据非法时(如图四)
(图三)
则提醒重新输入(如图五)
(图四)
7
数据结构大型实验——用户登录系统
其他界面类似
(图五)
三、调试分析
1.讨论分析调试过程中的主要技术问题以及具体的解决方法(至
少3个)
a)在用户修改密码时由于密码时私有数据,无法修改,登陆时也无法判断密码是否正确;
解决方法:定义两个函数 getpswd()和 setpswd(string)分别用于获取密码和修改密码;
b)关于文件的输入输出;
解决方法:参考了上学期的 C++大型实验
c)有关调整树平衡时左右旋和右左旋;
解决方法:结合网上和书中解释,先手画过程在写代码,再根据代码画过程。
2.技术难点分析(至少3个)
a)关于平衡因子的计算,原本 UserNode 类中 int 型的成员变量只有平衡因子,如何计算无
从入手;后来又添加了变量 h(高度),在每次某个节点有调整后就更新它的高度,同时更新
8