数据结构之单链表

从今天起开始数据结构系列的分享,今天分享的是单链表。
单链表大概是大概是每个数据结构初学者的必经之路,下面结合一个小小的工程
来深入学习单链表的使用–简易客户管理系统。
ps:如果还不清楚单链表是什么的小伙伴自行百度,在此不在赘述


#项目结构
增删改查,增、删、改这三个部分同时包含了将变动后的信息写入到文件中的操作


#代码编写

##项目基础代码
俗话说得好,“万丈高楼平地起”,先来编写项目的预定义代码部分,主要是头文件
包含、结构体定义、全局变量定义等

###头文件包含
#include<stdio.h> //C程序基础库
#include<stdlib.h> //包含函数exit()
#include<string.h> //包含函数strcmp()

###结构体定义


typedef struct item{
char name[20]; //保存客户姓名
char gender[20]; //保存客户性别
int age; //保存客户年龄
char tel[20]; //保存客户号码
} guest;

结构体定义不要多说了哈,这里typedef...guest是给结构体item起别名的意思,也就是
struct item在这个源文件里面等价于guest


typedef struct node {
guest data; //数据域
struct node next; //指针域
}
link;

这里是给指向结构体node的指针起别名

###全局变量定义
link T;//头指针
这个头指针T是整个系统的索引,六个模块共有一个,虽然有尽量少定义全局变量的原则,但这里
的全局变量T可以避免各个函数间复杂的参数传递问题,牺牲了空间,换取了运行时间的减少;
同时要注意我在后面对T的初始化代码


//初始化头指针
T=(link)malloc(sizeof(struct node));
T->next = NULL;

这里并没有给T安排数据域,T不是第一个存储客户信息的节点指针,T->next才是,初始化头指针
时还没有存储客户信息的结点加入,所以T->next=NULL;,这是一个编程者应该养成的好习惯;为
什么不给T安排数据域呢,这里主要考虑到后面的删除模块的编写,我们知道,删除一个结点,要先
找到这个结点的前驱指针p和后驱指针q,然后p->next = q->next;,如果给T安排数据域的话,
T的前驱是什么呢?就算不用上面我说的那套删除逻辑,用if...else...语句和另外一套逻辑
完成对T的删除,代码明显复杂些。

##项目核心代码

###一、加载文件
代码如下


void init() {
link p,s;
FILE *fp;
int i = 0;
s = p=(link)malloc(sizeof(struct node));
p->next = NULL;
if((fp=fopen(“1.txt”,”r”))==NULL) {
printf(“load error!”);
exit(1);
}
while(!feof(fp)) {
fscanf(fp,”%s\t%s\t%d\t%s\t\n”,p->data.name,p->data.gender,&p->data.age,p->data.tel);
i++;
if(i!=1) {
s->next = p;
s=p;
}
else{
T->next = p;
}
p=(link)malloc(sizeof(struct node));
p->next = NULL;
}
printf(“总人数i=====%d\n”,i);
if(fclose(fp)) {
printf(“Can’t close the file!\n”);
exit(1);
}
}

介绍下代码逻辑,新开辟内存空间,并使s、p指向它,打开文件,如果文件指针没有到文件尾,将
从文件读取到的一个客户信息赋给p的数据域,如果是读取第一个客户信息,将p指向的结点连在头
指针T后面,否则,将p连在s后面,因为这个时候s是p的前驱指针,连接成功后将p赋值给s,p又
指向一个新开辟的结点…
图示:

###二、增加客户
代码如下:


//添加
void create() {
link p,s;
FILE *fp;
int yn;
s=T;
while(s->next!=NULL) {
s=s->next;
}
do {
p=(link)malloc(sizeof(struct node));
printf(“请输入客户姓名:\n”);
scanf(“%s”,p->data.name);
printf(“请输入客户性别:\n”);
scanf(“%s”,p->data.gender);
printf(“请输入客户年龄:\n”);
scanf(“%d”,&p->data.age);
printf(“请输入客户联系方式:\n”);
scanf(“%s”,p->data.tel);
p->next=NULL;
s->next=p;
s=p;
if((fp=fopen(“1.txt”,”at”))==NULL) {
printf(“write error!\n”);
exit(0);
}
printf(“写了一次\n”);
fprintf(fp,”%s\t%s\t%d\t%s\n”,p->data.name,p->data.gender,p->data.age,p->data.tel);
if(fclose(fp)) {
printf(“can’t close the file!\n”);
exit(0);
}
printf(“添加成功!\n”);
printf(“是否继续添加请输入0或1:”);
scanf(“%d”,&yn);
} while(yn);
}

代码逻辑很简单,新增结点,并连在尾节点后面,同时写入文件,如果前一片代码看懂了,这不是什么
大问题…

###三、删除客户
代码如下


//删除
int del() {
link p,q;
FILE *fp;
char mod[25];
printf(“请输入需要删除的客户名称:\n”);
scanf(“%s”,mod);
p=T;
while(p->next!=NULL&&strcmp(p->next->data.name,mod)!=0)
p=p->next;
if(p->next==NULL) {
printf(“并无此人!\n”);
return 0;
}
q = p;
p = p->next;
q->next = p->next;
delete(p);
printf(“删除成功!\n”);
if((fp=fopen(“1.txt”,”wt”))==NULL) {
printf(“error!\n”);
exit(0);
}
p=T->next;
while(p!=NULL) {
printf(“%s”,p->data.name);
fprintf(fp,”%s\t%s\t%d\t%s\t\n”,p->data.name,p->data.gender,p->data.age,p->data.tel);
p = p->next;
}
if(fclose(fp)) {
printf(“can’t close the file!\n”);
exit(1);
}
}

模块三、四、五、六道理类似,不再赘述
附上代码地址:
github 欢迎star
如有疑问,欢迎进群讨论:

本文标题:数据结构之单链表

文章作者:月小水长

发布时间:2018年09月12日 - 14:09

最后更新:2019年04月10日 - 18:04

原始链接:https://inspurer.github.io/2018/09/12/数据结构之单链表/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

您的赞助将鼓励我继续创作!
-------------本文结束感谢阅读-------------