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

来源:互联网 发布:湖南省地质测绘院 知乎 编辑:程序博客网 时间:2024/06/09 21:48

学校数据结构的课程实验之一。
用到的数据结构: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;}

图书馆类:

#include <string>#include "B_tree.h"using namespace std;struct Book{    int number;    string name;    string introduction;    unsigned left;    Book(){}    Book(int num) :number(num), name(""), introduction(""), left(0){}//只有编号的初始化    Book(int num, string nam,string intro, unsigned lef)//完整初始化        :number(num),name(nam),introduction(intro),left(lef){}    void print()//显示信息    {        cout << "-------------------------------" << endl;        cout << "这本书的信息如下:" << endl;        cout << "编号: " << number << endl;        cout << "书名: " << name << endl;        cout << "简介: " << introduction << endl;        cout << "剩余数量: " << left << endl;        cout << "-------------------------------" << endl;    }    bool operator==(const Book &b) const//重载关系运算符    {        if(this->number == b.number) return true;//编号等即命中        else return false;    }    bool operator<(const Book &b) const    {        if (this->number < b.number) return true;        else return false;    }    bool operator>(const Book &b) const    {        if (this->number > b.number) return true;        else return false;    }};ofstream outFile;//输出流class Library{private:    B_tree<Book,3> books;    unsigned total;    static void readBook(Book &aBook)//写一本书的内容(一定要是静态的)     {        outFile<<aBook.number<<endl;        outFile<<aBook.name<<endl;        outFile<<aBook.introduction<<endl;        outFile << aBook.left << endl;    }    void readFile(const char filename[20])//读文件    {        total = 0;        ifstream inFile;        inFile.open(filename);        char trying;        while(inFile.is_open() && !inFile.eof())        {            //先试探是否为结束符            inFile >> trying;            if (trying == '#') break;            else            {                inFile.putback(trying);                int number;                inFile>>number;                string name;                inFile>>name;                string introduction;                inFile>>introduction;                unsigned left;                inFile>>left;                Book aBook=Book(number,name,introduction,left);                aBook.print();//显示这本书的信息                books.insert(aBook);                total+=left;            }                   }        cout << "库存共有图书" << total << "本"<<endl;        inFile.close();    }    void writeFile(const char filename[20])//写文件    {        outFile.open(filename);        books.traverse(readBook);        outFile << '#';//此处必须有一个结束标识符        outFile.close();    }    Book search(int num)//以编号为依据进行查找    {        Book se_book(num);        books.search_tree(se_book);        return se_book;    }    static void print(Book &aBook)//显示信息(必须是静态的)    {        cout << "-------------------------------" << endl;        cout << "这本书的信息如下:" << endl;        cout << "编号: " << aBook.number << endl;        cout << "书名: " << aBook.name << endl;        cout << "简介: " << aBook.introduction << endl;        cout << "剩余数量: " << aBook.left << endl;        cout << "-------------------------------" << endl;    }public:    Library(const char filename[20])    {        cout << "这是现在的库存信息:" << endl;        readFile(filename);    }    void add()//增加图书    {        cout << "请输入图书信息(编号 书名 简介 数量)" << endl;        int num;        string name;        string introduction;        unsigned left;        cin >> num >> name >> introduction >> left;        Book new_book = Book(num, name, introduction, left);        books.insert(new_book);        cout << "这本书已入库,信息如下:" << endl;        new_book.print();        total += left;    }    void display()//查看库存    {        cout << "这是现在的库存信息:" << endl;        books.traverse(print);        cout << "库存共有图书" << total << "本" << endl;    }    void remove()//删除    {        cout << "请输入要删除的图书编号:";        int num;        cin >> num;        Book &old_book =search(num);//通过编号找到这本书的记录        cout << "您即将删除这本书的所有信息:" << endl;        old_book.print();        cout << "确定要删除吗?[y/n]";        char choice;        cin >> choice;        if (choice == 'y')        {            books.remove(old_book);//删除这本书的记录            cout << "编号为" << num << "的书已成功从库中删除" << endl;            total--;        }           }    void lend()//借出    {        cout << "请输入要借出的图书编号:";        int num;        cin >> num;        Book &old_book = search(num);//通过编号找到这本书的记录        old_book.left--;        cout << "编号为" << num << "的图书已借出1本,下面是这本书的现存信息:" << endl;        old_book.print();        total--;    }    void change()//修改(先删除再添加)    {        cout << "请输入要修改的图书编号:";        int num;        cin >> num;        Book &old_book = search(num);        cout << "这是这本书的当前信息:" << endl;        old_book.print();//显示这本书之前的信息        books.remove(old_book);        cout << "请输入修改后的图书信息(编号 书名 简介 数量)" << endl;        string name;        string introduction;        unsigned left;        cin >> num >> name >> introduction >> left;        Book new_book = Book(num, name, introduction, left);        books.insert(new_book);        cout << "这本书的信息已修改为:" << endl;        new_book.print();    }    void back()//归还    {        cout << "请输入要归还的图书编号:";        int num;        cin >> num;        Book &old_book = search(num);//通过编号找到这本书的记录        old_book.left++;        cout << "编号为" << num << "的图书已归还,下面是这本书的现存信息:" << endl;        old_book.print();        total++;    }    void save(const char filename[20])    {        writeFile(filename);    }};这里写代码片

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

#include <iostream>using namespace std;enum Error_code{    success, not_present, overflow, duplicate_error};template <class Record, int order>//阶数(分支数)struct B_node{    int count;//成员数    Record data[order-1];    B_node<Record,order> *branch[order];    B_node(){count=0;}};template <class Record, int order>class B_tree{public:    B_tree(){root=NULL;}    Error_code search_tree(Record &target)    {        return recursive_search_tree(root,target);    }    Error_code insert(const Record &new_entry)    {        Record median;        B_node<Record,order> *right_branch, *new_root;        Error_code result=push_down(root,new_entry,median,right_branch);        if(result==overflow)        {            new_root=new B_node<Record,order>;            new_root->count=1;            new_root->data[0]=median;            new_root->branch[0]=root;            new_root->branch[1]=right_branch;            root=new_root;            result=success;        }        return result;    }    Error_code remove(const Record &target)    {        Error_code result;        result=recursive_remove(root, target);        if(root != NULL && root->count==0)        {            B_node<Record,order> *old_root=root;            root=root->branch[0];            delete old_root;        }        return result;    }    void traverse(void (*visit)(Record &))    {        recursie_traverse(root,visit);    }private:    B_node<Record, order> *root;    void recursie_traverse(B_node<Record,order> *current, void (*visit)(Record &))    {        if(current!=NULL)        {            for(int i=0; i<current->count; i++)                (*visit)(current->data[i]);            for(int i=0; i<current->count+1; i++)                recursie_traverse(current->branch[i], visit);        }    }    Error_code search_node(B_node<Record,order> *current, const Record &target, int &position) const    {        position=0;        while(position < current->count && (target > current->data[position]))            position++;        if(position < current->count && target == current->data[position])            return success;        else return not_present;    }    Error_code recursive_search_tree(B_node<Record,order> *current, Record &target)    {        Error_code result=not_present;        int position;        if(current != NULL)        {            result=search_node(current,target,position);            if(result==not_present)                result=recursive_search_tree(current->branch[position],target);            else                target=current->data[position];        }        return result;    }    void split_node(B_node<Record,order> *current, const Record &extra_entry,        B_node<Record,order> *extra_branch, int position,         B_node<Record,order>*&right_half, Record &median)    {        right_half=new B_node<Record,order>;        int mid=order/2;        if(position <= mid)        {            for(int i=mid; i<order-1; i++)            {                right_half->data[i-mid]=current->data[i];                right_half->branch[i+1-mid]=current->branch[i+1];            }            current->count=mid;            right_half->count=order-1-mid;            push_in(current,extra_entry,extra_branch,position);        }        else        {            mid++;            for(int i=mid; i<order-1; i++)            {                right_half->data[i-mid]=current->data[i];                right_half->branch[i+1-mid]=current->branch[i+1];            }            current->count=mid;            right_half->count=order-1-mid;            push_in(right_half,extra_entry,extra_branch,position-mid);        }        median=current->data[current->count-1];        right_half->branch[0]=current->branch[current->count];        current->count--;    }    void push_in(B_node<Record,order> *current, const Record &entry,        B_node<Record,order> *right_branch, int position)    {        for(int i=current->count; i>position; i--)        {            current->data[i]=current->data[i-1];            current->branch[i+1]=current->branch[i];        }        current->data[position]=entry;        current->branch[position+1]=right_branch;        current->count++;    }    Error_code push_down(B_node<Record,order> *current, const Record &new_entry,        Record &median, B_node<Record,order>*&right_branch)    {        Error_code result;        int position;        if(current==NULL)        {            median=new_entry;            right_branch=NULL;            result=overflow;        }        else        {            if(search_node(current,new_entry,position)==success)                result=duplicate_error;            else            {                Record extra_entry;                B_node<Record,order> *extra_branch;                result=push_down(current->branch[position],new_entry,                    extra_entry,extra_branch);                if(result==overflow)                {                    if(current->count < order-1)                    {                        result=success;                        push_in(current,extra_entry,extra_branch,position);                    }                    else                        split_node(current,extra_entry,extra_branch,position,                            right_branch,median);                }            }        }        return result;    }    void restore(B_node<Record,order> *current, int position)    {        if(position==current->count)            if(current->branch[position-1]->count > (order-1)/2)                move_right(current,position-1);            else                combine(current,position);        else if(position==0)            if(current->branch[1]->count > (order-1)/2)                move_left(current,1);            else                combine(current,1);        else            if(current->branch[position-1]->count > (order-1)/2)                move_right(current,position-1);            else if(current->branch[position+1]->count > (order-1)/2)                move_left(current,position+1);            else combine(current,position);    }    void move_left(B_node<Record,order> *current, int position)    {        B_node<Record,order> *left_branch=current->branch[position-1],        *right_branch=current->branch[position];        left_branch->data[left_branch->count]=current->data[position-1];        left_branch->branch[++left_branch->count]=right_branch->branch[0];        current->data[position-1]=right_branch->data[0];        right_branch->count--;        for(int i=0; i<right_branch->count; i++)        {            right_branch->data[i]=right_branch->data[i+1];            right_branch->branch[i]=right_branch->branch[i+1];        }        right_branch->branch[right_branch->count]=            right_branch->branch[right_branch->count+1];    }    void move_right(B_node<Record,order> *current, int position)    {        B_node<Record,order> *right_branch=current->branch[position+1],        *left_branch=current->branch[position];        right_branch->branch[right_branch->count+1]=            right_branch->branch[right_branch->count];        for(int i=right_branch->count; i>0; i--)        {            right_branch->data[i]=right_branch->data[i-1];            right_branch->branch[i]=right_branch->branch[i-1];        }        right_branch->count++;        right_branch->data[0]=current->data[position];        right_branch->branch[0]=left_branch->branch[left_branch->count--];        current->data[position]=left_branch->data[left_branch->count];    }    void combine(B_node<Record,order> *current, int position)    {        int i;        B_node<Record,order> *left_branch=current->branch[position-1],            *right_branch=current->branch[position];        left_branch->data[left_branch->count]=current->data[position-1];        left_branch->branch[++left_branch->count]=right_branch->branch[0];        for(i=0; i<right_branch->count; i++)        {            left_branch->data[left_branch->count]=right_branch->data[i];            left_branch->branch[++left_branch->count]=right_branch->branch[i+1];        }        current->count--;        for(i=position-1; i<current->count; i++)        {            current->data[i]=current->data[i+1];            current->branch[i+1]=current->branch[i+2];        }        delete right_branch;    }    void copy_in_predecessor(B_node<Record,order> *current, int position)    {        B_node<Record,order> *leaf=current->branch[position];        while(leaf->branch[leaf->count] != NULL)            leaf=leaf->branch[leaf->count];        current->data[position]=leaf->data[leaf->count-1];    }    void remove_data(B_node<Record,order> *current, int position)    {        for(int i=position; i<current->count-1; i++)            current->data[i]=current->data[i+1];        current->count--;    }    Error_code recursive_remove(B_node<Record,order> *current, const Record &target)    {        Error_code result;        int position;        if(current==NULL) result=not_present;        else        {            if(search_node(current,target,position)==success)            {                result=success;                if(current->branch[position]!=NULL)                {                    copy_in_predecessor(current,position);                    recursive_remove(current->branch[position],current->data[position]);                }                else                    remove_data(current,position);            }            else result=recursive_remove(current->branch[position],target);            if(current->branch[position]!=NULL)                if(current->branch[position]->count < (order-1)/2)                    restore(current,position);        }        return result;    }};
0 0