用C语言手搓一个图书管理系统从顺序表到链表的完整实现第一次接触数据结构时总觉得那些抽象的概念离实际开发很远。直到某天在图书馆借书看着管理员在电脑上快速检索、入库、出库突然意识到这不就是线性表的完美应用场景吗于是决定用C语言实现一个完整的图书管理系统把课本上的顺序表和链表真正用起来。这个项目不仅帮我通过了数据结构考试还成了简历上的亮点。下面我会分享从零开始的完整实现过程包含可直接运行的源码特别适合正在学习《数据结构》的C语言初学者。1. 系统设计与数据结构选型图书管理系统需要处理的核心操作包括图书信息的存储与检索新书入库与旧书出库图书信息修改价格排序与统计重复书籍检测数据结构对比分析特性顺序表链表内存占用连续空间可能浪费动态分配无浪费插入/删除效率O(n)O(1)随机访问效率O(1)O(n)实现难度简单中等// 图书信息结构体定义 typedef struct { char isbn[20]; // 国际标准书号 char name[50]; // 书名 float price; // 价格 } Book;2. 顺序表实现方案顺序表适合数据量固定、查询频繁的场景。我们先实现基础功能2.1 顺序表初始化与内存管理#define MAX_SIZE 1000 typedef struct { Book *elements; // 存储空间基地址 int length; // 当前图书数量 } SeqList; int InitList(SeqList *L) { L-elements (Book*)malloc(MAX_SIZE * sizeof(Book)); if(!L-elements) exit(OVERFLOW); L-length 0; return OK; }内存管理要点预分配固定大小的连续内存空间需要检查分配是否成功记得在程序结束时释放内存2.2 核心功能实现图书入库操作示例int InsertBook(SeqList *L, int position, Book book) { if (position 1 || position L-length 1) { return ERROR; // 非法位置 } if (L-length MAX_SIZE) { return OVERFLOW; // 存储空间已满 } // 移动元素腾出空间 for(int i L-length; i position; i--) { L-elements[i] L-elements[i-1]; } L-elements[position-1] book; L-length; return OK; }价格调整算法void AdjustPrices(SeqList *L) { float total 0; for(int i 0; i L-length; i) { total L-elements[i].price; } float avg total / L-length; for(int i 0; i L-length; i) { if(L-elements[i].price avg) { L-elements[i].price * 1.1; // 高于平均价涨10% } else { L-elements[i].price * 1.2; // 低于平均价涨20% } } }3. 链表实现方案当需要频繁插入删除时链表是更好的选择。我们采用带头结点的单链表实现3.1 链表结构定义typedef struct LNode { Book data; struct LNode *next; } LNode, *LinkList; int InitList(LinkList *L) { *L (LinkList)malloc(sizeof(LNode)); if(!*L) exit(OVERFLOW); (*L)-next NULL; return OK; }3.2 链表特色操作链表逆序存储实现void ReverseList(LinkList *L) { LNode *prev NULL; LNode *current (*L)-next; LNode *next NULL; while(current ! NULL) { next current-next; current-next prev; prev current; current next; } (*L)-next prev; }链表去重算法void RemoveDuplicates(LinkList *L) { LNode *current (*L)-next; while(current ! NULL) { LNode *runner current; while(runner-next ! NULL) { if(strcmp(runner-next-data.isbn, current-data.isbn) 0) { LNode *temp runner-next; runner-next runner-next-next; free(temp); } else { runner runner-next; } } current current-next; } }4. 性能优化实战技巧在实际开发中我们还需要考虑以下优化点4.1 混合存储策略结合顺序表和链表的优点主存储使用顺序表便于快速检索最近操作记录使用链表实现LRU缓存typedef struct { SeqList main_storage; // 主存储 LinkList recent_ops; // 最近操作缓存 int cache_size; // 缓存大小 } HybridStorage;4.2 索引优化为常用查询字段建立索引typedef struct { char isbn[20]; int position; // 在顺序表中的位置 } ISBN_Index; ISBN_Index *CreateISBNIndex(SeqList *L) { ISBN_Index *index (ISBN_Index*)malloc(L-length * sizeof(ISBN_Index)); for(int i0; iL-length; i) { strcpy(index[i].isbn, L-elements[i].isbn); index[i].position i; } // 按ISBN排序索引 qsort(index, L-length, sizeof(ISBN_Index), CompareISBN); return index; }4.3 文件持久化将数据保存到文件实现持久化void SaveToFile(SeqList *L, const char *filename) { FILE *fp fopen(filename, wb); if(fp NULL) return; fwrite((L-length), sizeof(int), 1, fp); fwrite(L-elements, sizeof(Book), L-length, fp); fclose(fp); } int LoadFromFile(SeqList *L, const char *filename) { FILE *fp fopen(filename, rb); if(fp NULL) return ERROR; fread((L-length), sizeof(int), 1, fp); L-elements (Book*)malloc(L-length * sizeof(Book)); fread(L-elements, sizeof(Book), L-length, fp); fclose(fp); return OK; }5. 完整系统实现将各个模块组合成完整系统int main() { SeqList bookList; InitList(bookList); // 加载初始数据 if(LoadFromFile(bookList, books.dat) ! OK) { printf(初始化图书数据...\n); // 添加示例图书 Book sampleBooks[5] { {9787302257646, 程序设计基础, 25.00}, {9787302164340, 程序设计基础(第2版), 20.00}, {9787302219972, 单片机技术及应用, 32.00}, {9787302203513, 单片机原理与应用技术, 26.00}, {7810827430, 工业计算机控制技术, 29.00} }; for(int i0; i5; i) { InsertBook(bookList, i1, sampleBooks[i]); } } // 主菜单界面 while(1) { printf(\n图书管理系统\n); printf(1. 添加新书\n); printf(2. 删除图书\n); printf(3. 查询图书\n); printf(4. 价格调整\n); printf(5. 保存退出\n); int choice; scanf(%d, choice); switch(choice) { case 1: AddBook(bookList); break; case 2: DeleteBook(bookList); break; case 3: SearchBook(bookList); break; case 4: AdjustPrices(bookList); break; case 5: SaveToFile(bookList, books.dat); free(bookList.elements); return 0; default: printf(无效选择\n); } } }实现这个系统的过程中最深的体会是数据结构的选择会极大影响系统性能。当图书数量超过5000本时顺序表的插入操作明显变慢这时就需要考虑改用链表或其他更高效的数据结构。
用C语言手搓一个图书管理系统:从顺序表到链表的完整实现(附严蔚敏数据结构实验源码)
用C语言手搓一个图书管理系统从顺序表到链表的完整实现第一次接触数据结构时总觉得那些抽象的概念离实际开发很远。直到某天在图书馆借书看着管理员在电脑上快速检索、入库、出库突然意识到这不就是线性表的完美应用场景吗于是决定用C语言实现一个完整的图书管理系统把课本上的顺序表和链表真正用起来。这个项目不仅帮我通过了数据结构考试还成了简历上的亮点。下面我会分享从零开始的完整实现过程包含可直接运行的源码特别适合正在学习《数据结构》的C语言初学者。1. 系统设计与数据结构选型图书管理系统需要处理的核心操作包括图书信息的存储与检索新书入库与旧书出库图书信息修改价格排序与统计重复书籍检测数据结构对比分析特性顺序表链表内存占用连续空间可能浪费动态分配无浪费插入/删除效率O(n)O(1)随机访问效率O(1)O(n)实现难度简单中等// 图书信息结构体定义 typedef struct { char isbn[20]; // 国际标准书号 char name[50]; // 书名 float price; // 价格 } Book;2. 顺序表实现方案顺序表适合数据量固定、查询频繁的场景。我们先实现基础功能2.1 顺序表初始化与内存管理#define MAX_SIZE 1000 typedef struct { Book *elements; // 存储空间基地址 int length; // 当前图书数量 } SeqList; int InitList(SeqList *L) { L-elements (Book*)malloc(MAX_SIZE * sizeof(Book)); if(!L-elements) exit(OVERFLOW); L-length 0; return OK; }内存管理要点预分配固定大小的连续内存空间需要检查分配是否成功记得在程序结束时释放内存2.2 核心功能实现图书入库操作示例int InsertBook(SeqList *L, int position, Book book) { if (position 1 || position L-length 1) { return ERROR; // 非法位置 } if (L-length MAX_SIZE) { return OVERFLOW; // 存储空间已满 } // 移动元素腾出空间 for(int i L-length; i position; i--) { L-elements[i] L-elements[i-1]; } L-elements[position-1] book; L-length; return OK; }价格调整算法void AdjustPrices(SeqList *L) { float total 0; for(int i 0; i L-length; i) { total L-elements[i].price; } float avg total / L-length; for(int i 0; i L-length; i) { if(L-elements[i].price avg) { L-elements[i].price * 1.1; // 高于平均价涨10% } else { L-elements[i].price * 1.2; // 低于平均价涨20% } } }3. 链表实现方案当需要频繁插入删除时链表是更好的选择。我们采用带头结点的单链表实现3.1 链表结构定义typedef struct LNode { Book data; struct LNode *next; } LNode, *LinkList; int InitList(LinkList *L) { *L (LinkList)malloc(sizeof(LNode)); if(!*L) exit(OVERFLOW); (*L)-next NULL; return OK; }3.2 链表特色操作链表逆序存储实现void ReverseList(LinkList *L) { LNode *prev NULL; LNode *current (*L)-next; LNode *next NULL; while(current ! NULL) { next current-next; current-next prev; prev current; current next; } (*L)-next prev; }链表去重算法void RemoveDuplicates(LinkList *L) { LNode *current (*L)-next; while(current ! NULL) { LNode *runner current; while(runner-next ! NULL) { if(strcmp(runner-next-data.isbn, current-data.isbn) 0) { LNode *temp runner-next; runner-next runner-next-next; free(temp); } else { runner runner-next; } } current current-next; } }4. 性能优化实战技巧在实际开发中我们还需要考虑以下优化点4.1 混合存储策略结合顺序表和链表的优点主存储使用顺序表便于快速检索最近操作记录使用链表实现LRU缓存typedef struct { SeqList main_storage; // 主存储 LinkList recent_ops; // 最近操作缓存 int cache_size; // 缓存大小 } HybridStorage;4.2 索引优化为常用查询字段建立索引typedef struct { char isbn[20]; int position; // 在顺序表中的位置 } ISBN_Index; ISBN_Index *CreateISBNIndex(SeqList *L) { ISBN_Index *index (ISBN_Index*)malloc(L-length * sizeof(ISBN_Index)); for(int i0; iL-length; i) { strcpy(index[i].isbn, L-elements[i].isbn); index[i].position i; } // 按ISBN排序索引 qsort(index, L-length, sizeof(ISBN_Index), CompareISBN); return index; }4.3 文件持久化将数据保存到文件实现持久化void SaveToFile(SeqList *L, const char *filename) { FILE *fp fopen(filename, wb); if(fp NULL) return; fwrite((L-length), sizeof(int), 1, fp); fwrite(L-elements, sizeof(Book), L-length, fp); fclose(fp); } int LoadFromFile(SeqList *L, const char *filename) { FILE *fp fopen(filename, rb); if(fp NULL) return ERROR; fread((L-length), sizeof(int), 1, fp); L-elements (Book*)malloc(L-length * sizeof(Book)); fread(L-elements, sizeof(Book), L-length, fp); fclose(fp); return OK; }5. 完整系统实现将各个模块组合成完整系统int main() { SeqList bookList; InitList(bookList); // 加载初始数据 if(LoadFromFile(bookList, books.dat) ! OK) { printf(初始化图书数据...\n); // 添加示例图书 Book sampleBooks[5] { {9787302257646, 程序设计基础, 25.00}, {9787302164340, 程序设计基础(第2版), 20.00}, {9787302219972, 单片机技术及应用, 32.00}, {9787302203513, 单片机原理与应用技术, 26.00}, {7810827430, 工业计算机控制技术, 29.00} }; for(int i0; i5; i) { InsertBook(bookList, i1, sampleBooks[i]); } } // 主菜单界面 while(1) { printf(\n图书管理系统\n); printf(1. 添加新书\n); printf(2. 删除图书\n); printf(3. 查询图书\n); printf(4. 价格调整\n); printf(5. 保存退出\n); int choice; scanf(%d, choice); switch(choice) { case 1: AddBook(bookList); break; case 2: DeleteBook(bookList); break; case 3: SearchBook(bookList); break; case 4: AdjustPrices(bookList); break; case 5: SaveToFile(bookList, books.dat); free(bookList.elements); return 0; default: printf(无效选择\n); } } }实现这个系统的过程中最深的体会是数据结构的选择会极大影响系统性能。当图书数量超过5000本时顺序表的插入操作明显变慢这时就需要考虑改用链表或其他更高效的数据结构。