用户登录系统.docx
《用户登录系统.docx》由会员分享,可在线阅读,更多相关《用户登录系统.docx(30页珍藏版)》请在冰豆网上搜索。
![用户登录系统.docx](https://file1.bdocx.com/fileroot1/2022-12/1/b034c5e8-ce31-424f-9202-fab322ddc440/b034c5e8-ce31-424f-9202-fab322ddc4401.gif)
用户登录系统
用户登录系统
LT
1.
2.
3.系统总体设计:
采用平衡二叉查找树(AVL),以用户名(IP)作为比较的关键词进行插入。
平衡二叉查找树是在二叉搜索树(BST)的基础上进行了优化,使得树基本达到平衡。
定义内部类userNode来存储AVL树的节点信息。
4.系统功能设计:
要创建一颗包含用户名和用户密码的二叉树,要能适应频繁的查找,因为每个用户名是唯一的,将用户名(string类型)作为AVL树的比较参数,这样就可以实现快速的插入、删除和查找,重定义userNode类的比较函数。
AVL树是用模板类实现的,这样就可以直接比较两个用户类,方便了很多。
图1系统功能结构图
5.类的设计:
//节点的类
classuserNode
{
private:
stringname;
stringpassword;
shortintheight;
public:
userNode*left;
userNode*right;
userNode(conststring&name,conststring&password);
userNode(constuserNode&temp);
voidsetName(conststring&name);
voidsetPassword(conststring&password);
stringgetName();
stringgetPassword();
intgetHeight();
voidchangeHeight(constintheight);//改变树的高度
boolcheckName(conststring&name);
};
//树的类
classtree
{
private:
userNode*root;
public:
tree();
~tree();
voidinsert_node(userNode*&t,userNode&temp);
voidinsert_node(userNode&temp);//新建一个节点
voidremove(userNode*&r,userNode*&temp);
voidremove(userNode*&temp);//删除一个节点
voidclear(userNode*t);
voidclear();
voidprint();
voidprint(intindex,userNode*r);//输出一棵树
voidPrint();
voidPrint(ofstream&ofile,userNode*&r);//写入文件
voidrotateL(userNode*&r);//左旋
voidrotateR(userNode*&r);//右旋
voidrotateDoubleLR(userNode*&r);//左右旋
voidrotateDoubleRL(userNode*&r);//右左旋
voidrightBalance(userNode*&r);
voidleftBalance(userNode*&r);
userNode*findNode(strings);//搜索一个节点
userNode*searchLeftMaxNode(userNode*&r,userNode*&R);
};
//框架类
classframe
{
treemyTree;
public:
frame();
voidview();//显示主界面
voidLogin();//登录界面
voidtestInsert();//插入一个节点
voidprintTree();//画出一棵树
};
6.主程序的设计:
图2类的调用
一.调试分析:
1.技术难点分析:
(1)查询操作时,怎么能找到相应用户的节点?
考虑到用户名的唯一性,所以将用户名作为AVL树的关键词,以字符串来比较大小,进行排序,重定义userNode类的比较操作符,只比较IP,因此,在查询的时候,新建一个userNode的对象,其IP赋值为所要查询的IP,然后调用查找函数,可找到对应的点
(2)AVL树的实现
看书,上网查询。
先了解二叉查找树(BST)的实现,二叉查找树(BST)是一种很好的数据结构,它的特点是,对其任一节点,都满足该节点的左子树的所有点的值都小于该节点,而右子树则是大于。
我采用链表来实现它,创建关于节点的一个类Node,内含描述该节点的值,及左右指针。
我定义insert_node()函数来实现新节点的插入。
AVL树相对于BST树,多了平衡两字,树都有高度,而AVL树就是要求每一个节点的左子树和右子树的高度差不超过1,这样就能使其尽可能的减小整棵树的高度,使时间复杂度能稳定在O(logN),但我们不可能去约束用户的输入,因此,引入了四种旋转:
是新插入的节点
图3右旋
图4左旋
图5先右旋再左旋
图6先左旋再右旋
(3)修改密码或删除用户后如何返回上一界面?
经反复修改,未果,遂放弃。
2.调试错误分析:
(1)登陆时密码要正确。
图7用户登录界面
(2)登陆时用户要存在
图8用户不存在界面
(3)新建用户名不能已存在
图9用户名已存在界面
四、测试结果分析:
1)主界面
图10主界面
2)登录界面
图11登录界面
3)注册界面
图12注册界面
4)树图
图13树形图界面
5)修改密码
图14修改密码
6)删除用户
图15删除用户界面
五、附录:
Node.h
#include
#include
#include
#include
#include
usingnamespacestd;
classuserNode
{
private:
stringname;
stringpassword;
shortintheight;
public:
userNode*left;
userNode*right;
userNode(conststring&name,conststring&password);
userNode(constuserNode&temp);
voidsetName(conststring&name);
voidsetPassword(conststring&password);
stringgetName();
stringgetPassword();
intgetHeight();
voidchangeHeight(constintheight);//改变树的高度
boolcheckName(conststring&name);
};
Tree.h
#include"node.h"
#include
classtree
{
private:
userNode*root;
public:
tree();
~tree();
voidinsert_node(userNode*&t,userNode&temp);
voidinsert_node(userNode&temp);//新建一个节点
voidremove(userNode*&r,userNode*&temp);
voidremove(userNode*&temp);//删除一个节点
voidclear(userNode*t);
voidclear();
voidprint();
voidprint(intindex,userNode*r);//输出一棵树
voidPrint();
voidPrint(ofstream&ofile,userNode*&r);//写入文件
voidrotateL(userNode*&r);//左旋
voidrotateR(userNode*&r);//右旋
voidrotateDoubleLR(userNode*&r);//左右旋
voidrotateDoubleRL(userNode*&r);//右左旋
voidrightBalance(userNode*&r);
voidleftBalance(userNode*&r);
userNode*findNode(strings);//搜索一个节点
userNode*searchLeftMaxNode(userNode*&r,userNode*&R);
};
Frame.h
#include"tree.h"
classframe
{
treemyTree;
public:
frame();
voidview();//显示主界面
voidLogin();//登录界面
voidtestInsert();//插入一个节点
voidprintTree();//画出一棵树
};
Node.cpp
#include"node.h"
voiduserNode:
:
setName(conststring&name)
{
this->name=name;
}
voiduserNode:
:
setPassword(conststring&password)
{
this->password=password;
}
stringuserNode:
:
getName()
{
returnname;
}
stringuserNode:
:
getPassword()
{
returnpassword;
}
intuserNode:
:
getHeight()
{
returnthis==NULL?
-1:
height;
}
voiduserNode:
:
changeHeight(constinth)
{
height=h;
}
booluserNode:
:
checkName(conststring&name)
{
if(this->name==name)returntrue;
elsereturnfalse;
}
userNode:
:
userNode(conststring&name,conststring&password)
{
this->name=name;
this->password=password;
height=0;
left=NULL;
right=NULL;
}
userNode:
:
userNode(constuserNode&temp)
{
this->name=temp.name;
this->password=temp.password;
height=0;
left=NULL;
right=NULL;
}
Tree.cpp
#include"tree.h"
#include
//构造函数
tree:
:
tree()
{
root=NULL;
}
voidtree:
:
insert_node(userNode&temp)
{
insert_node(root,temp);
}
voidtree:
:
insert_node(userNode*&r,userNode&t)
{
if(r==NULL)
{
r=newuserNode(t);//若树为空,直接新建节点
}
elseif(r->getName()==t.getName())//若节点值相等,则用户名重复
{
return;
stringrename;
cout<<"用?
户§名?
"<经-存?
在ú,?
请?
修T改?
"<cin>>rename;
t.setName(rename);
insert_node(r,t);
}
elseif(r->getName()>t.getName())
{
insert_node(r->left,t);
if(r->left->getHeight()-r->right->getHeight()==2)
{
rightBalance(r);
}
}
elseif(r->getName(){
insert_node(r->right,t);
if(r->right->getHeight()-r->left->getHeight()==2)
{
leftBalance(r);
}
}
r->changeHeight(max(r->left->getHeight(),r->right->getHeight())+1);
}
//移除
voidtree:
:
remove(userNode*&r,userNode*&temp)
{
if(r==NULL)
{
return;
}
elseif(temp->getName()getName())
{
remove(r->left,temp);
if(r->right->getHeight()-r->left->getHeight()==2)
leftBalance(r);
}
elseif(temp->getName()>r->getName())
{
remove(r->right,temp);
if(r->left->getHeight()-r->right->getHeight()==2)
rightBalance(r);
}
else
{
if(r->left==NULL)
{
userNode*q=r;
r=r->right;
deleteq;
}
elseif(r->right==NULL)
{
userNode*q=r;
r=r->left;
deleteq;
}
else{
userNode*R;
r=searchLeftMaxNode(r,R);
remove(r->left,R);
if(r->right->getHeight()-r->left->getHeight()==2)
leftBalance(r);
}
}
if(r)
r->changeHeight(max(r->left->getHeight(),r->right->getHeight())+1);
}
voidtree:
:
remove(userNode*&temp)
{
remove(root,temp);
}
voidtree:
:
print()
{
print(0,root);
}
voidtree:
:
print(intindex,userNode*r)
{
if(r)
{
print(index+8,r->right);
cout<getName()<<"("<left->getHeight()-r->right->getHeight()<<")"<print(index+8,r->left);
}
}
voidtree:
:
Print(ofstream&ofile,userNode*&r)
{
if(r)
{
Print(ofile,r->left);
ofile<getName()<<","<getPassword()<<'\n';
Print(ofile,r->right);
}
}
voidtree:
:
Print()
{
userNode*p=root;
ofstreamofile;
ofile.open("user.txt");
assert(ofile.is_open());
Print(ofile,p);
ofile.close();
}
voidtree:
:
rotateL(userNode*&r)
{
userNode*R=r->right;
r->right=R->left;
R->left=r;
r->changeHeight(max(r->left->getHeight(),r->right->getHeight())+1);
R->changeHeight(max(R->left->getHeight(),r->getHeight())+1);
r=R;
}
voidtree:
:
rotateR(userNode*&r)
{
userNode*L=r->left;
r->left=L->right;
L->right=r;
r->changeHeight(max(r->left->getHeight(),r->right->getHeight())+1);
L->changeHeight(max(L->left->getHeight(),r->getHeight())+1);
r=L;
}
voidtree:
:
rotateDoubleLR(userNode*&r)
{
rotateL(r->left);
rotateR(r);
}
voidtree:
:
rotateDoubleRL(userNode*&r)
{
rotateR(r->right);
rotateL(r);
}
voidtree:
:
rightBalance(userNode*&r)
{
userNode*temp=r->left;
if(temp->left->getHeight()-temp->right->getHeight()==-1)
rotateDoubleLR(r);
elserotateR(r);
}
voidtree:
:
leftBalance(userNode*&r)
{
userNode*temp=r->right;
if(temp->left->getHeight()-temp->right->getHeight()==1)
rotateDoubleRL(r);
elserotateL(r);
}
userNode*tree:
:
findNode(strings)
{
userNode*r=root;
while(r)
{
if(s==r->getName())
returnr;
elseif(sgetName())
r=r->left;
elseif(s>r->getName())
r=r->right;
}
returnNULL;
}
userNode*tree:
:
searchLeftMaxNode(userNode*&r,userNode*&R)
{
boolLeft=false,Right=true;
userNode*q=NULL;
R=r;
if(r->left->left==NULL&&r->left->right==NULL)
{
q=r;
r=r->left;
q->left=NULL;
r->left=q;
r->right=q->right;
q->right=NULL;
R=q;
}
else{
if(r->left)
r=r->left;
while(r->right)
{
if(r->right->right==NULL)
q=r;
r=r->right;
Right=false;
}
if(Right)
{
if(r->left)
{
q=r;
r=r->left;
q->left=NULL;
}
}
r->left=R->left;
r->right=R->right;
R->left=NULL;
R->right=NULL;
q->right=R;
}
inttemp=r->getHeight();
r->changeHeight(R->getHeight());
R->changeHeight(0);
returnr;
}
tree:
:
~tree()
{
clear();
}
voidtree:
:
clear()
{
clear(root);
}
voidtree:
:
clear(userNode*t)
{
if(t==NULL)return;
if(t!
=NULL)
{
clear(t->left);
clear(t->right);
deletet;
}
t=NULL;
}
Frame.cpp
#include"frame.h"
#include
frame:
:
frame()
{
fstreamfile("user.txt");
chars[50];
userNode*userPeople;
while(!
file.eof())
{
file.getline(s,50);
for(inti=0;i{
if(s[i]==',')
{
stringuser(&s[0],&s[i]),pass(&s[i+1],&s[strlen(s)]);
userPeople=newuserNode(user,pass);
myTree.insert_node(*userPeople);
break;
}
}
}
file.close();
}
voidframe:
:
view()
{
while
(1)
{
system("cls");
//cout<<"1、¢登?
录?
"<册á"<