
图书推荐和管理系统(Qmazon)简介
这是我在本科学习的第二年参加的“面向对象程序设计(C ++)”的课程. 该系统实现了类似于Amazon,Dangdang和Douban的图书审查和推荐系统. 该系统使用C ++作为编程语言,并使用Qt程序开发框架来完成程序的可视化,并构建了PC风格的QQ风格的界面,具有很高的美感. 该系统采用基于用户的协同过滤算法作为图书推荐的核心功能,并结合基于人口统计的冷启动推荐算法来完成推荐模块的设计.
数据集: 〜cziegler / BX /
请手动删除数据集的三个csv文件的最后一行的空行! ! ! ! ! ! ! !
编译项目后,将数据放入build目录中的相应编译模式文件夹中! ! ! ! ! ! ! !
欢迎对此项目感兴趣的朋友通过电子邮件zymaa@ruc.edu.cn或通过微信: r7ma_1
与我联系.
系统显示图


需求分析
系统对我们的要求可以分为前端功能和后端功能. 前端功能是普通用户的一些操作功能,包括用户注册,登录,获取推荐,评分,评论,更改信息,取消帐户,查找书籍,查找朋友等功能,后端功能包括以下功能: 管理员基于qt的图书管理系统,包括管理员登录,添加书籍,删除书籍,更改书籍信息,添加新用户,删除用户,更改用户信息,查找书籍,查找用户,取消帐户等功能. 因此,在CLI(命令行界面)下,我们需要首先设置登录和注册功能,并设计不同的功能,这些功能可以在登录后根据不同的登录身份来执行. 在GUI(图形用户界面)下,我们需要设置登录界面,注册界面,管理员功能界面,用户功能界面以及用户的每个子功能界面. 命令行界面的实现将由VS,Dev-Cpp实现,图形界面将由Qt Creator根据CLI代码进行编译和实现.
课程设计
此程序有两个主要类,它们在base.h头文件中定义: book(书)类和user(用户)类. 具体的定义和操作可以在base.h头文件中看到,因此在此不再赘述. 其功能在Main.cpp文件中专门定义.
文件操作1.图书信息

使用ifstream打开文件后,将每个读取的数据临时存储在书本类型的新书中. 阅读完本书中的所有数据后,请使用新书
books.insert(map<string, Book>::value_type(IS, newbook));
添加到整个书籍的地图对象. 其中,IS是newbook的ISBN代码,可直接用于索引书籍. 单独使用本书的各种信息
getline(file, value, ';'); IS = string(value, 1, value.length() - 2);
表示“;”之前的数据读取,并通过删除值的第一个“和最后一个”来获得IS的内容. 最后,使用c ++ file.close();关闭文件.
2. 用户信息
类似于阅读图书信息的过程.
3. 评分信息
使用ifstream首先打开文件,然后使用
getline(file, value, ';'); string(value, 1, value.length() - 2);
读入IS和ID,然后使用地图索引将信息读入每个信息的对应项中. 并增加已阅读该书的用户的信息,以及该用户已阅读的书的信息.
users[ID].booksRead.insert(map<string, int>::value_type(IS, rank)); books[IS].usersRead.insert(map<string, int>::value_type(ID, rank));
最后使用file.close();关闭文件. 阅读完所有用户的评分信息后,使用迭代器查找每本书和每个用户的平均评分. 例如,以下是用于查找每本书平均得分的代码.
map<string, Book>::iterator iter = books.begin(); for (; iter != books.end(); iter++) { iter->second.aveRank = iter->second.sum / iter->second.cnt; }
4. 文件写回

由于增加了修改,删除等用户,因此所有信息必须在使用系统一次后重写. #####书本文件回写首先使用ofstream打开文件,然后先写回标题栏.
file << "\"ISBN\";\"Book-Title\";\"Book-Author\";\"Year-Of-Publication\";\"Publisher\""<< ";\"Image-URL-S\";\"Image-URL-M\";\"Image-URL-L\"" << endl;
写回每种类型的信息后,双引号由\“表示. 最后
file.close();
关闭文件. #####用户文件被写回. 首先使用ofstream打开文件,然后首先写回标题栏.
file2 << "\"User-ID\";\"Location\";\"Age\"" << endl;
写回每种类型的信息后,双引号由\“表示. 最后
file.close();
关闭文件. #####等级文件回写. 首先使用ofstream打开文件,然后首先写回标题栏.
file3 << "\"User-ID\";\"ISBN\";\"Book-Rating\"" << endl;
写回每种类型的信息后,双引号由\“表示. 最后
file.close();
关闭文件.
基于用户的协同过滤推荐算法
对于阅读过几本书的用户,我们推荐的方法是使用基于用户的常规协作过滤算法. 基于用户的协同过滤推荐算法的基本思想是: 首先根据用户对项目的评价计算所有用户之间的相似度,然后选择与当前用户最相似的N个用户,然后使用N个邻居用户用户对项目的评分会预测当前用户对尚未查看的项目的可能评分,最后根据预测的可能评分的级别向当前用户推荐该项目. 接下来,将详细描述该算法的实现. 算法在程序中的位置在recommendedsystem1.cpp

中
User:: getrecommendation()
首先,我们必须首先计算与所有用户的相似度. 计算的基本公式如下:

当我们计算当前用户A与用户B之间的相似度时,首先我们必须浏览A阅读过的书,从这些书中查找B也阅读过的书,然后找到相应的书,即book是公式中的p. 上面的公式可以分为三个求和部分,因此我使用sumup,sumdown1,sumdown2分别在函数中进行累加. 然后,通过应用该公式并累积他们一起阅读的所有书籍,计算用户A和B之间的相似度,并通过第一层相似地计算A与所有用户之间的相似度,并将相似度存储在其中
map<string, double>Sims
当前用户与ID为String的用户之间的相似性.
在这里,我们计算了当前用户与所有用户之间的相似度,然后我们可以选择邻居用户来预测得分. 选择此处的邻居用户数作为总用户数(27w +),因为数据集本来就很稀疏,并且几乎没有用户可以具有相似性. 因此,所有用户的使用都可以得到最准确的建议,而不会造成速度慢. 预测公式如下:

首先,我们遍历所有书籍并过滤掉用户尚未阅读的书籍. 假设现在我们要预测书籍P的预测分数. 然后,我们将从所有阅读P的人中查找和查找. 可以根据上述公式计算和累积与当前用户相似的用户,并预测可以计算出P的分数. 同样,可以计算所有书籍的预测分数. 在这里,我将所有预测的评级存储在地图
以下是排序过程. 在这里,我首先编写了一个函数,该函数按降序对地图中的元素进行排序并将其存储在Vector中
void sortMapByValue(map<string, double>& tMap, vector<pair<string, double> >& tVector)
Rankpre被排序并存储在Rvector中,然后Rvector的前几个元素可以作为推荐书输出.
在计算推荐书的过程中,我们实际上是通过以下方式来计算推荐朋友的,即我们已经存储了相似性Sims. 然后,Sims调用sortMapByValue函数以降序排序并将其存储在Svector中,然后将前几个元素作为推荐的朋友输出.
同时,这也值得注意. 如果用户读了一本书,但读的书太少或太“不受欢迎”,以致没有人读过同一本书,也就是说,没有人与他有相似之处,那么他仍然是冷门.

以上是算法原理和实现的基本内容. 还值得一提的是,如果两个用户都读过同一本书基于qt的图书管理系统,则直观上的相似度应该非常大(1),但是所应用公式的分母为0,无法计算,因此如果两个用户使用了特殊处理阅读同一本书(同等),然后将相似度直接设置为1,这样,考虑到极端情况,可以或多或少地减少错误.
Qt框架的使用
该项目使用Qt进行C ++可视化. 在Main.cpp函数中,必须首先引入Qt自动生成的每个接口的头文件. 之后,您可以为每个界面上的每个按钮事件编写一个函数. 例如,删除一本书的事件触发功能:
void menu_admin::on_pushButton_3_clicked() { bool ok; // 获取字符串 QString qid = QInputDialog::getText(this,tr("input"), tr("input the id:"),QLineEdit::Normal,tr("admin"),&ok); string id=qid.toStdString(); if(books.find(id)!=books.end()){ books[id].deletebook(); } else{ QMessageBox::information(this,tr("tip"), tr("cannot find so you cannot delete!"),QMessageBox::Ok); } }
该项目的亮点之一是出色的ui设计. UI设计完成的很大一部分也归功于Qt强大的UI设计功能. 我们将Qt的ui模式下的操作设计过程可视化,并通过qss文件提供帮助,并且qss文件的语法与css非常相似,因此也很容易上手.
时空分析1.时间复杂度
此程序中使用的主要容器是map. 在C ++中,根据键的值搜索映射. 本质上,由于使用了红黑树的数据结构,因此搜索时的时间复杂度为O(logn). 在地图中插入键值对时,由于没有最佳的位置提示,因此插入和删除的时间复杂度为O(logn),而插入和删除多个键值对的时间复杂度为O(nlogn) ,但是由于这本书对用户信息的修改仅受到几次限制,因此时间复杂度可以直接视为O(logn).
读取文件时,已获得书的平均分数并存储了数据. 这里的时间复杂度是O(n). 回写文件时,它也是一次性写入的,时间复杂度也为O(n).
修改书籍和用户信息. 用户评分的时间复杂度为O(1).
冷启动推荐算法,根据信息相似度匹配用户,时间复杂度为O(n),依次取出用户的高评价书或根据200个最相似用户的评价预测当前用户评价,时间复杂度为O(1),因为相对于总共200,000个用户,可以将200个用户视为一个较小的常数.
基于用户的协作过滤算法,在为指定用户推荐书籍时,首先找到时间复杂度为O(n)的当前用户相似的用户,然后根据协作进行预测和计算过滤算法公式,因为每个用户阅读的书数不是太多且固定的,因此可以视为一个常数,时间复杂度为O(n).
总而言之,该实验的时间复杂度为O(n).
2. 空间复杂度
该程序的存储思想类似于稀疏矩阵. 它不是创建N * M用户手册的二维数组,而只是保存有意义的信息值. 尽管相同的键值对保存了两次(用户查看过每本书并对其进行评级,以及每个用户查看过哪本书和所评级),但这不会影响最终的空间复杂度,这等效于最终的空间复杂度. 是O(n * m). 并且地图容器的空间复杂度为O(n)和O(m). 因此,最终程序的空间复杂度为O(n * m).
未来展望和改进
因为该程序使用文件操作,并且该项目的数据集很大,所以三个csv文件总计118MB,因此程序入口处的文件读取操作很耗时,并且用户体验也很差. 由于第二学期的第二年没有学习相关课程,因此很遗憾没有使用存储. 我相信,如果这个项目以后可以使用存储数据,那肯定会在很大程度上改善用户体验.
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-186641-1.html
中国应该实行
离开制造业这个国民经济的基石
欧盟绝对不会放过这个机会正式转正