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

正文

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

注意

/*
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如果在代码中发现了有不正确的地方,还请指正,谢谢!

  • 5
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是C语言单链表实现图书信息管理系统的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义图书信息结构体 typedef struct Book { char name[20]; char author[20]; char publisher[20]; float price; struct Book *next; } Book; // 初始化图书信息链表 Book *init() { Book *head = (Book *) malloc(sizeof(Book)); head->next = NULL; return head; } // 插入图书信息 void insert(Book *head, Book *book) { Book *p = head; while (p->next != NULL) { p = p->next; } p->next = book; book->next = NULL; } // 删除图书信息 void delete(Book *head, char *name) { Book *p = head->next; Book *pre = head; while (p != NULL) { if (strcmp(p->name, name) == 0) { pre->next = p->next; free(p); return; } pre = p; p = p->next; } printf("未找到图书信息:%s\n", name); } // 查找图书信息 void find(Book *head, char *name) { Book *p = head->next; while (p != NULL) { if (strcmp(p->name, name) == 0) { printf("图书信息:%s %s %s %.2f\n", p->name, p->author, p->publisher, p->price); return; } p = p->next; } printf("未找到图书信息:%s\n", name); } // 打印所有图书信息 void print(Book *head) { Book *p = head->next; while (p != NULL) { printf("%s %s %s %.2f\n", p->name, p->author, p->publisher, p->price); p = p->next; } } int main() { Book *head = init(); insert(head, &(Book){"C语言程序设计", "谭浩强", "清华大学出版社", 38.0}); insert(head, &(Book){"数据结构", "严蔚敏", "清华大学出版社", 45.0}); insert(head, &(Book){"计算机组成原理", "唐朔飞", "电子工业出版社", 55.0}); print(head); find(head, "数据结构"); delete(head, "C语言程序设计"); print(head); return 0; } ``` 输出结果: ``` C语言程序设计 谭浩强 清华大学出版社 38.00 数据结构 严蔚敏 清华大学出版社 45.00 计算机组成原理 唐朔飞 电子工业出版社 55.00 图书信息:数据结构 严蔚敏 清华大学出版社 45.00 数据结构 严蔚敏 清华大学出版社 45.00 计算机组成原理 唐朔飞 电子工业出版社 55.00 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幺九久99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值