用B-树实现虚拟图书管理系统

学校数据结构的课程实验之一。

用到的数据结构:B-树

基本功能:对虚拟书库的图书进行查看、增加、删除、修改。

主函数:

#include <iostream>
#include "Library.h"
using namespace std;
int main()
{
    Library myLib=Library("books.txt");
    char choice=‘y‘;
    while(choice==‘y‘)
    {
        cout << "请选择操作"<<endl;
        cout << "--------------------------------" << endl;
        cout << "1----新书入库" << endl;
        cout << "2----查看库存" << endl;
        cout << "3----借阅" << endl;
        cout << "4----归还" << endl;
        cout << "5----删除旧书" << endl;
        cout << "6----修改图书信息" << endl;
        cout << "--------------------------------" << endl;
        int option;
        cin >> option;
        switch (option)
        {
        case 1: myLib.add(); break;
        case 2: myLib.display(); break;
        case 3: myLib.lend(); break;
        case 4: myLib.back(); break;
        case 5: myLib.remove(); break;
        case 6: myLib.change(); break;
        }
        cout << "继续吗?[y/n]";
        cin >> choice;
    }
    cout << "是否保存修改?[y/n]";
    cin >> choice;
    if (choice == ‘y‘)
        myLib.save("books.txt");//需要保存时保存文件
    return 0;
}

main.cpp

图书馆类:

  1 #include <fstream>
  2 #include <string>
  3 #include "B_tree.h"
  4 using namespace std;
  5
  6 struct Book
  7 {
  8     int number;
  9     string name;
 10     string introduction;
 11     unsigned left;
 12     Book(){}
 13     Book(int num) :number(num), name(""), introduction(""), left(0){}//只有编号的初始化
 14     Book(int num, string nam,string intro, unsigned lef)//完整初始化
 15         :number(num),name(nam),introduction(intro),left(lef){}
 16     void print()//显示信息
 17     {
 18         cout << "-------------------------------" << endl;
 19         cout << "这本书的信息如下:" << endl;
 20         cout << "编号: " << number << endl;
 21         cout << "书名: " << name << endl;
 22         cout << "简介: " << introduction << endl;
 23         cout << "剩余数量: " << left << endl;
 24         cout << "-------------------------------" << endl;
 25     }
 26     bool operator==(const Book &b) const//重载关系运算符
 27     {
 28         if(this->number == b.number) return true;//编号等即命中
 29         else return false;
 30     }
 31     bool operator<(const Book &b) const
 32     {
 33         if (this->number < b.number) return true;
 34         else return false;
 35     }
 36     bool operator>(const Book &b) const
 37     {
 38         if (this->number > b.number) return true;
 39         else return false;
 40     }
 41 };
 42 ofstream outFile;//输出流
 43
 44 class Library
 45 {
 46 private:
 47     B_tree<Book,3> books;
 48     unsigned total;
 49     static void readBook(Book &aBook)//写一本书的内容(一定要是静态的)
 50     {
 51         outFile<<aBook.number<<endl;
 52         outFile<<aBook.name<<endl;
 53         outFile<<aBook.introduction<<endl;
 54         outFile << aBook.left << endl;
 55     }
 56     void readFile(const char filename[20])//读文件
 57     {
 58         total = 0;
 59         ifstream inFile;
 60         inFile.open(filename);
 61         char trying;
 62         while(inFile.is_open() && !inFile.eof())
 63         {
 64             //先试探是否为结束符
 65             inFile >> trying;
 66             if (trying == ‘#‘) break;
 67             else
 68             {
 69                 inFile.putback(trying);
 70                 int number;
 71                 inFile>>number;
 72                 string name;
 73                 inFile>>name;
 74                 string introduction;
 75                 inFile>>introduction;
 76                 unsigned left;
 77                 inFile>>left;
 78                 Book aBook=Book(number,name,introduction,left);
 79                 aBook.print();//显示这本书的信息
 80                 books.insert(aBook);
 81                 total+=left;
 82             }
 83         }
 84         cout << "库存共有图书" << total << "本"<<endl;
 85         inFile.close();
 86     }
 87     void writeFile(const char filename[20])//写文件
 88     {
 89         outFile.open(filename);
 90         books.traverse(readBook);
 91         outFile << ‘#‘;//此处必须有一个结束标识符
 92         outFile.close();
 93     }
 94     Book search(int num)//以编号为依据进行查找
 95     {
 96         Book se_book(num);
 97         books.search_tree(se_book);
 98         return se_book;
 99     }
100     static void print(Book &aBook)//显示信息(必须是静态的)
101     {
102         cout << "-------------------------------" << endl;
103         cout << "这本书的信息如下:" << endl;
104         cout << "编号: " << aBook.number << endl;
105         cout << "书名: " << aBook.name << endl;
106         cout << "简介: " << aBook.introduction << endl;
107         cout << "剩余数量: " << aBook.left << endl;
108         cout << "-------------------------------" << endl;
109     }
110 public:
111     Library(const char filename[20])
112     {
113         cout << "这是现在的库存信息:" << endl;
114         readFile(filename);
115     }
116     void add()//增加图书
117     {
118         cout << "请输入图书信息(编号 书名 简介 数量)" << endl;
119         int num;
120         string name;
121         string introduction;
122         unsigned left;
123         cin >> num >> name >> introduction >> left;
124         Book new_book = Book(num, name, introduction, left);
125         books.insert(new_book);
126         cout << "这本书已入库,信息如下:" << endl;
127         new_book.print();
128         total += left;
129     }
130     void display()//查看库存
131     {
132         cout << "这是现在的库存信息:" << endl;
133         books.traverse(print);
134         cout << "库存共有图书" << total << "本" << endl;
135     }
136     void remove()//删除
137     {
138         cout << "请输入要删除的图书编号:";
139         int num;
140         cin >> num;
141         Book &old_book =search(num);//通过编号找到这本书的记录
142         cout << "您即将删除这本书的所有信息:" << endl;
143         old_book.print();
144         cout << "确定要删除吗?[y/n]";
145         char choice;
146         cin >> choice;
147         if (choice == ‘y‘)
148         {
149             books.remove(old_book);//删除这本书的记录
150             cout << "编号为" << num << "的书已成功从库中删除" << endl;
151             total--;
152         }
153     }
154     void lend()//借出
155     {
156         cout << "请输入要借出的图书编号:";
157         int num;
158         cin >> num;
159         Book &old_book = search(num);//通过编号找到这本书的记录
160         old_book.left--;
161         cout << "编号为" << num << "的图书已借出1本,下面是这本书的现存信息:" << endl;
162         old_book.print();
163         total--;
164     }
165     void change()//修改(先删除再添加)
166     {
167         cout << "请输入要修改的图书编号:";
168         int num;
169         cin >> num;
170         Book &old_book = search(num);
171         cout << "这是这本书的当前信息:" << endl;
172         old_book.print();//显示这本书之前的信息
173         books.remove(old_book);
174         cout << "请输入修改后的图书信息(编号 书名 简介 数量)" << endl;
175         string name;
176         string introduction;
177         unsigned left;
178         cin >> num >> name >> introduction >> left;
179         Book new_book = Book(num, name, introduction, left);
180         books.insert(new_book);
181         cout << "这本书的信息已修改为:" << endl;
182         new_book.print();
183     }
184     void back()//归还
185     {
186         cout << "请输入要归还的图书编号:";
187         int num;
188         cin >> num;
189         Book &old_book = search(num);//通过编号找到这本书的记录
190         old_book.left++;
191         cout << "编号为" << num << "的图书已归还,下面是这本书的现存信息:" << endl;
192         old_book.print();
193         total++;
194     }
195     void save(const char filename[20])
196     {
197         writeFile(filename);
198     }
199 };

Library.h

B-树的实现参考了经典教材"Data Structures and Program Design in C++" Robert L. Kruse, Alexander J. Ryba 高等教育出版社-影印版,代码如下:

  1 #include <iostream>
  2 using namespace std;
  3 enum Error_code
  4 {
  5     success, not_present, overflow, duplicate_error
  6 };
  7
  8 template <class Record, int order>//阶数(分支数)
  9 struct B_node
 10 {
 11     int count;//成员数
 12     Record data[order-1];
 13     B_node<Record,order> *branch[order];
 14     B_node(){count=0;}
 15 };
 16
 17 template <class Record, int order>
 18 class B_tree
 19 {
 20 public:
 21     B_tree(){root=NULL;}
 22     Error_code search_tree(Record &target)
 23     {
 24         return recursive_search_tree(root,target);
 25     }
 26     Error_code insert(const Record &new_entry)
 27     {
 28         Record median;
 29         B_node<Record,order> *right_branch, *new_root;
 30         Error_code result=push_down(root,new_entry,median,right_branch);
 31         if(result==overflow)
 32         {
 33             new_root=new B_node<Record,order>;
 34             new_root->count=1;
 35             new_root->data[0]=median;
 36             new_root->branch[0]=root;
 37             new_root->branch[1]=right_branch;
 38             root=new_root;
 39             result=success;
 40         }
 41         return result;
 42     }
 43     Error_code remove(const Record &target)
 44     {
 45         Error_code result;
 46         result=recursive_remove(root, target);
 47         if(root != NULL && root->count==0)
 48         {
 49             B_node<Record,order> *old_root=root;
 50             root=root->branch[0];
 51             delete old_root;
 52         }
 53         return result;
 54     }
 55     void traverse(void (*visit)(Record &))
 56     {
 57         recursie_traverse(root,visit);
 58     }
 59 private:
 60     B_node<Record, order> *root;
 61     void recursie_traverse(B_node<Record,order> *current, void (*visit)(Record &))
 62     {
 63         if(current!=NULL)
 64         {
 65             for(int i=0; i<current->count; i++)
 66                 (*visit)(current->data[i]);
 67             for(int i=0; i<current->count+1; i++)
 68                 recursie_traverse(current->branch[i], visit);
 69         }
 70     }
 71     Error_code search_node(B_node<Record,order> *current, const Record &target, int &position) const
 72     {
 73         position=0;
 74         while(position < current->count && (target > current->data[position]))
 75             position++;
 76         if(position < current->count && target == current->data[position])
 77             return success;
 78         else return not_present;
 79     }
 80     Error_code recursive_search_tree(B_node<Record,order> *current, Record &target)
 81     {
 82         Error_code result=not_present;
 83         int position;
 84         if(current != NULL)
 85         {
 86             result=search_node(current,target,position);
 87             if(result==not_present)
 88                 result=recursive_search_tree(current->branch[position],target);
 89             else
 90                 target=current->data[position];
 91         }
 92         return result;
 93     }
 94     void split_node(B_node<Record,order> *current, const Record &extra_entry,
 95         B_node<Record,order> *extra_branch, int position,
 96         B_node<Record,order>*&right_half, Record &median)
 97     {
 98         right_half=new B_node<Record,order>;
 99         int mid=order/2;
100         if(position <= mid)
101         {
102             for(int i=mid; i<order-1; i++)
103             {
104                 right_half->data[i-mid]=current->data[i];
105                 right_half->branch[i+1-mid]=current->branch[i+1];
106             }
107             current->count=mid;
108             right_half->count=order-1-mid;
109             push_in(current,extra_entry,extra_branch,position);
110         }
111         else
112         {
113             mid++;
114             for(int i=mid; i<order-1; i++)
115             {
116                 right_half->data[i-mid]=current->data[i];
117                 right_half->branch[i+1-mid]=current->branch[i+1];
118             }
119             current->count=mid;
120             right_half->count=order-1-mid;
121             push_in(right_half,extra_entry,extra_branch,position-mid);
122         }
123         median=current->data[current->count-1];
124         right_half->branch[0]=current->branch[current->count];
125         current->count--;
126     }
127     void push_in(B_node<Record,order> *current, const Record &entry,
128         B_node<Record,order> *right_branch, int position)
129     {
130         for(int i=current->count; i>position; i--)
131         {
132             current->data[i]=current->data[i-1];
133             current->branch[i+1]=current->branch[i];
134         }
135         current->data[position]=entry;
136         current->branch[position+1]=right_branch;
137         current->count++;
138     }
139     Error_code push_down(B_node<Record,order> *current, const Record &new_entry,
140         Record &median, B_node<Record,order>*&right_branch)
141     {
142         Error_code result;
143         int position;
144         if(current==NULL)
145         {
146             median=new_entry;
147             right_branch=NULL;
148             result=overflow;
149         }
150         else
151         {
152             if(search_node(current,new_entry,position)==success)
153                 result=duplicate_error;
154             else
155             {
156                 Record extra_entry;
157                 B_node<Record,order> *extra_branch;
158                 result=push_down(current->branch[position],new_entry,
159                     extra_entry,extra_branch);
160                 if(result==overflow)
161                 {
162                     if(current->count < order-1)
163                     {
164                         result=success;
165                         push_in(current,extra_entry,extra_branch,position);
166                     }
167                     else
168                         split_node(current,extra_entry,extra_branch,position,
169                             right_branch,median);
170                 }
171             }
172         }
173         return result;
174     }
175     void restore(B_node<Record,order> *current, int position)
176     {
177         if(position==current->count)
178             if(current->branch[position-1]->count > (order-1)/2)
179                 move_right(current,position-1);
180             else
181                 combine(current,position);
182         else if(position==0)
183             if(current->branch[1]->count > (order-1)/2)
184                 move_left(current,1);
185             else
186                 combine(current,1);
187         else
188             if(current->branch[position-1]->count > (order-1)/2)
189                 move_right(current,position-1);
190             else if(current->branch[position+1]->count > (order-1)/2)
191                 move_left(current,position+1);
192             else combine(current,position);
193     }
194     void move_left(B_node<Record,order> *current, int position)
195     {
196         B_node<Record,order> *left_branch=current->branch[position-1],
197         *right_branch=current->branch[position];
198         left_branch->data[left_branch->count]=current->data[position-1];
199         left_branch->branch[++left_branch->count]=right_branch->branch[0];
200         current->data[position-1]=right_branch->data[0];
201         right_branch->count--;
202         for(int i=0; i<right_branch->count; i++)
203         {
204             right_branch->data[i]=right_branch->data[i+1];
205             right_branch->branch[i]=right_branch->branch[i+1];
206         }
207         right_branch->branch[right_branch->count]=
208             right_branch->branch[right_branch->count+1];
209     }
210     void move_right(B_node<Record,order> *current, int position)
211     {
212         B_node<Record,order> *right_branch=current->branch[position+1],
213         *left_branch=current->branch[position];
214         right_branch->branch[right_branch->count+1]=
215             right_branch->branch[right_branch->count];
216         for(int i=right_branch->count; i>0; i--)
217         {
218             right_branch->data[i]=right_branch->data[i-1];
219             right_branch->branch[i]=right_branch->branch[i-1];
220         }
221         right_branch->count++;
222         right_branch->data[0]=current->data[position];
223         right_branch->branch[0]=left_branch->branch[left_branch->count--];
224         current->data[position]=left_branch->data[left_branch->count];
225     }
226     void combine(B_node<Record,order> *current, int position)
227     {
228         int i;
229         B_node<Record,order> *left_branch=current->branch[position-1],
230             *right_branch=current->branch[position];
231         left_branch->data[left_branch->count]=current->data[position-1];
232         left_branch->branch[++left_branch->count]=right_branch->branch[0];
233         for(i=0; i<right_branch->count; i++)
234         {
235             left_branch->data[left_branch->count]=right_branch->data[i];
236             left_branch->branch[++left_branch->count]=right_branch->branch[i+1];
237         }
238         current->count--;
239         for(i=position-1; i<current->count; i++)
240         {
241             current->data[i]=current->data[i+1];
242             current->branch[i+1]=current->branch[i+2];
243         }
244         delete right_branch;
245     }
246     void copy_in_predecessor(B_node<Record,order> *current, int position)
247     {
248         B_node<Record,order> *leaf=current->branch[position];
249         while(leaf->branch[leaf->count] != NULL)
250             leaf=leaf->branch[leaf->count];
251         current->data[position]=leaf->data[leaf->count-1];
252     }
253     void remove_data(B_node<Record,order> *current, int position)
254     {
255         for(int i=position; i<current->count-1; i++)
256             current->data[i]=current->data[i+1];
257         current->count--;
258     }
259     Error_code recursive_remove(B_node<Record,order> *current, const Record &target)
260     {
261         Error_code result;
262         int position;
263         if(current==NULL) result=not_present;
264         else
265         {
266             if(search_node(current,target,position)==success)
267             {
268                 result=success;
269                 if(current->branch[position]!=NULL)
270                 {
271                     copy_in_predecessor(current,position);
272                     recursive_remove(current->branch[position],current->data[position]);
273                 }
274                 else
275                     remove_data(current,position);
276             }
277             else result=recursive_remove(current->branch[position],target);
278             if(current->branch[position]!=NULL)
279                 if(current->branch[position]->count < (order-1)/2)
280                     restore(current,position);
281         }
282         return result;
283     }
284 };

B_tree.h

时间: 2024-11-05 02:24:11

用B-树实现虚拟图书管理系统的相关文章

Node.js 切近实战(二) 之图书管理系统(图书信息录入)

上一节我们讲了图书管理系统的登录,相信大家对jade模板和angular js也有了了解,今天的话我们来看一下图书信息录入.在这里我们准备使用Nosql数据库,本篇博客中使用的是MongoDB.OK.Mongo DB的安装我就不多说了,那么Node.Js平台使用mongoDB我们使用什么扩展包好呢,我觉得还是mongoose比较合适,封装了好多针对mongodb的方法,简单易用. 首先我们来看一下图书model的设计bookInfo.js. var mongoose = require('mon

[mysql+qt] 图书管理系统

一.图书管理数据库概念模式设计 图书管理系统包括了游客.用户登录.管理员登录三种模式. 在游客模式下,可以实现检索书籍的功能. 游客可以注册用户,但是借书权限需要管理员授予. 用户登录后,在检索书籍功能的基础上,还可以进行书籍的借阅,并且查看自己的借还情况. 管理员登录后,可以对图书进行管理,即入库新的书籍,也可以对用户进行管理,即授予用户借书证,注销用户. 二.数据库设计         管理员(manager) 属性 主码/外码 数据类型 说明 Username 主码 varchar(20)

部署图书管理系统

前戏: 一.python创建虚拟环境 fiel ----settings ---  Project  xxx   project interpreter  ---->右上角齿轮 选择路径,base interpreter 本体python解释器用3.6----ok   虚拟环境创建成功 二.确保开发环境的一致性 将本体python的所有包,安装在虚拟环境上 操作方法: 1. 导出当前python环境的包 pip3 reeeze > requirements.txt 2.创建一个虚拟环境mkvi

脚踏实地 志存高远-快意图书管理系统开发侧记之二

以网络技术为主的信息技术的飞速发展,使得图书管理信息化向着更加智能.快捷的方向不断变革.原有的一批图书管理软件的处理模式.软件架构.操作流程已不能满足网络时代所要求的双向互动.信息共享.高度智能的操作诉求.快意团队于2011年10月成立,并在调研数家企事业单位.大中专学校.中小学校图书管理业务流程及需求的基础上,研制了快意图书管理综合解决方案,开发了快意图书综合管理软件,并针对不同行业特点,进行了差异化开发,推出了快意图书管理企事业版本,中小学版本.大中专院校等多个版本,为不同行业图书管理提供了

图书管理系统

该图书馆里系统能实现基本的对图书信息的操作和借阅.归还功能. 一.主要内容: 本课程设计结合本学期所学C语言知识,数组.函数.结构体.指针.链表.文件读取操作等等,准备设计开发一个简单的图书管理系统.设计开发这个系统需要用到链表.文件读取操作.结构体.函数.指针.等C语言知识.本课程设计将会实现对图书信息的账号登录.注册账号.密码修改.密码查找.查找.输出.排序.备份.恢复.图书借阅和归还功能.本着简单.易用的设计原则,本课程设计在尽量优化界面在保证输入输出美观的同时又不失友好的交互界面. 本次

图书管理系统------软件设计图纸

图书管理系统------软件设计图纸 一.图书馆管理系统总体功能概述 图书馆管理系统功能图: 1.系统登录模块 : 本模块的功能点包括: (1) 判断用户名和密码是否相符: (2) 根据用户的权限类型,登录到系统的制定界面操作使用. 2.图书管理模块: 在本模块中图书馆工作人员可以对图书进行管理操作. 本模块的功能点包括: (1) 新书入库,将新进图书按其类型将图书的基本信息录入系统数据库: (2) 图书出库,某一部分图书会随着时间的增长及知识的更新而变得不再有收藏的价值,或者图书被损坏,这些图

图书管理系统测试计划说明书

图书管理系统测试计划说明书 一. 引言 1.1 编写目的 本测试计划文档作为指导此测试项目循序渐进的基础,帮助我们安排合适的资源和进度,避免可能的风险.本文档有助于实现以下目标: 1) 确定现有项目的信息和应测试的软件结构. 2) 列出推荐的测试需求 3) 推荐可采用的测试策略,并对这些策略加以详细说明 4) 确定所需的资源,并对测试的工作量进行估计. 5) 列出测试项目的可交付元素,包括用例以及测试报告等. 1.2 背景 随着人们知识层次的提高,阅读成为日常生活中不可缺少的一部分.而图书馆的存

s1考试 图书管理系统 结构体版

讲解目录 <保卫战:异形入侵>游戏开发    1 第一讲   游戏演示和资源的介绍    1 第二讲  "异形"怪物的实现    1 第三讲  "异形"怪物生命值的体现    9 第四讲  "异形"怪物死后处理    12 第五讲  玩家的制作    15 第六讲  玩家的行走控制(键盘)    16 第七讲  武器的切换(鼠标)     16 第八讲  摄像头的变化(鼠标)    19 第九讲  子弹预制体和特效的制作    20

Java图书管理系统(用Java常用集合实现)

图书管理系统 一.需求说明 1.功能:登录,注册,忘记密码,管理员管理,图书管理. 2.管理员管理:管理员的增删改查. 3.图书管理:图书的增删改查. 4.管理员属性包括:id,姓名,性别,年龄,家庭住址,手机号码,登录名称,登录密码,状态. 5.图书属性包括:id,图书名称,作者,单价,出版社,出版日期,类别. 6.技术:通过用集合来模拟数据库实现该系统,建议采用List集合实现,集合模拟数据库只是一个数据的临时保存. 二.功能说明 1.注册功能 描述:注册需要用户输入所有的必须的用户信息.