图书信息管理系统的设计与实现

一、实验内容

设计并实现一个图书信息管理系统。根据实验要求设计该系统的菜单和交互逻辑,并编码实现增删改查的各项功能。 该系统至少包含以下功能:

  1. 根据指定图书个数,逐个输入图书信息;
  2. 逐个显示图书表中所有图书的相关信息;
  3. 能根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中指定的位置;
  4. 根据指定的待出库的旧图书的位置,将该图书从图书表中删除;
  5. 能统计表中图书个数;
  6. 实现图书信息表的图书去重;
  7. 实现最爱书籍查询;
  8. 图书信息表按指定条件进行批量修改;
  9. 利用快速排序按照图书价格降序排序;
  10. 实现最贵图书的查找;

二、实验设计过程

本实验的图书信息定义三个方面的内容,采用结构体设计如下:

//图书信息的定义:
typedef struct {
    char no[13];   //13位书号
    char name[20]; //书名
    float price;     //价格
}Book;

本实验采用带头尾指针的单链表来储存图书信息,链表的结构体定义如下:

//链表的定义:
typedef struct LNode{
     Book   data;       //数据域
     struct LNode  *next;   //指针域
}LNode,*LinkList;

功能一和三、根据指定图书个数,逐个输入图书信息及指定位置插入图书

步骤:新建一个结点,存储图书的相关信息,未指定位置默认加在链表后面

//(1)读入相应的图书数据来完成图书信息表的创建,在尾结点插入图书信息
void BookLinkList:: Creat()
{
    bool flag=true;
    //新建一个结点,储存新插入的图书的信息
    LNode *p;
    p=new LNode;
    while(flag)
    {
        cin>>p->data.no;
        if(strcmp(p->data.no,"0 0 0"))
        {
            flag=false;
        }
        else
        {
            cin>>p->data.name;
            cin>>p->data.price;
            p->next=NULL;

            //将新建的结点插入链表中
            rear->next=p;

            //更新尾指针
            rear=p;
            length++;
            sum+=p->data.price;
            average=sum/length;
        }
    }
}

功能三实现:指定位置插入代码

//(3)在指定位置插入图书信息
void BookLinkList:: Location_Index()
{
    int location;
    cin>>location;
    if(location<=0 || location>length)
    {
        cout<<"抱歉,入库位置非法!\n";
    }
    else
    {
        //新建一个结点,储存新插入的图书的信息
        LNode *p;
        p=new LNode;
        cin>>p->data.no;
        cin>>p->data.name;
        cin>>p->data.price;

        int cout=location-1;
        LNode *s;
        s=head;
        //将新建的结点插入指定位置
        while(cout>0)
        {
            s=s->next;
            cout--;
        }

        LNode *q=s->next;

        //将新结点插入
        s->next=p;
        p->next=q;
        length++;
    }
}

功能二、逐个显示图书表中所有图书的相关信息;

//(2)逐个显示图书表中所有图书的相关信息
void BookLinkList::OutPut()
{
    cout<<"**************************************************"<<'\n';
    cout<<"图书表中的图书个数:"<<length<<'\n';
    LNode *p;
    p=head->next;
    
    cout<<fixed<<setprecision(2);//保留小数点后两位
    while(p != NULL)
    {
        cout<<p->data.no<<" ";
        cout<<p->data.name<<" ";
        cout<<p->data.price<<endl;
        
        p=p->next;
    }
}

功能四、根据指定的待出库的旧图书的位置,将该图书从图书表中删除;

//(4)将图书从图书表中删除
void BookLinkList::Delete()
{
    cout<<"输入要删除的图书在图书表中的位置:";
    int location;
    cin>>location;
    if(location<=0 || location>length)
    {
        cout<<"出库失败,未找到此书\n";
    }
    else
    {
        LNode *p;
        LNode *q=head;//遍历链表找到删除结点的位置
        int i=1;
        while(i<location)
        {
            q=q->next;
            i++;
        }
        p=q->next;//找到位置
        q->next=p->next;
        delete p;
        length--;
    }
}

功能六、实现图书信息表的图书去重;

使用两个指针变量遍历链表,删除书号相同的图书,保留第一个

具体代码实现如下:

//(6)实现图书信息表的图书去重
void BookLinkList::Remove()
{
    LNode *p=head->next;
    LNode *q=p;
    while (p != rear)
    {
        q=p;
        while(q != NULL)
        {
            if(strcmp(p->data.no,q->next->data.no) == 0)
            {
                LNode *s=q->next;
                q->next=s->next;
                length--;
                delete s;
                if(q->next == NULL)
                {
                    rear=q;
                    break;
                }
            }
            q=q->next;
        }
        p=p->next;
    }
    return;
}

功能七和十、实现最爱书籍查询及最贵图书查找;

原本实验要求折半查找,但是折半查找还需将链表排序,所以直接采用遍历单链表的方式更为方便时间复杂度O(n)

具体代码如下:

//(7)实现最爱书籍查询
void BookLinkList::SearchFavourite()
{
    LNode *q=head->next;
    int count=0;//统计有多少最爱图书数目
    char favourite[20]; //书名
    cin>>favourite;
    
    //遍历链表找最喜爱的书
    while(q != NULL)
    {
        if(favourite == q->data.name)
        {
            count++;
            cout<<q->data.no<<" ";
            cout<<q->data.name<<" ";
            cout<<q->data.price<<endl;
        }
        q=q->next;
    }
    if(count == 0)
    {
        cout<<"抱歉,没有你的最爱!";
    }
}

最贵图书可能不止一本,想过采用保存最贵图书的结点,最后输出,可是由于最贵图书可能不止一本就比较麻烦,还是采用遍历单链表直接找出最贵的价格,然后遍历链表直接输出与最高价格相同的图书

//(10)实现最贵图书的查找
void BookLinkList::SearchMExpensive()
{
    LNode *q=head->next;
    int count=0;//统计最贵书的数量
    int mexpensive=q->data.price;
    
    //遍历链表找最大数
    while(q != NULL)
    {
        q=q->next;
        if(mexpensive<q->data.price)
        {
            mexpensive=q->data.price;
        }
    }
    
    q=head->next;
    //遍历链表输出最贵的图书
    while(q != NULL)
    {
        if(mexpensive == q->data.price)
        {
            count++;
            cout<<q->data.no<<" ";
            cout<<q->data.name<<" ";
            cout<<q->data.price<<endl;
        }
        q=q->next;
    }
    
}

功能八、图书信息表按指定条件进行批量修改;

 输入所有要改价格的图书进行批量修改,然后输出修改价格后的图书信息

//(8)图书信息表按指定条件进行批量修改
void BookLinkList::Change()
{
    LNode *p=head->next;
    
    //循环链表中所有图书,修改价格
    while(p != NULL)
    {
        if(p->data.price<average)
        {
            p->data.price=p->data.price*1.2;//将所有低于平均价格的图书价格提高20%
            sum+=p->data.price*0.2;
            average=sum/length;
        }
        else
        {
            p->data.price=p->data.price*1.1;//所有高于或等于平均价格的图书价格提高10%
            sum+=p->data.price*0.1;
            average=sum/length;
        }
        p=p->next;
    }
    
    //输出修改价格后的图书表
    LNode *s;
    s=head->next;
    
    cout<<fixed<<setprecision(2);
    while(s != NULL)
    {
        cout<<s->data.no<<" ";
        cout<<s->data.name<<" ";
        cout<<s->data.price<<endl;
        
        s=s->next;
    }
}

功能九、利用快速排序按照图书价格降序排序;

由于单链表不支持下标访问,所以采用快排的基本思想稍稍修改的思路。

以单链表中第一个元素为基准进行排序,使用i,j对链表进行遍历。如果链表只有两个数直接排序交换,如果多个数,则将小于key的数放在i与j之间。再对key左右的元素进行左右递归。无序时的时间复杂度为O(nlogn),有序时的时间复杂度下降到O(n^2)。

第一次找位置的时候对 i 不进行i=i->next的操作,为了后面便于找到第一次快排后左子链的尾结点。流程如图所示:

具体代码实现如下:

//基于快排思想稍稍修改的排序
void BookLinkList::Quicksort(LinkList shead, LinkList srear)
{
    int jlocation=0;
    int ilocation=0;

    LinkList key=shead;
    LinkList i;
    i=key;
    LinkList j=i;
    //如果只有两个数,直接交换,提前结束
    if(shead->next == srear)
    {
        j=j->next;
        if(j->data.price>i->data.price)
        {
            swap(j->data.no,i->data.no);
            swap(j->data.name,i->data.name);
            swap(j->data.price,i->data.price);
        }
        return;
    }

    //若多个数采用快排,两个指针遍历
    while(j !=srear)
    {
        if(j==shead && j->next->data.price>key->data.price)
        {

            //如果j下一个数比key的值大,则交换,确保i与j之间的数比key小

            swap(j->next->data.no,i->next->data.no);
            swap(j->next->data.name,i->next->data.name);
            swap(j->next->data.price,i->next->data.price);

        }
        else if(j->next->data.price>key->data.price)
        {
            //如果j下一个数比key的值大,则交换,确保i与j之间的数比key小
            i=i->next;
            ilocation++;
            swap(j->next->data.no,i->next->data.no);
            swap(j->next->data.name,i->next->data.name);
            swap(j->next->data.price,i->next->data.price);
        }

        j=j->next;
        jlocation++;
    }

    swap(key->data.no,i->next->data.no);
    swap(key->data.name,i->next->data.name);
    swap(key->data.price,i->next->data.price);

    //对右边子链递归
    if(jlocation-ilocation>1)
        Quicksort(i->next->next,j);
    //对左边子链进行递归
    if(ilocation>0)
        Quicksort(shead,i);


}
//(9)利用快速排序按照图书价格降序排序
void BookLinkList::Sort()
{
    if(length == 0 && length == 1)
    {
        return;
    }
    Quicksort(head->next,rear);

    return;
}

三、实验完整代码

booklinklist.h头文件

#ifndef BOOKINFORMATION_H
#define BOOKINFORMATION_H

#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;

//图书信息的定义:
typedef struct {
    char no[13];   //13位书号
    char name[20]; //书名
    float price;     //价格
}Book;


//链表的定义:
typedef struct LNode{
     Book   data;       //数据域
     struct LNode  *next;   //指针域
}LNode,*LinkList;

//基于链式存储结构的图书信息表
class BookLinkList
{
public:
    BookLinkList();//建立一个带头结点的单链表
    void Creat();//读入相应的图书数据来完成图书信息表的创建
    void Location_Index();//指定位置插入图书信息
    void OutPut();//输出信息
    void Delete();//将图书从图书表中删除
    void GetLength();//得到图书表中图书的个数
    void Remove();//图书信息表的图书去重
    void SearchFavourite();//(7)实现最爱书籍查询,根据书名进行折半查找
    void Change();//图书信息表的修改
    void Sort();//利用快速排序按照图书价格降序排序
    void Quicksort(LinkList shead, LinkList srear);//快排关键代码
    void SearchMExpensive();//实现最贵图书的查找
    ~BookLinkList();//释放所有结点

private:
    LNode *head;//头指针
    LNode *rear;//尾指针
    int length;
    float sum;//计算总价格
    float average;//计算平均价格;

};

#endif // BOOKINFORMATION_H

booklinklist.cpp文件

#include "booklinklist.h"

//建立一个带头结点的单链表
BookLinkList::BookLinkList()
{
    length=0;
    sum=0;
    average=0;
    head=new LNode;
    rear=head;
    rear->next=NULL;
}

//(1)读入相应的图书数据来完成图书信息表的创建,在尾结点插入图书信息
void BookLinkList:: Creat()
{
    cout<<"输入样例:\n";
    cout<<"9787302257646 程序设计基础 25.00\n";
    cout<<"若想要结束,则输出:";
    cout<<"0 0 0\n";
    
    while(true)
    {
        //新建一个结点,储存新插入的图书的信息
        LNode *p;
        p=new LNode;
        cin>>p->data.no;
        cin>>p->data.name;
        cin>>p->data.price;
        p->next=NULL;
        if(!strcmp(p->data.no,"0") && !strcmp(p->data.name,"0") && p->data.price == 0)
        {
            return;
        }
        else
        {
            //将新建的结点插入链表中
            rear->next=p;
            
            //更新尾指针
            rear=p;
            length++;
            sum+=p->data.price;
            average=sum/length;
        }
    }
}

//(2)逐个显示图书表中所有图书的相关信息
void BookLinkList::OutPut()
{
    cout<<"**************************************************"<<'\n';
    cout<<"图书表中的图书个数:"<<length<<'\n';
    LinkList p;
    p=head->next;
    
    cout<<fixed<<setprecision(2);//保留小数点后两位
    while(p != NULL)
    {
        cout<<p->data.no<<" "<<p->data.name<<" "<<p->data.price<<endl;
        
        p=p->next;
    }
    cout<<'\n';
}

//(3)在指定位置插入图书信息
void BookLinkList:: Location_Index()
{
    cout<<"输入样例:\n";
    cout<<"2\n";
    cout<<"9787302265436  计算机导论实验指导 18.00\n";
    
    int location;
    cin>>location;
    if(location<=0 || location>length)
    {
        cout<<"抱歉,入库位置非法!\n";
    }
    else
    {
        //新建一个结点,储存新插入的图书的信息
        LNode *p;
        p=new LNode;
        cin>>p->data.no;
        cin>>p->data.name;
        cin>>p->data.price;
        
        int cout=location-1;
        LNode *s;
        s=head;
        //将新建的结点插入指定位置
        while(cout>0)
        {
            s=s->next;
            cout--;
        }
        
        LNode *q=s->next;
        
        //将新结点插入
        s->next=p;
        p->next=q;
        length++;
    }
    cout<<'\n';
}

//(4)将图书从图书表中删除
void BookLinkList::Delete()
{
    cout<<"输入要删除的图书在图书表中的位置:";
    int location;
    cin>>location;
    if(location<=0 || location>length)
    {
        cout<<"出库失败,未找到此书\n";
    }
    else
    {
        LNode *p;
        LNode *q=head;//遍历链表找到删除结点的位置
        int i=1;
        while(i<location)
        {
            q=q->next;
            i++;
        }
        p=q->next;//找到位置
        q->next=p->next;
        length--;
        sum-=p->data.price;
        average=sum/length;
        delete p;
    }
}

//(5)得到图书表中图书的个数
void BookLinkList::GetLength()
{
    cout<<"图书个数为:"<<length<<'\n';
}

//(6)实现图书信息表的图书去重
void BookLinkList::Remove()
{
    LNode *p=head->next;
    LNode *q=p;
    while (p != rear)
    {
        q=p;
        while(q != NULL)
        {
            if(strcmp(p->data.no,q->next->data.no) == 0)
            {
                LNode *s=q->next;
                q->next=s->next;
                length--;
                delete s;
                if(q->next == NULL)
                {
                    rear=q;
                    break;
                }
            }
            q=q->next;
        }
        p=p->next;
    }
    return;
}

//(7)实现最爱书籍查询
void BookLinkList::SearchFavourite()
{
    LNode *q=head->next;
    int count=0;//统计有多少最爱图书数目
    char favourite[20]; //书名
    cout<<"输入最喜爱的书的书名:";
    cin>>favourite;
    
    //遍历链表找最喜爱的书
    while(q != NULL)
    {
        if(strcmp(favourite,q->data.name) == 0)
        {
            count++;
            cout<<q->data.no<<" ";
            cout<<q->data.name<<" ";
            cout<<q->data.price<<endl;
        }
        q=q->next;
    }
    if(count == 0)
    {
        cout<<"抱歉,没有你的最爱!";
    }
}

//(8)图书信息表按指定条件进行批量修改
void BookLinkList::Change()
{
    LNode *p=head->next;
    
    //循环链表中所有图书,修改价格
    while(p != NULL)
    {
        if(p->data.price<average)
        {
            p->data.price=p->data.price*1.2;//将所有低于平均价格的图书价格提高20%
            sum+=p->data.price*0.2;
            average=sum/length;
        }
        else
        {
            p->data.price=p->data.price*1.1;//所有高于或等于平均价格的图书价格提高10%
            sum+=p->data.price*0.1;
            average=sum/length;
        }
        p=p->next;
    }
    
    //输出修改价格后的图书表
    LNode *s;
    s=head->next;
    
    cout<<fixed<<setprecision(2);
    while(s != NULL)
    {
        cout<<s->data.no<<" ";
        cout<<s->data.name<<" ";
        cout<<s->data.price<<endl;
        
        s=s->next;
    }
}

//基于快排思想稍稍修改的排序
void BookLinkList::Quicksort(LinkList shead, LinkList srear)
{
    int jlocation=0;
    int ilocation=0;
    
    LinkList key=shead;
    LinkList i;
    i=key;
    LinkList j=i;
    //如果只有两个数,直接交换,提前结束
    if(shead->next == srear)
    {
        j=j->next;
        if(j->data.price>i->data.price)
        {
            swap(j->data.no,i->data.no);
            swap(j->data.name,i->data.name);
            swap(j->data.price,i->data.price);
        }
        return;
    }
    
    //若多个数采用快排,两个指针遍历
    while(j !=srear)
    {
        if(j==shead && j->next->data.price>key->data.price)
        {
            
            //如果j下一个数比key的值大,则交换,确保i与j之间的数比key小
            
            swap(j->next->data.no,i->next->data.no);
            swap(j->next->data.name,i->next->data.name);
            swap(j->next->data.price,i->next->data.price);
            
        }
        else if(j->next->data.price>key->data.price)
        {
            //如果j下一个数比key的值大,则交换,确保i与j之间的数比key小
            i=i->next;
            ilocation++;
            swap(j->next->data.no,i->next->data.no);
            swap(j->next->data.name,i->next->data.name);
            swap(j->next->data.price,i->next->data.price);
        }
        
        j=j->next;
        jlocation++;
    }
    
    swap(key->data.no,i->next->data.no);
    swap(key->data.name,i->next->data.name);
    swap(key->data.price,i->next->data.price);
    
    //对右边子链递归
    if(jlocation-ilocation>1)
        Quicksort(i->next->next,j);
    //对左边子链进行递归
    if(ilocation>0)
        Quicksort(shead,i);
    
    
}
//(9)利用快速排序按照图书价格降序排序
void BookLinkList::Sort()
{
    if(length == 0 && length == 1)
    {
        return;
    }
    Quicksort(head->next,rear);
    
    return;
}

//(10)实现最贵图书的查找
void BookLinkList::SearchMExpensive()
{
    LNode *q=head->next;
    int count=0;//统计最贵书的数量
    int mexpensive=q->data.price;
    
    //遍历链表找最大数
    while(q != NULL)
    {
        q=q->next;
        if(mexpensive<q->data.price)
        {
            mexpensive=q->data.price;
        }
    }
    
    q=head->next;
    //遍历链表输出最贵的图书
    while(q != NULL)
    {
        if(mexpensive == q->data.price)
        {
            count++;
            cout<<q->data.no<<" ";
            cout<<q->data.name<<" ";
            cout<<q->data.price<<endl;
        }
        q=q->next;
    }
    
}

//(11)释放所有结点
BookLinkList::~BookLinkList()
{
    LNode *p;
    LNode *q=head;
    while(length!=0)
    {
        while(q->next != rear)
        {
            q=q->next;
        }
        p=q->next;
        rear=q;
        delete p;
        length--;
    }
}


main.cpp代码

#include "booklinklist.h"

int main()
{
    int number=0;
    bool flag=true;
    BookLinkList book;
    cout<<"改图书信息管理系统包含如下功能:\n";
    cout<<"(1)	根据指定图书个数,逐个输入图书信息;\n";
    cout<<"(2)	逐个显示图书表中所有图书的相关信息;\n";
    cout<<"(3)	能根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中指定的位置;\n";
    cout<<"(4)	根据指定的待出库的旧图书的位置,将该图书从图书表中删除;\n";
    cout<<"(5)	能统计表中图书个数;\n";
    cout<<"(6)	实现图书信息表的图书去重;\n";
    cout<<"(7)	实现最爱书籍查询;\n";
    cout<<"(8)	图书信息表按指定条件进行批量修改;\n";
    cout<<"(9)	利用快速排序按照图书价格降序排序;\n";
    cout<<"(10)	实现最贵图书的查找;\n";
    cout<<"若要实现以上任一功能,";

    while(flag)
    {
        cout<<"请输入各个功能前的数字编号,若不需要则输入11\n";
        cin>>number;
        switch(number)
        {
        case 1:
            book.Creat();
            book.OutPut();;
            break;
        case 2:
            book.OutPut();;
            break;
        case 3:
            book.Location_Index();
            book.OutPut();
            break;
        case 4:
            book.Delete();
            book.OutPut();
            break;
        case 5:
            book.GetLength();
            break;
        case 6:
            book.Remove();
            book.OutPut();
            break;
        case 7:
            book.SearchFavourite();
            break;
        case 8:
            book.Change();
            break;
        case 9:
            book.Sort();
            book.OutPut();
            break;
        case 10:
            book.SearchMExpensive();
            break;
        default:
            cout<<"输入数字无效";
            flag=false;
            return(true);
        }
    }
    book.~BookLinkList();
}

四、实验运行结果

功能一运行结果:

功能二、三运行结果:

功能四运行结果:

功能五运行结果:

功能六运行结果:

输入的带重的图书表为:

去重后运行结果:

功能七运行结果:

功能八运行结果:

功能九运行结果:

功能十运行结果:

  • 2
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值