----基于对数据结构(C语言版)中单链表基本操作的实现与演示,本篇文章以图书管理系统做演示
一. 单链表的初始化(尾插法)
尾插法算法:1.申请一个指针*p始终让它指向最后一个结点。
2.生成一个新的结点*book,并给它的数据域赋值。
3.将新结点*book插入尾结点*p的next域。
4.将*p指向新的尾结点*book。
Getbook函数用于给新结点赋值在Createlibrary函数中被调用。
void Getbook(Library *book)//给新结点赋值
{
printf("请输入序号 书名 价格\n");
scanf("%d %s %f",&book->isbn,book->name,&book->money);
}
void Createlibrary(Library **head)//传入head头指针,因为需要改变指针指向的地址所以这里的形参传入二级指针
{
//构造一个单链表
Library *p = *head;//尾插法 申请一个变量记录最后一个节点的位置
int isbn;//图书的序号
printf("isbn = -1 退出停止录入\n");//isbn等于-1时停止录入数据,用isbn作为循环的判断条件
scanf("%d",&isbn);
while(isbn!=-1)
{
Library *book = (Library*)malloc(sizeof(Library));//创造新的结点申请空间
if(book == NULL)
{
printf("内存分配失败");
exit(1);
}
Getbook(book);//录入新结点的内容
p->next = book;
book->next = NULL;
p = book;//用指针p记录最后一个结点的位置
printf("是否需要继续输入(1/-1):");
scanf("%d",&isbn);
}
}
二.单链表的插入
插入的算法:1.申请一个指针*p用于遍历单链表。
2.找到比要插入数据的序号的前一个结点,将它的*next域赋值给新结点的*next域。
3.将比isbn大的结点的序号加一。
void Insertbook(Library **head,int isbn)//isbn要插入数据的序号,所有数据序号从1开始
{
Library *p,*L;//*p用于遍历
p = *head;
int i=1;
for(;i<isbn&&p;i++)
{
p = p->next;
}
if(p) {printf("插入位置不合法\n"); return ;}//未找到合法的插入位置
Library *book = (Library*)malloc(sizeof(Library));//为新结点申请空间
Getbook(book);
book->next = p->next;//将新结点插入到尾结点之后,变成新的尾结点
p->next = book;
L = book->next;
if(L->isbn==isbn)
{
while(L)
{
L->isbn++;//将比isbn大的结点序号加一
L = L->next;
}
}
}
三.单链表的删除
删除算法:1.申请三个指针*p用于记录删除数据的直接前驱,*L用于记录删除的数据,*tmp用于释放空间
2.将问题简单化,分为删除第一个结点,和大于1结点的情况
void Deletebook(Library **head,int isbn)
{
Library *p,*L,*tmp;//删除数据的前驱L,删掉的数据p,释放内存tmp
p = (*head)->next;
L = *head;//注意必须将指向指针的指针复制给临时变量才能修改指针的指向,完成删除或者插入单链表的操作
while(p)//当p不为空时循环执行
{
if(isbn==1)
{
(*head)->next = p->next;
break;
}
if(p->isbn==isbn)
{
tmp = p;
L->next = p->next;
free(p);
tmp = tmp->next;
while(tmp)
{
tmp->isbn--;
tmp = tmp->next;
}
break;
}
p = p->next;//指向下一个结点
L = L->next;//指向下一个结点
}
}
四.单链表的查找
查找的算法:1.用指针*p指向头结点
2.从首元结点开始依次顺着链表域next向下查找,只要指针p不为空,且指针p的数据域不等于isbn,则p指向下一个结点。
3.若查找成功输出p此时的数据域,若查找失败,打印查找失败。
void Findbook(Library *head,int isbn)//*head头指针,isbn要查找的序号
{
Library *p = head->next;//*p用于遍历
int flag = 0;//用于记录是否查找成功
while(p)//当p不为空时循环执行
{
if(p->isbn==isbn)
{
printf("序号:%d 书名:%s\n",p->isbn,p->name);
printf("价格:%.2f\n",p->money);
flag = 1;
}
p = p->next;//指向下一个结点
}
if(flag==0)
printf("未找到该元素");
}
五.单链表数据域的修改
修改的算法.1:用指针p指向头结点
2:从首元结点开始依次向下遍历单链表,只要p不为空,或者p的数据域不等于isbn,则指向下一个结点。
void Modifybook(Library *head,int isbn)//head为头指针,isbn为修改结点的序号
{
Library *p = head->next;//将*p指向头结点
int num=0;//switch语句的判断条件
for(int i = 1;p;i++)
{
if(p->isbn==isbn)
{
printf("需要修改 1-序号-2书名-3价格(1/2/3):");
scanf("%d",&num);//用于判断要修改的数据
switch(num){
case 1:printf("请输入新的序号:");
scanf("%d",&p->isbn);
break;
case 2:printf("请输入新的书名:");
scanf("%s",&p->name);
break;
case 3:printf("请输入新的价格:");
scanf("%f",&p->money);
break;
default : break;
}
}
p = p->next;//指向下一个结点
}
}
六.单链表空间的释放。
释放空间的算法:1.将p指向头指针
2.从首元结点开始依次利用free函数释放空间,直至p为空。
void FreeLibrary(Library *head) {
Library *p = head;//用于遍历单链表
while (p) {
Library *temp = p;
p = p->next;
free(temp);
}
}
七.单链表的计数
算法:1.将p指向头结点
2.从首元结点开始依次遍历单链表,每次循环只要p不为空,num加一记录结点数量
3.最后返回num。
int Countbook(Library *head)
{
int num = 0;//返回计数结果的变量
Library *p = head->next;
while(p)
{
num++;
p = p->next;
}
return num;
}
八.图书管理系统的代码实现
#include <stdio.h>
#include <stdlib.h>
//功能:创建 查找 插入 删除 修改 计数
typedef struct Library{
int isbn;//序号
char name[20];
float money;
Library *next;
};
void Createlibrary(Library **head);//创建单链表
void Getbook(Library *book);//书籍信息输入
void Printfbook(Library *book);//打印书籍
void Insertbook(Library **book,int isbn);//插入书籍
void FreeLibrary(Library *head);//释放内存
void Deletebook(Library **head,int isbn);//删除书籍
void Modifybook(Library *head,int isbn);//修改书籍
void Findbook(Library *head,int isbn);//查找书籍
int Countbook(Library *head);//计数
void Getbook(Library *book)
{
printf("请输入序号 书名 价格\n");
scanf("%d %s %f",&book->isbn,book->name,&book->money);
}
void Createlibrary(Library **head)//head 头节点
{
Library *p = *head;//尾插法 申请一个变量记录最后一个节点的位置
int isbn;
printf("isbn = -1 退出停止录入\n");
scanf("%d",&isbn);
while(isbn!=-1)
{
Library *book = (Library*)malloc(sizeof(Library));//创造新的节点申请空间
if(book == NULL)
{
printf("内存分配失败");
exit(1);
}
Getbook(book);
p->next = book;
book->next = NULL;
p = book;
printf("是否需要继续输入(1/-1):");
scanf("%d",&isbn);
}
}
void Printfbook(Library *head)
{
Library *L;//获取头节点的位置
L = head->next;
while(L)
{
printf("序号:%d 书名:%s\n",L->isbn,L->name);
printf("价格:%.2f\n",L->money);
putchar('\n');
L = L->next;
}
}
void Insertbook(Library **head,int isbn)//isbn要插入数据的序号,所有数据序号从1开始
{
Library *p,*L;//p用于遍历
p = *head;
int i=1;
for(;i<isbn&&p;i++)
{
p = p->next;
}
if(p) {printf("插入位置不合法\n"); return ;}
Library *book = (Library*)malloc(sizeof(Library));
Getbook(book);
book->next = p->next;
p->next = book;
L = book->next;
if(L->isbn==isbn)
{
while(L)
{
L->isbn++;
L = L->next;
}
}
}
void FreeLibrary(Library *head) {
Library *p = head;
while (p) {
Library *temp = p;
p = p->next;
free(temp);
}
}
void Deletebook(Library **head,int isbn)
{
Library *p,*L,*tmp;//删掉数据的前驱L,删掉的数据p,释放内存tmp
p = (*head)->next;
L = *head;//注意必须将指向指针的指针复制给临时变量才能修改指针的指向,完成删除或者插入单链表的操作
while(p)
{
if(isbn==1)
{
(*head)->next = p->next;
break;
}
if(p->isbn==isbn)
{
tmp = p;
L->next = p->next;
free(p);
tmp = tmp->next;
while(tmp)
{
tmp->isbn--;
tmp = tmp->next;
}
break;
}
p = p->next;
L = L->next;
}
}
void Modifybook(Library *head,int isbn)
{
Library *p = head->next;
int num=0;
for(int i = 1;p;i++)
{
if(p->isbn==isbn)
{
printf("需要修改 1-序号-2书名-3价格(1/2/3):");
scanf("%d",&num);
switch(num){
case 1:printf("请输入新的序号:");
scanf("%d",&p->isbn);
break;
case 2:printf("请输入新的书名:");
scanf("%s",&p->name);
break;
case 3:printf("请输入新的价格:");
scanf("%f",&p->money);
break;
default : break;
}
}
p = p->next;
}
}
void Findbook(Library *head,int isbn)
{
Library *p = head->next;
while(p)
{
if(p->isbn==isbn)
{
printf("序号:%d 书名:%s\n",p->isbn,p->name);
printf("价格:%.2f\n",p->money);
}
p = p->next;
}
}
int Countbook(Library *head)
{
int num=0;
Library *p = head->next;
while(p)
{
num++;
p = p->next;
}
return num;
}
int main(){
Library *head = (Library*)malloc(sizeof(Library));//有头结点需要申请空间,next需要存放数据
int flag = 0,isbn = 0,num = 0;//flag用于判断 isbn用于记录序号 num用来记录图书数量
head->next = NULL;
Createlibrary(&head);
printf("是否需要打印图书管理目录(1/-1):");
scanf("%d",&flag);
if(flag==1)
Printfbook(head);
printf("是否需要添加书籍(1/-1):");
scanf("%d",&flag);
if(flag==1)
{
printf("请输入书籍序号:");
scanf("%d",&isbn);
Insertbook(&head,isbn);
printf("请问是否需要重新打印(1/-1):");
scanf("%d",&flag);
if(flag==1)
Printfbook(head);
}
printf("是否需要删除某本书籍(1/-1):");
scanf("%d",&flag);
if(flag==1)
{
printf("请输入要删掉书籍的序号:");
scanf("%d",&isbn);
Deletebook(&head,isbn);
printf("是否需要打印目录(1/-1):");
scanf("%d",&flag);
if(flag==1) Printfbook(head);
}
printf("是否需要修改某一书籍(1/-1):");
scanf("%d",&flag);
if(flag==1)
{
printf("请输入修改书籍的序号:");
scanf("%d",&isbn);
Modifybook(head,isbn);
Findbook(head,isbn);
}
printf("----图书目录最终结果----\n");
Printfbook(head);
FreeLibrary(head);
return 0;
}
6838





