1、用户登录系统用户登录系统LT1.2.3.系统总体设计: 采用平衡二叉查找树(AVL),以用户名(IP)作为比较的关键词进行插入。平衡二叉查找树是在二叉搜索树(BST)的基础上进行了优化,使得树基本达到平衡。定义内部类userNode来存储AVL树的节点信息。4.系统功能设计:要创建一颗包含用户名和用户密码的二叉树,要能适应频繁的查找,因为每个用户名是唯一的,将用户名(string类型)作为AVL树的比较参数,这样就可以实现快速的插入、删除和查找,重定义userNode类的比较函数。AVL树是用模板类实现的,这样就可以直接比较两个用户类,方便了很多。图1 系统功能结构图5.类的设计:/ 节点的类
2、class userNodeprivate: string name; string password; short int height;public: userNode *left; userNode *right; userNode(const string &name,const string &password); userNode(const userNode & temp); void setName(const string &name); void setPassword(const string &password); string getName(); string ge
3、tPassword(); int getHeight(); void changeHeight(const int height);/改变树的高度 bool checkName(const string &name);/ 树的类class treeprivate: userNode *root; public: tree(); tree(); void insert_node(userNode *&t ,userNode &temp); void insert_node(userNode &temp); /新建一个节点 void remove(userNode *&r,userNode *&t
4、emp); void remove(userNode *&temp);/删除一个节点 void clear(userNode *t); void clear(); void print(); void print(int index,userNode *r);/输出一棵树 void Print(); void Print(ofstream &ofile,userNode *&r);/写入文件 void rotateL(userNode *&r);/左旋 void rotateR(userNode *&r);/右旋 void rotateDoubleLR(userNode *&r);/左右旋 v
5、oid rotateDoubleRL(userNode *&r);/右左旋 void rightBalance(userNode *&r); void leftBalance(userNode *&r); userNode *findNode(string s);/搜索一个节点 userNode *searchLeftMaxNode(userNode *&r,userNode *&R);/ 框架类class frame tree myTree;public: frame(); void view();/显示主界面 void Login();/登录界面 void testInsert();/插入
6、一个节点 void printTree();/画出一棵树;6.主程序的设计:图2 类的调用一. 调试分析:1.技术难点分析:(1)查询操作时,怎么能找到相应用户的节点?考虑到用户名的唯一性,所以将用户名作为AVL树的关键词,以字符串来比较大小,进行排序,重定义userNode类的比较操作符,只比较IP,因此,在查询的时候,新建一个userNode的对象,其IP赋值为所要查询的IP,然后调用查找函数,可找到对应的点(2)AVL树的实现看书,上网查询。先了解二叉查找树(BST)的实现,二叉查找树(BST)是一种很好的数据结构,它的特点是,对其任一节点,都满足该节点的左子树的所有点的值都小于该节点,
7、而右子树则是大于。我采用链表来实现它,创建关于节点的一个类 Node ,内含描述该节点的值,及左右指针。我定义 insert_node() 函数来实现新节点的插入。AVL树相对于BST树,多了平衡两字,树都有高度,而AVL树就是要求每一个节点的左子树和右子树的高度差不超过1,这样就能使其尽可能的减小整棵树的高度,使时间复杂度能稳定在O(logN), 但我们不可能去约束用户的输入,因此,引入了四种旋转:是新插入的节点图3 右旋图4 左旋图5 先右旋再左旋图6 先左旋再右旋(3)修改密码或删除用户后如何返回上一界面?经反复修改,未果,遂放弃。2.调试错误分析:(1)登陆时密码要正确。图7 用户登录
8、界面(2)登陆时用户要存在图8 用户不存在界面(3)新建用户名不能已存在图9 用户名已存在界面四、 测试结果分析:1)主界面图10 主界面2)登录界面图11 登录界面3)注册界面图12 注册界面4)树图图13 树形图界面5)修改密码图14 修改密码6)删除用户图15 删除用户界面五、附录:Node.h#include#include#include#include#includeusing namespace std;class userNodeprivate: string name; string password; short int height;public: userNode *l
9、eft; userNode *right; userNode(const string &name,const string &password); userNode(const userNode & temp); void setName(const string &name); void setPassword(const string &password); string getName(); string getPassword(); int getHeight(); void changeHeight(const int height);/改变树的高度 bool checkName(
10、const string &name);Tree.h#includenode.h#includeclass treeprivate: userNode *root; public: tree(); tree(); void insert_node(userNode *&t ,userNode &temp); void insert_node(userNode &temp); /新建一个节点 void remove(userNode *&r,userNode *&temp); void remove(userNode *&temp);/删除一个节点 void clear(userNode *t)
11、; void clear(); void print(); void print(int index,userNode *r);/输出一棵树 void Print(); void Print(ofstream &ofile,userNode *&r);/写入文件 void rotateL(userNode *&r);/左旋 void rotateR(userNode *&r);/右旋 void rotateDoubleLR(userNode *&r);/左右旋 void rotateDoubleRL(userNode *&r);/右左旋 void rightBalance(userNode *
12、&r); void leftBalance(userNode *&r); userNode *findNode(string s);/搜索一个节点 userNode *searchLeftMaxNode(userNode *&r,userNode *&R);Frame.h#includetree.hclass frame tree myTree;public: frame(); void view();/显示主界面 void Login();/登录界面 void testInsert();/插入一个节点 void printTree();/画出一棵树;Node.cpp#includenode.
13、hvoid userNode:setName(const string &name) this-name=name;void userNode:setPassword(const string &password) this-password=password;string userNode:getName() return name;string userNode:getPassword() return password;int userNode:getHeight() return this=NULL?-1:height;void userNode:changeHeight(const
14、int h) height=h;bool userNode:checkName(const string &name) if(this-name=name)return true; else return false;userNode:userNode(const string &name,const string &password) this-name=name; this-password=password; height=0; left=NULL; right=NULL;userNode:userNode(const userNode & temp) this-name=temp.na
15、me; this-password=temp.password; height=0; left=NULL; right=NULL;Tree.cpp#includetree.h#include /构造函数tree:tree() root=NULL;void tree:insert_node(userNode &temp) insert_node(root,temp);void tree:insert_node(userNode *&r,userNode &t) if(r=NULL) r=new userNode(t);/若树为空,直接新建节点 else if(r-getName()=t.getN
16、ame()/若节点值相等,则用户名重复 return; string rename; cout用?户名?t.getName()已?经-存?在,?请?修T改?rename; t.setName(rename); insert_node(r,t); else if(r-getName()t.getName() insert_node(r-left,t); if(r-left-getHeight()-r-right-getHeight()=2) rightBalance(r); else if(r-getName()right,t); if(r-right-getHeight()-r-left-ge
17、tHeight()=2) leftBalance(r); r-changeHeight( max(r-left-getHeight(),r-right-getHeight()+1 ); / 移除void tree:remove(userNode *&r,userNode *&temp) if(r=NULL) return; else if(temp-getName()getName() remove(r-left,temp); if(r-right-getHeight()-r-left-getHeight()=2) leftBalance(r); else if(temp-getName()r
18、-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; delete q; else if(r-right=NULL) userNode *q=r; r=r-left; delete q; else userNode *R; r=searchLeftMaxNode(r,R); remove(r-left,R); if(r-right-getHeight()-r-left
19、-getHeight()=2) leftBalance(r); if(r) r-changeHeight(max(r-left-getHeight(),r-right-getHeight()+1); void tree:remove(userNode *&temp) remove(root,temp); void tree:print() print(0,root);void tree:print(int index,userNode *r) if(r) print(index+8,r-right); coutsetw(index)getName()(left-getHeight()-r-ri
20、ght-getHeight()left); void tree:Print(ofstream &ofile,userNode *&r) if(r) Print(ofile,r-left); ofilegetName(),getPassword()right); void tree:Print() userNode *p=root; ofstream ofile; ofile.open(user.txt); assert(ofile.is_open(); Print(ofile,p); ofile.close();void tree:rotateL(userNode *&r) userNode
21、*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;void tree:rotateR(userNode *&r) userNode *L=r-left; r-left=L-right; L-right=r; r-changeHeight(max(r-left-getHeight(),r-right-getHeight()+1);
22、 L-changeHeight(max(L-left-getHeight(),r-getHeight()+1); r=L;void tree:rotateDoubleLR(userNode *&r) rotateL(r-left); rotateR(r); void tree:rotateDoubleRL(userNode *&r) rotateR(r-right); rotateL(r); void tree:rightBalance(userNode *&r) userNode *temp=r-left; if(temp-left-getHeight()-temp-right-getHei
23、ght()=-1) rotateDoubleLR(r); else rotateR(r);void tree:leftBalance(userNode *&r) userNode *temp=r-right; if(temp-left-getHeight()-temp-right-getHeight()=1) rotateDoubleRL(r); else rotateL(r);userNode* tree:findNode(string s) userNode *r=root; while(r) if(s=r-getName() return r; else if(sgetName() r=
24、r-left; else if(sr-getName() r=r-right; return NULL;userNode*tree:searchLeftMaxNode(userNode *&r,userNode *&R) bool Left=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;
25、 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; int temp=r-getHeight(); r-changeHeight(R-getHeight(); R-changeHeight(0); return r;tree:tree() clear();void tree:c
26、lear() clear(root);void tree:clear(userNode *t) if(t=NULL)return; if(t!=NULL) clear(t-left); clear(t-right); delete t; t=NULL;Frame.cpp#includeframe.h#includeframe:frame() fstream file(user.txt); char s50; userNode *userPeople; while(!file.eof() file.getline(s,50); for(int i=0;istrlen(s);i+) if(si=,) string user(&s0,&si),pass(&si+1,&sstrlen(s); userPeople=new userNode(user,pass); myTree.insert_node(*userPeople); break; file.close(); void frame:view() while(1) system(cls); /cout1、登?录?endl2、注痢?册endl3、
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1