用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;
}

图书馆类:

#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;
    }
};
    原文作者:B树
    原文地址: https://blog.csdn.net/u012711841/article/details/44956081
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞