AVL树模拟用户登录系统的实验报告附代码和详尽注释 2.docx
- 文档编号:23735627
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:53
- 大小:192.42KB
AVL树模拟用户登录系统的实验报告附代码和详尽注释 2.docx
《AVL树模拟用户登录系统的实验报告附代码和详尽注释 2.docx》由会员分享,可在线阅读,更多相关《AVL树模拟用户登录系统的实验报告附代码和详尽注释 2.docx(53页珍藏版)》请在冰豆网上搜索。
AVL树模拟用户登录系统的实验报告附代码和详尽注释2
一.实验内容分析:
1.实验目的:
模拟用户登录系统,在O(lgn)时间内完成用户登录、删除、修改等工作。
2.设计思路:
主要分以下四个类:
AVLTreeNode:
存储平衡树节点;
AVLTree:
AVL平衡树的主要实现算法;
UserInfo:
存储用户信息;
Interface:
界面,与用户交互;
3.
流程图以及类的主要包含和调用关系:
二.实验验证分析
(1)输入的形式和输入值的范围;
控制台的输入:
如图,输入为数字,超出范围将提示不正确并返回重新输入
文件的输入:
程序会找寻当前目录的database.data文件,并读入数据,如果未找到则自创此文件,创建空树
(2)输出的形式;
程序退出时析构函数保存文件到database.data并覆盖原文件。
(3)程序所能达到的功能;
在O(lgn)时间内添加、查找、删除、修改用户信息。
(4)测试数据:
本系统包含三个测试函数样例:
1.顺序插入测试(分别在debug和release环境下和STLmap比较速度)
2.随机插入测试(分别在debug和release环境下和STLmap比较速度)
3.删除测试
测试函数均在main文件里
voidrandomTest();//随机数测试
voidorderTest();//顺序插入测试
voiddeleteTest();//删除测试
voidmain_interface();//主界面
1,2均在debug模式下插入100W数据,在release模式下插入1000W数据。
顺序插入的实现是用整数1~n转换为string,位数不够的在前面补‘0’。
测试结果:
1.debug下顺序插入测试:
2.Release下顺序插入测试
3.debug下随机插入测试
4.release下随机插入测试
实践证明map的红黑树在顺序插入测试时慢于我的avl树,但随机插入测试表现比AVL树要好。
3.删除数据的图形化表示(‘R’‘L’‘=’为平衡因子以检验正确性)
下面删除3(树中无3):
还是一样,下面删除2
删除成功,下面删除7
删除成功。
三.调试分析
(1)讨论分析调试过程中的主要技术问题以及具体的解决方法(至少3个);
1.代码重复问题:
有重复的代码不是好代码。
左右旋和左旋右旋有大量重复,经过分析发现左右旋可以分解为先左旋后右旋,但平衡因子调整方法不一。
所以分解左旋和右旋为两个函数,调整平衡因子单分一个函数。
2.空间占用问题:
平衡因子只有3个取值却占了一个int4个字节是极大的浪费,所以改用char型。
编程实践中发现树高也可以取消,也极大的节省了空间。
3.时间浪费问题:
先调整平衡因子再旋转最后再调整平衡因子浪费时间,经分析后可以采取一些代码上的改动而将第一次调整省略。
(2)技术难点分析(至少3个);
1.由于放弃树高调整平衡因子,所以平衡因子的调整是编程最困难之处,采用方法是根据插入子数是左子树还是右子树调整父亲的平衡因子。
2.删除时需先采用BST的删除方式,再分情况用类似AVL插入节点时的调整方法,必须完全搞懂BST和AVL才能正确地处理删除问题。
3.代码阅读问题:
纯算法程序一般难以阅读,尤其是像AVL这类复杂算法,即使是自己也是编了前面忘了后面,所以程序添加了海量的注释,每个函数每个重要语句都有功能解说,代码命名取其意思,格式遵循《cleanCode》。
(3)印象最深刻的3个调试错误,及修正方法;
1.最深的当然是访问了没初始化的内存!
!
几乎90%调试问题都与此有关。
大部分非法访问内存经调试都归结于平衡因子的错误。
解决方法是在纸上画出几个正确的例子,再输入进程序调试,看平衡因子的错误具体地址和引起其错误的代码。
反复调试修改直到测试再大数据量也不会报错。
2.链接错误。
好像是1005,此错误的原因是.h文件内除了成员函数不能有其它函数。
原来是我用的友元重载比较函数(必须用友元,否则类对象比较时重载不匹配。
)网上查了好半天才知道的原因。
解决方法:
友元重载比较运算符函数放到.cpp文件里。
3.头文件包含问题要彻底搞明白,.h文件必须加头文件卫士,.cpp必须不加而且不能被#include,。
4.测试结果:
(1)展示程序的运行结果,包括输入和输出,分析数据的正确性;
1.database.data文件(存放用户名密码)
2.用户登录
3.添加用户
4.删除用户
4.更新用户
(2)应用边界数据、或极端数据测试系统,分析结果的正确性。
实验分析验证里已进行充分测试。
5.附录:
附上源代码,并标明源代码的所属文件,并且源代码必须有注释。
//-----------------------------------------------------------------
//AVLTreeNode.h
//AVL树节点类
//功能:
提供主键、左右子指针、父指针,平衡因子
//说明:
平衡因子为char,节约空间(L相当于1,R相当于-1,=相当于0)
//修改时间:
2013-12-2514:
29:
44
//-----------------------------------------------------------------
#ifndefAVLTreeNode_H
#defineAVLTreeNode_H
#include"UserInfo.h"
classAVLTreeNode
{
public:
UserInfokey;
AVLTreeNode*left;
AVLTreeNode*right;
AVLTreeNode*parent;
charbalanceFactor;
AVLTreeNode()
{
left=0;
right=0;
parent=0;
balanceFactor='=';
}
AVLTreeNode(UserInfos)
{
key=s;
left=0;
right=0;
parent=0;
balanceFactor='=';
}
};
#endif
//==================================================================
//AVLTree.h
//AVL平衡树,实现了添加、查找、图形输出等功能
//Author:
hufeiyaZJUT
//2013-12-414:
38:
04
//2013-12-2414:
35:
42添加了删除方法
//插入经过3KW数据严格测试,删除不严格测试
//==================================================================
#ifndefAVLTree_H
#defineAVLTree_H
#include
#include
#include
#include"AVLTreeNode.h"
usingnamespacestd;
classAVLTree
{
private:
public:
AVLTree();
~AVLTree();//析构函数。
调用①
voidinsert(AVLTreeNode*n);//插入元素。
调用④⑤⑥⑦
voidgraph();//图形输入。
调用②
voidinOrder(ofstream&fs);//中序遍历修改文件。
调用③
AVLTreeNode*find(UserInfotarget);//查找元素,返回地址。
voidremove(UserInfokey);//删除元素。
调用⑥⑦⑧⑨
private:
AVLTreeNode*root;
voidClearTree(AVLTreeNode*n);//清除所有元素①
voidgraphAux(AVLTreeNode*subtree,inta);//递归图形输出②
voidinOrderAux(ofstream&fs,AVLTreeNode*subtree);//递归中序遍历③
voidrestoreAVL(AVLTreeNode*ancestor,AVLTreeNode*newNode);//添加节点后重建树④
voidadjustBalanceFactors(AVLTreeNode*end,AVLTreeNode*start);//调整平衡因子(插入时)⑤
voidrotateLeft(AVLTreeNode*n);//左旋,插入删除共用⑥
voidrotateRight(AVLTreeNode*n);//右旋,插入删除共用⑦
voidsearch2(constUserInfo&data,bool&found,AVLTreeNode*&x,AVLTreeNode*&parent);//remove辅助函数⑧
voidrestoreAVL2(AVLTreeNode*start,boolleft);//删除节点后后重建树⑨
};
#endif
//-----------------------------------------------------------------
//Interface.h
//界面类
//功能:
构建界面、读取和写入文件
//修改时间:
2013-12-2514:
27:
17
//-----------------------------------------------------------------
#ifndefInterface_H
#defineInterface_H
#include
#include
#include
#include
#include"AVLTree.h"
usingnamespacestd;
classInterface
{
public:
Interface();//构造函数,读取文件,创建并建立树
~Interface();//保存信息到文件,销毁树,关闭文件
voidmainFace();
voidlogIn();
voidaddUser();
voidremoveUser();
voidupdate();
private:
AVLTree*data;
ifstreamreadStream;
ofstreamwriteStream;
};
#endif
//-----------------------------------------------------------------
//UserInfo.h
//用户信息类
//功能:
储存用户名、密码等信息,重载部分操作符
//修改时间:
2013-12-2514:
26:
05
//-----------------------------------------------------------------
#ifndefUserInfo_H
#defineUserInfo_H
#include
#include
usingnamespacestd;
classUserInfo
{
public:
UserInfo(){}
UserInfo(stringname,stringpass);
UserInfo(stringname);//缺省密码等于账号
UserInfo(char*name);//缺省密码等于账号
UserInfo(constUserInfo&b);//复制构造函数
friendbooloperator<(constUserInfo&a,constUserInfo&b);
friendbooloperator>(constUserInfo&a,constUserInfo&b);
booloperator==(constUserInfo&b);
friendostream&operator<<(ostream&os,constUserInfo&b);
friendclassInterface;
friendclassAVLTree;
private:
stringusername;
stringpassword;
};
#endif
下面是.cpp文件
Main.cpp:
#include"AVLTree.h"
#include
#include
#include
#include
#include
#include
#include"Interface.h"
#pragmawarning(disable:
4996)
usingnamespacestd;
#defineMAX10000000
stringa[MAX];
AVLTreeNode*p[MAX];
voidrandomTest();//随机数测试
voidorderTest();//顺序插入测试
voiddeleteTest();//删除测试
voidmain_interface();//主界面
intmain()
{
//orderTest();
//randomTest();
//deleteTest();
main_interface();
return0;
}
voiddeleteTest()
{
AVLTree&a=*newAVLTree();
AVLTreeNode*p=newAVLTreeNode("4");
a.insert(p);
p=newAVLTreeNode("15");
a.insert(p);
p=newAVLTreeNode("21");
a.insert(p);
p=newAVLTreeNode("38");
a.insert(p);
p=newAVLTreeNode("14");
a.insert(p);
p=newAVLTreeNode("18");
a.insert(p);
p=newAVLTreeNode("28");
a.insert(p);
p=newAVLTreeNode("6");
a.insert(p);
p=newAVLTreeNode("5");
a.insert(p);
p=newAVLTreeNode("7");
a.insert(p);
p=newAVLTreeNode("1");
a.insert(p);
p=newAVLTreeNode("2");
a.insert(p);
p=newAVLTreeNode("100");
a.insert(p);
p=newAVLTreeNode("8");
a.insert(p);
a.graph();
a.remove("3");
a.graph();
a.remove("2");
a.graph();
a.remove("7");
a.graph();
delete&a;
}
voidrandomTest()
{
//freopen("G:
\\1.txt","w",stdout);
AVLTree&at=*newAVLTree();
ints=0;
stringstreamss;
map
srand((int)time(0));
for(inti=0;i { ss< ss>>a[i]; p[i]=newAVLTreeNode(a[i]); ss.clear(); } cout<<"随机字符串生成完毕,现在插入到AVL树\n"; doubleoldTime=clock(),newTime; while(s { at.insert(p[s]); s++; //cout< } //at.graph(); newTime=clock()-oldTime; cout<<"写入"< cout<<"现在测试STLmap,写入相同字符串集合\n"; oldTime=clock(); for(inti=0;i { stlMap[a[i]]++; } newTime=clock()-oldTime; cout<<"写入"< cout<<"请输入要查找的数\n"; stringtempName; AVLTreeNode*address=0; while(cin>>tempName) { UserInfotempUser(tempName); oldTime=clock(); address=at.find(tempUser); if(0! =address) cout<<"已找到,在地址为"< else cout<<"未找到\n"; newTime=clock()-oldTime; cout<<"查找共用时"< } delete&at; } voidorderTest() { //freopen("G: \\1.txt","w",stdout); AVLTree&at=*newAVLTree(); ints=0; stringstreamss; map inttemp; stringzeroNum[]={"","0","00","000","0000","00000","000000","0000000","00000000","000000000",}; srand((int)time(0)); for(inti=1;i { stringtempZero; intnum=0; for(intj=i;j { num+=1; } ss< stringtemp1; ss>>temp1; tempZero+=zeroNum[num]; tempZero+=temp1; a[i]=tempZero; p[i]=newAVLTreeNode(a[i]); ss.clear(); } cout<<"顺序字符串生成完毕,现在插入到AVL树\n"; doubleoldTime=clock(),newTime; while(s { at.insert(p[s]); s++; //cout< } //at.graph(); newTime=clock()-oldTime; cout<<"写入"< cout<<"现在测试STLmap,写入相同字符串集合\n"; oldTime=clock(); for(inti=0;i { stlMap[a[i]]++; } newTime=clock()-oldTime; cout<<"写入"< cout<<"请输入要查找的数\n"; stringtempName; AVLTreeNode*address=0; while(cin>>tempName) { UserInfotempUser(tempName); oldTime=clock(); address=at.find(tempUser); if(0! =address) cout<<"已找到,在地址为"< else cout<<"未找到\n"; newTime=clock()-oldTime; cout<<"查找共用时"< } delete&at; } voidmain_interface() { Interface&test=*newInterface(); delete&test; } UserInfo.cpp #include"UserInfo.h" UserInfo: : UserInfo(stringname,stringpass) { username=name; password=pass; } UserInfo: : UserInfo(stringname) { username=name; password=name; } UserInfo: : UserInfo(char*name) { username=name; password=name; } UserInfo: : UserInfo(constUserInfo&b)//复制构造函数 { username=b.username; password=b.password; } booloperator<(constUserInfo&a,constUserInfo&b) { returna.username }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AVL树模拟用户登录系统的实验报告附代码和详尽注释 AVL 模拟 用户 登录 系统 实验 报告 代码 详尽 注释