数据结构C语⾔_线性表之顺序表_图书信息管理系统
最近在看严蔚敏的《数据结构C语⾔版|第2版》,看完了线性表,写了⽤顺序表实现的图书信息管理系统。
经测试可以成功运⾏。但是输⼊⼩数就会出bug。
操作系统:Windows 10
编译器:Visual Studio 2022 preview
个⼈撰写,仅供参考。
然后说⼀下代码实现的主要功能,⼀共是6个功能。输⼊数字执⾏对应功能。
1 - 添加图书
2 - 查图书
3 - 删除图书
4 - 打印图书信息 (⽅便查看运⾏结果)
5 - 插⼊图书
6 - 修改图书信息
书中对此系统的描述:
【案例分析】 把图书表抽象成⼀个线性表,每本图书(包括ISBN、书名、定价)作为线性表中的⼀个元素。
现在写⼀下⾃⼰对两个结构体的理解。
结构体的定义
⽐如图书馆想新增⼀本书,那么,先买到这本书,在电脑中登记书的信息,接着把书放到某个书架上。
在计算机中要想创建这本书,就需要为书分配⼀定的内存空间。分配给书的内存包括两部分,⼀部分是书本⾝携带的数据,另⼀部分是书所在的书架位置。
结构体BookList是⽤来存储书本⾝信息的。
BookList是⼀个⽤来封装书籍数据的结构体,携带的数据包括:书的ISBN、书名和书的定价。
typedef//重命名
struct BookList//重命名的对象
{
int ISBN;// 书的ISBN
char bookName[20];// 书名
int price;// 书的定价
}
Book;//新名字
有了封装好的书之后,接着要确定书放在哪个书架上。
在计算机中,也就是确定书所在的内存地址。
由于顺序表的特性,书的位置在内存中是相邻的,因⽽可以将顺序表看成⼀个数组。
an = a1 + (n-1) * q
an—— 第n本书所在地址
a1—— 第1本书所在地址
q—— 1本书所占的内存空间
为数组中的每本书分配⼀个下标elem,并存储当前总共的书籍数量n,如此封装之后,便得到⼀个新的结构体。
typedef struct List
{
Book* elem;// 存储空间的基地址
int number;// n
}List;
函数解释
插⼊函数Insert
通过掌握这个函数,理解顺序表的存储⽅式。
⾸先⽤if判断是否达到存储空间上限。
if(当前元素数量加⼀⼤于上限)
return;
如果if中是这样的:
if(L.number +1> MAXSIZE)
L.number将会逻辑加1。导致还没有插⼊元素,元素数量就莫名其妙多出来⼀个。
所以需要定义⼀个局部变量num,将L.number+1赋值给num。
int num = L.number +1;
if(num > MAXSIZE)
return false;
另⼀个注意点——元素的挪动
这⾥可以联想实际⽣活中的排队,我们把要插⼊的元素看做⼩明同学。⼩明要么排在队伍最后,要么插队。当⼩明排在队伍最后,其他⼈不需要移动。如果⼩明插队,则⼩明之后的⼈都需要往后移动⼀格。
因⽽,在顺序表中插⼊⼀个元素时,也考虑2种情况:
第1种情况,元素插在队尾。此时不需要挪动其他元素,整体元素数量+1。
顺序表的[队尾]=⼩明;
顺序表的总个数++;
在结构体中,可以把 “.” 运算符读作 “的” 。把上⾯的 “的” 换成 “.”
顺序表.[队尾]=⼩明;
顺序表.总个数++;
再把“顺序表”换成顺序表的变量名“L”,“总个数”换成“number”,“⼩明”换成“book”,“队尾下标”换成“i-1”(存储的第1个元素下标为0,第2个元素下标是1,…,第i个元素的下标是i-1)。
L.elem[i-1]= book;
L.number++;
第2种情况,元素不插在队尾。此时它后⾯的所有元素都需要往后挪动⼀格。
移动的次序是什么样的呢?继续想象⼀个队伍。
队伍最后⼀个⼈往后移动⼀格,
倒数第⼆个⼈往后移动⼀格,
…,
⼩明之后的所有⼈都往后移动了⼀格,
队伍出现了⼀个空位,
⼩明进⼊空位,
⼩明插队成功。
移动的步骤,使⽤⼀个for循环,把⼩明后⾯的元素统统往后挪动⼀格。从最后⼀个⼈开始,到⼩明之后的那1个⼈(包括此⼈)结束。for(int j = L.number-1; j >= i-1; j--)//从后往前挪动存储单元
代码大全书籍{
L.elem[j+1]= L.elem[j];
}
最后插⼊⼩明。这和第⼀种情况的插⼊⽅式是⼀样的,可以合并。
L.elem[i-1]= book;
L.number++;
因此,挪动元素、插⼊元素、总数+1合起来的代码是这样的。
for(int j = L.number-1; j >= i-1; j--)//从后往前挪动存储单元
{
L.elem[j+1]= L.elem[j];
}
L.elem[i-1]= book;
L.number++;
最后把整个函数合在⼀起。
bool Insert(List& L,int i)
{
// 如果使⽤if(L.number + 1 > MAXSIZE)语句,L.number将会逻辑加1,从⽽导致输出错误。所以需要定义⼀个局部变量num,将L.number+1赋值给num。if(int num = L.number +1> MAXSIZE)
return false;
Book book;// 保存⽤户输⼊的数据
printf("请输⼊图书的ISBN,以回车结束:");
std::cin >> book.isbn;
printf("请输⼊书名,以回车结束:");
std::cin >> book.bookName;
printf("请输⼊图书价格,以回车结束:");
std::cin >> book.price;
for(int j = L.number-1; j >= i-1; j--)//从后往前挪动存储单元
{
L.elem[j+1]= L.elem[j];
}
L.elem[i-1]= book;
L.number++;
return true;
}
运⾏结果
主提⽰
添加图书:
查图书
删除图书(故意输了⼀个错值)
源码
#include<iostream>
#define MAXSIZE 100
typedef struct BookList
{
int isbn;
char bookName[20];
int price;
}Book;
typedef struct List
{
Book* elem;// 存储空间的基地址(这句注释是抄了书上的)int number;
}List;
void initList(List &L)
{
{
L.elem = new Book[MAXSIZE];
if(!L.elem)
printf("初始化失败\n");
L.number =0;
printf("初始化成功\n");
}
bool SearchElem(List& L,int i)
{
if(i <1)
{
printf("输⼊的图书序号为负。当前图书数量:%d\n",L.number);
return false;
}
if(i > L.number)
{
printf("列表中不存在此图书。当前图书数量:%d\n", L.number);
return false;
}
Book* p =&L.elem[i -1];
printf("到图书----------------------\n");
std::cout <<"ISBN:"<< p->isbn <<" 书名:"<< p->bookName <<" 价格:"<< p->price <<"\n"; return true;
}
void Add(List& L,int n)
{
int i =0;
while(i < n && L.number != MAXSIZE)
{
Book book;//创建结构体BookList的⼀个成员book 存储⽤户输⼊的数据信息
std::cout <<"正在添加第"<< i+1<<"本图书:\n";
printf("请输⼊图书的ISBN,以回车结束:");
std::cin >> book.isbn;
printf("请输⼊书名,以回车结束:");
std::cin >> book.bookName;
printf("请输⼊图书价格,以回车结束:");
std::cin >> book.price;
L.elem[L.number]= book;//不是i-1
L.number++;//书籍数量+1
i++;
std::cout <<"添加图书成功!\n"<<"当前书籍数量:"<< L.number <<"\n";
}
printf("结束添加\n");
}
bool Insert(List& L,int i)
{
// 如果⽤if(L.number + 1 > MAXSIZE)语句,L.number将会逻辑加1,从⽽导致输出错误
if(int num = L.number +1> MAXSIZE)
return false;
Book book;
printf("请输⼊图书的ISBN,以回车结束:");
std::cin >> book.isbn;
printf("请输⼊书名,以回车结束:");
std::cin >> book.bookName;
printf("请输⼊图书价格,以回车结束:");
std::cin >> book.price;
for(int j = L.number-1; j >= i-1; j--)//从后往前挪动存储单元
{
L.elem[j+1]= L.elem[j];