数据结构练习:运用单链表实现图书管理系统

  • 正文
    • 注意
    • 部分功能运行展示
    • 所包含头文件及结构体的定义
    • 自定义函数
    • 主函数
    • 完整代码
  • 结束语

正文

本程序使用带头节点的单链表存储结构实现,共有六个基本功能,完成对信息链表的增删改查。

注意

/*
1.对于结构体或自定义元素类型最好传地址,传值的话会涉及到内存拷贝。
2.函数memset()与memcpy()是c/c++中的内存初始化和内存拷贝函数,数据元素是结构体变量时也适用,初始化或者赋值时不需要对结构体内数据元素进行一个一个的赋值。
函数解释:
(1).void *memset(void *s, int ch, size_t n);
将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
(2).void *memcpy(void *destin, void *source, unsigned n);
从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。
3.system(“color f1”);//调整背景颜色与字符颜色
头文件是 #include<windows.h>
**/

部分功能运行展示

1.插入信息功能:

2.清除信息功能

3.退出系统功能

所包含头文件及结构体的定义

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>int seat;//定义一个全局变量,保存结点的位置序号 //定义结构体数据元素。
typedef struct{int num; //定义图书编号。 char name[31]; //定义图书名字。
}ElemType;//定义链表节点结构体。
typedef struct LNode{ ElemType data; // 加入一个自定义数据元素 用来存放数据。 struct LNode *next; //定义一个节点类型指针,后续让它指向该节点的下一结点。
}LNode,*LinkList;

自定义函数

// 初始化链表LL,返回值:成功-头结点的地址,失败-NULL。
LNode *InitList(); // 销毁链表LL。
//注意链表的销毁操作最后需要将链表指针也置空。
void DestroyList(LinkList LL); // 清空链表。
//清空链表需要保留头指针。
void ClearList(LinkList LL);//打印链表。
void PrintList(LinkList LL);//在链表中第seat个位置插入元素,返回值:成功-1,失败-0。
int InsertList(LinkList LL,unsigned int seat,ElemType *ee); //在链表第一个位置添加元素,返回值:成功-1,失败-0。
int PushFront(LinkList LL,ElemType *ee);//在链表最后一个位置添加元素。
void PushBack(LinkList LL,ElemType *ee);//在链表中第seat个位置删除元素,返回值:成功-1,失败-0。
int DeleteList(LinkList LL,unsigned int seat,ElemType *ee);// 通过元素信息删除表中节点
void DeleteNode(LinkList LL,ElemType *ee);  //根据编号寻找结点位置,返回值:成功-结点位置,失败-0。
int LocateList(LinkList LL,int ii);

主函数

int main()
{LinkList LL;//声明一个链表。 LL=NULL;ElemType ee;//声明一个自定义元素。 LL=InitList();//对链表进行初始化。 int choose,ii; //choose保存主要功能选择号码,ii用于保存次要功能选择号码。 char name_tmp[31];system("color f1");//调整背景颜色与字符颜色 //条件始终为真的循环。 while(1){printf("\n");printf("---------------------------------\n");printf("*    欢迎使用图书管理系统    *\n");printf("*    1.查看所有图书信息      *\n");printf("*    2.添加图书信息          *\n");printf("*    3.删除图书信息          *\n");printf("*    4.修改图书信息          *\n");printf("*    5.清空图书信息          *\n");printf("*    6.退出系统              *\n");printf("---------------------------------\n");printf("\n");printf("请选择功能选项(1-6):\n");scanf("%d",&choose);switch(choose){case 1:PrintList(LL); //打印链表。 break;case 2:printf("请插入图书信息(输入为0时停止插入):\n");printf("请输入要插入的图书编号:\n");scanf("%d",&ee.num);printf("请输入要插入的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);while(ee.num!=0){printf("请选择要添加图书信息的位置(1-添加在第一个,2-添加在末尾,3-自定义位置):\n");scanf("%d",&ii);if(ii == 1) PushFront(LL,&ee);//在链表第一个位置添加元素 。 if(ii == 2) PushBack(LL,&ee);//在链表最后一个位置添加元素。 if(ii == 3){printf("请输入插入位置:\n");scanf("%d",&seat);InsertList(LL,seat,&ee);//在链表中第ii个位置插入元素,返回值:成功-1,失败-0。 }printf("请插入图书信息(输入为0时停止插入):\n");printf("请输入要插入的图书编号:\n");scanf("%d",&ee.num);printf("请输入要插入的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);}PrintList(LL);break; case 3:printf("请选择想要进行的图书信息删除操作(1-通过编号删除,2-自定义位置):\n");scanf("%d",&ii);if(ii == 1) {memset(&ee,0,sizeof(ElemType));//通过该函数将ee初始化。printf("请输入要删除的图书编号:\n");scanf("%d",&ee.num);DeleteNode(LL,&ee); // 通过元素信息删除表中节点 }if(ii == 2){printf("请输入删除位置:\n");scanf("%d",&seat);DeleteList(LL,seat,&ee);//在链表中第ii个位置删除元素,返回值:成功-1,失败-0。 }PrintList(LL);break; case 4:printf("请输入要修改图书的编号:\n");scanf("%d",&ii);seat=LocateList(LL,ii);//根据编号寻找结点位置,返回值:成功-结点位置,失败-0。if(seat!=0){printf("请输入更新后的图书编号:\n");scanf("%d",&ee.num);printf("请输入更新后的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);ReplaceList(LL,seat,&ee);//在链表中第ii个位置替换元素。PrintList(LL);}break;case 5:ClearList(LL);//清空链表。 break;case 6:DestroyList(LL); LL=NULL;//销毁链表并将指针置空。 printf("成功退出!欢迎再次使用图书管理系统!\n");return 0;default:printf("选择的功能选项不存在!功能选项范围值在1-6之间!\n");break;}}
}

完整代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>int seat;//定义一个全局变量,保存结点的位置序号 //定义结构体数据元素。
typedef struct{int num; //定义图书编号。 char name[31]; //定义图书名字。
}ElemType;//定义链表节点结构体。
typedef struct LNode{ ElemType data; // 加入一个自定义数据元素 用来存放数据。 struct LNode *next; //定义一个节点类型指针,后续让它指向该节点的下一结点。
}LNode,*LinkList;// 初始化链表LL,返回值:成功-头结点的地址,失败-NULL。
LNode *InitList(); // 销毁链表LL。
//注意链表的销毁操作最后需要将链表指针也置空。
void DestroyList(LinkList LL); // 清空链表。
//清空链表需要保留头指针。
void ClearList(LinkList LL);//打印链表。
void PrintList(LinkList LL);//在链表中第seat个位置插入元素,返回值:成功-1,失败-0。
int InsertList(LinkList LL,unsigned int seat,ElemType *ee); //在链表第一个位置添加元素,返回值:成功-1,失败-0。
int PushFront(LinkList LL,ElemType *ee);//在链表最后一个位置添加元素。
void PushBack(LinkList LL,ElemType *ee);//在链表中第seat个位置删除元素,返回值:成功-1,失败-0。
int DeleteList(LinkList LL,unsigned int seat,ElemType *ee);// 通过元素信息删除表中节点
void DeleteNode(LinkList LL,ElemType *ee);  //根据编号寻找结点位置,返回值:成功-结点位置,失败-0。
int LocateList(LinkList LL,int ii);//在链表中第seat个位置替换元素。
void ReplaceList(LinkList LL,unsigned int seat,ElemType *ee);int main()
{LinkList LL;//声明一个链表。 LL=NULL;ElemType ee;//声明一个自定义元素。 LL=InitList();//对链表进行初始化。 int choose,ii; //choose保存主要功能选择号码,ii用于保存次要功能选择号码。 char name_tmp[31];system("color f1");//调整背景颜色与字符颜色 //条件始终为真的循环。 while(1){printf("\n");printf("---------------------------------\n");printf("*    欢迎使用图书管理系统    *\n");printf("*    1.查看所有图书信息      *\n");printf("*    2.添加图书信息          *\n");printf("*    3.删除图书信息          *\n");printf("*    4.修改图书信息          *\n");printf("*    5.清空图书信息          *\n");printf("*    6.退出系统              *\n");printf("---------------------------------\n");printf("\n");printf("请选择功能选项(1-6):\n");scanf("%d",&choose);switch(choose){case 1:PrintList(LL); //打印链表。 break;case 2:printf("请插入图书信息(输入为0时停止插入):\n");printf("请输入要插入的图书编号:\n");scanf("%d",&ee.num);printf("请输入要插入的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);while(ee.num!=0){printf("请选择要添加图书信息的位置(1-添加在第一个,2-添加在末尾,3-自定义位置):\n");scanf("%d",&ii);if(ii == 1) PushFront(LL,&ee);//在链表第一个位置添加元素 。 if(ii == 2) PushBack(LL,&ee);//在链表最后一个位置添加元素。 if(ii == 3){printf("请输入插入位置:\n");scanf("%d",&seat);InsertList(LL,seat,&ee);//在链表中第ii个位置插入元素,返回值:成功-1,失败-0。 }printf("请插入图书信息(输入为0时停止插入):\n");printf("请输入要插入的图书编号:\n");scanf("%d",&ee.num);printf("请输入要插入的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);}PrintList(LL);break; case 3:printf("请选择想要进行的图书信息删除操作(1-通过编号删除,2-自定义位置):\n");scanf("%d",&ii);if(ii == 1) {memset(&ee,0,sizeof(ElemType));//通过该函数将ee初始化。printf("请输入要删除的图书编号:\n");scanf("%d",&ee.num);DeleteNode(LL,&ee); // 通过元素信息删除表中节点 }if(ii == 2){printf("请输入删除位置:\n");scanf("%d",&seat);DeleteList(LL,seat,&ee);//在链表中第ii个位置删除元素,返回值:成功-1,失败-0。 }PrintList(LL);break; case 4:printf("请输入要修改图书的编号:\n");scanf("%d",&ii);seat=LocateList(LL,ii);//根据编号寻找结点位置,返回值:成功-结点位置,失败-0。if(seat!=0){printf("请输入更新后的图书编号:\n");scanf("%d",&ee.num);printf("请输入更新后的图书名:\n");scanf("%s",&name_tmp); strcpy(ee.name,name_tmp);ReplaceList(LL,seat,&ee);//在链表中第ii个位置替换元素。PrintList(LL);}break;case 5:ClearList(LL);//清空链表。 break;case 6:DestroyList(LL); LL=NULL;//销毁链表并将指针置空。 printf("成功退出!欢迎再次使用图书管理系统!\n");return 0;default:printf("选择的功能选项不存在!功能选项范围值在1-6之间!\n");break;}}
}// 初始化链表LL,返回值:成功-头结点的地址,失败-NULL。
LNode *InitList()
{LNode *head=(LNode*)malloc(sizeof(LNode)); //定义一个头结点。 if(head == NULL) return NULL; //内存分配失败。head->next=NULL; // 头结点的下一结点置空。return head; // 返回头结点。
}// 销毁链表LL。
//注意链表的销毁操作最后需要将链表指针也置空。
void DestroyList(LinkList LL)
{//本函数的链表指针置空操作需要在函数外部完成。 LNode *pp;while(LL!=NULL){pp=LL->next; //pp指针保存下一结点的信息 free(LL); //依次释放节点内存 LL=pp; //LL指针指向下移一结点 }}// 清空链表。
//清空链表需要保留头指针。
void ClearList(LinkList LL)
{if(LL == NULL) { printf("图书管理信息表不存在!\n"); return; }//检查是否传入空指针。LNode *tmp1,*tmp2;tmp1=LL->next;//从头结点的下一结点开始遍历。 while(tmp1!=NULL){tmp2=tmp1->next; //tmp2指针保存下一结点的信息。 free(tmp1); //依次释放节点内存。 tmp1=tmp2; //tmp1指针指向下移一结点。 }LL->next=NULL; //将指向头结点下一结点的指针置空,防止出现野指针。 printf("所有信息已经清空!\n");
}//打印链表。
void PrintList(LinkList LL)
{if(LL == NULL) { printf("图书管理信息表不存在!\n"); return; }//检查是否传入空指针。if(LL->next == NULL) { printf("图书管理信息表为空!\n"); return; }LNode *tmp=LL->next; //从头结点的下一个结点开始打印。 seat=1; //从第一个位置开始 。 printf("---------------------------------\n");printf("序号\t编号\t书名\n");while(tmp!=NULL){printf("%d\t%d\t%s\n",seat,tmp->data.num,tmp->data.name); //逐行打印信息。 seat++; //序号加1。 tmp=tmp->next; //指针指向下一结点 。 } printf("---------------------------------\n");
}//在链表中第seat个位置插入元素,返回值:成功-1,失败-0。
int InsertList(LinkList LL,unsigned int seat,ElemType *ee)
{if( (LL == NULL) && (ee == NULL) ) { printf("图书管理信息表不存在或者书籍信息未建立成功!\n"); return 0; } //检查是否传入空指针。if(seat<1) { printf("插入位置不合法!输入位置序号应大于0!\n"); return 0; }LNode *pp=LL;int ii=0; //需要找到要插入位置的上一个结点。 while( (pp!=NULL) && (ii<seat-1) ) {pp=pp->next;ii++;}LNode *tmp=(LNode*)malloc(sizeof(LNode)); //分配一个结点用于数据元素的插入。 if(tmp == NULL)  { printf("内存不足!无法插入图书信息\n"); return 0; } //内存不足,分配失败。 //结点插入操作 。 tmp->next=pp->next;pp->next=tmp;//插入结点数据。 memcpy(&tmp->data,ee,sizeof(ElemType));printf("图书信息插入成功!\n");return 1;
}//在链表第一个位置添加元素,返回值:成功-1,失败-0。
int PushFront(LinkList LL,ElemType *ee)
{return InsertList(LL,1,ee); //可以直接调用插入函数,插入位置为1。
}//在链表最后一个位置添加元素。
void PushBack(LinkList LL,ElemType *ee)
{if( (LL == NULL) && (ee == NULL) ) { printf("图书管理信息表不存在或者书籍信息未建立成功!\n"); return; } //检查是否传入空指针。LNode *pp=LL;while(pp->next!=NULL) pp=pp->next; //指针依次往后继结点移动,直到找到最后一个结点。 LNode *tmp=(LNode*)malloc(sizeof(LNode)); //分配一个结点用于数据元素的插入。 if(tmp == NULL)  { printf("内存不足!无法插入图书信息\n"); return; } //内存不足,分配失败。 //结点插入操作 。 tmp->next=NULL; // 所插入结点为最后一个结点,后继指针指向空。 pp->next=tmp;//插入结点数据。 memcpy(&tmp->data,ee,sizeof(ElemType));printf("图书信息插入成功!\n");
}//在链表中第seat个位置删除元素,返回值:成功-1,失败-0。
int DeleteList(LinkList LL,unsigned int seat,ElemType *ee)
{if( (LL == NULL) && (ee == NULL) ) { printf("图书管理信息表不存在或图书信息输入未成功!\n"); return 0; } //检查是否传入空指针。if(seat<1) { printf("删除位置不合法!输入位置序号应大于0!\n"); return 0; }LNode *pp=LL; //定义一个指针指向头结点。 int ii=0; //需要找到要删除位置的上一个结点。 while( (pp!=NULL) && (ii<seat-1) ) {pp=pp->next;ii++;}//因为是删除所找到结点的下一结点,如果下一结点不存在则返回失败。 if(pp->next == NULL) { printf("删除位置不合法!应小于图书信息表长度!\n"); return 0; }LNode *tmp=pp->next; //定义一个指针使其指向需要删除的结点。 pp->next=tmp->next; // pp的后继指针指向所要删除结点的后一个结点。free(tmp); //释放所要删除的结点内存。printf("图书信息删除成功!\n");return 1;
}// 通过元素信息删除表中节点
void DeleteNode(LinkList LL,ElemType *ee)
{if( (LL == NULL) && (ee == NULL) ) { printf("图书管理信息表不存在或图书信息输入未成功!\n"); return; } //检查是否传入空指针。seat=LocateList(LL,ee->num);DeleteList(LL,seat,ee); }//根据编号寻找结点位置,返回值:成功-结点位置,失败-0。
int LocateList(LinkList LL,int ii)
{if(LL == NULL) { printf("图书管理信息表不存在!\n"); return 0; }//检查是否传入空指针。LNode *pp=LL->next; //从第一个结点开始查找。seat=1; //序号从1开始。 while(pp!=NULL){if(pp->data.num == ii) return seat;pp=pp->next;seat++;}printf("未找到图书信息!\n");return 0;
}//在链表中第seat个位置替换元素。
void ReplaceList(LinkList LL,unsigned int seat,ElemType *ee)
{if( (LL == NULL) && (ee == NULL) ) { printf("图书管理信息表不存在或图书信息输入未成功!\n"); return; } //检查是否传入空指针。LNode *tmp=LL->next;int kk=1;//找到替换位置的结点。 while( (tmp!=NULL) && (kk<seat) ){tmp=tmp->next;kk++;}if(tmp == NULL) { printf("更新位置不合法!应小于图书信息表长度!\n"); return; }memset(&tmp->data,0,sizeof(ElemType));//清空原结点内容。memcpy(&tmp->data,ee,sizeof(ElemType));//添加修改的内容。printf("图书信息更新成功!\n");
}

结束语

因为本程序使用到的是基本的链表操作,仅实现了链表的增删改查操作,所以部分功能还可以进一步完善,各位uu如果在代码中发现了有不正确的地方,还请指正,谢谢!

数据结构练习:运用单链表实现图书管理系统(c/c++)(内含带头结点的单链表的基本操作)相关推荐

  1. java带头节点的单链表_自己实现集合框架(五):带头结点单链表的实现

    这是系列文章,每篇文章末尾均附有源代码地址.目的是通过模拟集合框架的简单实现,从而对常用的数据结构和java集合有个大概的了解.当然实现没有java集合的实现那么复杂,功能也没有那么强大,但是可以通过 ...

  2. 单链表实现图书管理系统(销售系统,马踏棋盘)

    这篇文章主要介绍三个数据结构的课程设计,一共设涉及到三个课程设计,分别是图书管理系统,销售管理系统,马踏棋盘. 声明:图书管理系统为作者所写,其他两个来源于网络,如有侵权,请通知作者删除. 以下代码经 ...

  3. 【C语言】数据结构C语言版 实验3 带头结点的单链表

    slnklist.h #include <stdio.h> #include <stdlib.h> /************************************* ...

  4. 【C语言】数据结构C语言版 实验2 不带头结点的单链表

    运行环境:Dev-C++ vs2013可能不能运行 首先新建一个头文件slnklist.h #include <stdio.h> #include <stdlib.h> /** ...

  5. 数据结构:假设有一个带头结点的单链表L,每个结点值由单个数字、小写字母和大写字母构成。设计一个算法将其拆分成3个带头结点的单链表L1、L2和L3,L1包含L中的所有数字结点,L2包含L中的所有小写字母

    假设有一个带头结点的单链表L,每个结点值由单个数字.小写字母和大写字母构成.设计一个算法将其拆分成3个带头结点的单链表L1.L2和L3,L1包含L中的所有数字结点,L2包含L中的所有小写字母结点,L3 ...

  6. 不带头结点的单链表c语言,数据结构:C语言实现----不带头结点单链表总结

    不带头结点的单链表结构体声明 typedef struct Node { int data; struct Node *next; }Node, *LinkList; (1)初始化 void Init ...

  7. 算法与数据结构之带头结点的单链表

    单链表优缺点 链表是非随机存取的存储结构,和顺序表相比,链表存储结构在实现插入.删除的操作时,不需要移动大量数据元素(但不容易实现随机存取线性表的第 i 个数据元素的操作).所以,链表适用于经常需要进 ...

  8. 数据结构--带头结点的单链表

    单链表分为:带头结点和不带头结点,不带头结点的单链表需要用到二级指针,容易出错. 1.结构体设计 typedef int ELEM_TYPE; //有效数据节点结构体设计(头结点借用) typedef ...

  9. 数据结构c/c++ 头插法尾插法建立带头结点的单链表,以数组创建带头结点的单链表和不带头结点的单链表,输出打印单链表

    // // Created by 焦娇 on 2021/9/17. //#ifndef CHAPTER2_LINELINK_LLK_H #define CHAPTER2_LINELINK_LLK_H# ...

最新文章

  1. Systemd:再一次的,回归第一进程
  2. Weex Workshop 挑战赛,等你来战!
  3. 百题大冲关系列课程更新啦!这次是 Golang
  4. ble mac地址 协议_BLE获取iphone mac地址的方法--【sky原创】
  5. 十一届蓝桥杯国赛 玩具蛇-dfs
  6. Invalid connection string format, a valid format is: host:port:sid
  7. 深入学习linux socket编程之select
  8. 6 rethad 自定义硬盘_图文详解zabbix配置自定义监控项过程
  9. gifcam使用缩小内存_Fedora 上的桌面环境内存占用测试 | Linux 中国
  10. Verilog实现2分频实例
  11. 苹果2021年WWDC大会可能继续采用线上方式举办
  12. mysql 运行 compile_install mysql by compile(通过编译安装mysql)
  13. J2EE中使用MediaInfo库获取视频信息
  14. 适配器模式 - 上厕所案例
  15. idea中热部署插件JRebel的激活
  16. 取消Word自动首字母大写步骤
  17. 11尺寸长宽 iphone_2019新发布iPhone 11、iPhone 11 Pro、iPhone 11 Pro Max尺寸规格对比
  18. JetBrain代码补全
  19. 筑梦数字时代,城链科技战略峰会西安站顺利落幕
  20. Qt Opengl 给两个立方体设置两中不同颜色

热门文章

  1. CentOS宝塔搭建(超详细)
  2. 一个很有意思的flash游戏,蚂蚁蛋糕保卫战(antbuster)
  3. mysql数据库中index什么意思_MySQL Index详解
  4. 华为linux系统信息,Linux系统信息相关、其他命令(五)
  5. 华为顶级网络工程师分享出这份TCP/IP网络编程笔记,已封神
  6. Linux 在线时间校准
  7. 调试器工作原理(1):基础篇
  8. 如何升级python的包_Python的包怎么升级
  9. [NOIP2014 普及组] 珠心算测验
  10. Facebook广告怎么投放?脸书广告的展现形式是怎么样的?