链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
简单地说,
链表是一种可以将多个数据依次连接起来的存储结构。
一个链表中每个结点应由两块组成,数据,指针。
形如:
typdef struct{
char name[10]; //姓名
int num; //数据信息
struct date *next; //指向下一个结点的指针
}student;
数据 即为我们想要存储的数据,可以是一个,也可以是多个,可以是int型,也可以是结构体,等等。
指针 一般位于每个结点的末尾,用来指向下一个结点,起到连接的作用。
一般当我们申请到第一块空间时,我们通常会定义一个指针*head 指向这个结点的起始部位,再定义一个指针 *next 指向下一结点的数据内容,这样就将两个结点连接在了一起。
以下是将两个结点a,s连接的代码:
student *a=(student*)malloc(sizeof(student)); //申请第一块空间
student *head=a; //创建头指针,将其指向第一个结点的头部
int c;
scanf("%d",&c); //读入第一个数据
a->num=c; //存入第一个结点中
studate *s=(student*)malloc(sizeof(student)); //创建新的结点
scanf("%d",&c); //读入第二个节点中的数据
s->num=c; //将数据存入第二个节点中
a->next=s; //将a中的指针*next 指向下一结点的数据
head=s; //将头指针移动到指向第二个节点的数据
b->next=NULL; //由于以两个节点为例,第二个结点的指针应指向NULL
假设有两个指针*p,*q 。*p 指向第一个结点的数据,*q 指向第一个结点的指针,此时若想添加节点,只需将第一个结点的指针指向新的结点的数据,第新的结点的指针指向第三个节点的数据就意味着已经连接成功。
但为了方便下一次添加,一般通过 p=p->next 将 *p 指向最后一个结点的数据, q=q->next;q=NULL将 *q 指向最后一结点的指针。
切记最后一个节点的指针需指向空值NULL。
studate *p,*q;
int x,y;
scanf("%d",&y);
p=head; //p指向第一个结点head
q=head->next; //q指向第一个结点head的next
while(q->num!=y&&q->next!=NULL){
//移动指针直到查询到或结束
q=q->next;
p=p->next;
}
/*此时q已指向所要添加结点位置的下一个结点,
p已指向所要添加结点位置的上一个结点*/
printf("have find");
scanf("%d",&x);
studate *s=(studate*)malloc(sizeof(studate));//新建结点
s->num=x; //将x存储在新结点的数据域中
s->next=q; //新结点的指针指向下一结点(即q)
p->next=s; //上一结点的指针(即p)指向新结点
假设有结点a、结点b、结点c
typdef struct{
int num; //数据信息
struct date *next; //指向下一个结点的指针
}a,b,c; //结点a,b,c
想要删除结点b,应将结点a的指针指向c的数据即可
a->next=c;
c->next=NULL;
通过移动指针p、q来确定指定结点位置
student *p,*q;
int y;
scanf("%d",&y);
p=head; //p指向第一个结点 head
q=head->next; //q指向第一个结点的 next
while(q->num!=y&&q->next!=NULL){
//移动指针直到查询到或结束
q=q->next;
p=p->next;
}
功能:输入自由多个数据,直到输入-1停止,并可以进行指定位置的添加,删除结点。
话不多说,上源码!
#include
#include
/*结构体*/
typedef struct date{
int num;
struct date *next;
}studate;
/*函数*/
void creat_(studate *b); //创建链表
void putout_(studate *b,studate *head); //遍历链表
void add_(studate *head); //添加结点
void del_(studate *head); //删除结点
int main(void)
{
studate *head=(studate*)malloc(sizeof(studate)),*b=head; //创建头指针
creat_(b);
putout_(b,head);
add_(head);
putout_(b,head);
del_(head);
putout_(b,head);
free(head);
return 0;
}
/**********************************************************
创建链表
**********************************************************/
void creat_(studate *b){
int c;
printf("输入数据");
scanf("%d",&c);
b->num=c;
do{
printf("输入数据");
scanf("%d",&c);
studate *s=(studate*)malloc(sizeof(studate)); //创建新的结点
s->num=c;
b->next=s;
b=s;
}while(c!=-1);
b->next=NULL;
}
/**********************************************************
添加结点
**********************************************************/
void add_(studate *head){
studate *p,*q;
int x,y;
printf("请输入插入数据的两个位置(数据)");
scanf("%d %d",&x,&y);
p=head;
q=head->next;
while(q->num!=y&&q->next!=NULL){
q=q->next;
p=p->next;
}
printf("have find");
scanf("%d",&x);
studate *s=(studate*)malloc(sizeof(studate));
s->num=x;
s->next=q;
p->next=s;
}
/**********************************************************
遍历链表
**********************************************************/
void putout_(studate *b,studate *head){
b=head;
printf("head->");
while(b->next){
printf("%d->",b->num);
b=b->next;
}
printf("NULL\n");
}
/**********************************************************
删除结点
**********************************************************/
void del_(studate *head){
studate *p,*q;
int x;
printf("请输入删除的数据");
scanf("%d",&x);
p=head;
q=head->next;
while(q->num!=x&&q->next!=NULL){
q=q->next;
p=p->next;
}
if(q->num!=x&&q->next==NULL)
printf("sorry");
else {
q=q->next;
(p->next)=q;
printf("ok, have delete");
}
}
!!!最后一定要free掉空间哦,这是个好习惯!!!
本文仅简单介绍了链表的使用
其实链表有很多优点,也有缺点:
1、空间上,顺序比链式节约空间。是因为链式结构每一个节点都有一个指针存储域;
2、存储操作上,顺序支持随机存取,方便操作;
3、插入和删除上,链式的要比顺序的方便
链表较顺序表来说稍微复杂点,但只要多加练习就一定可以流畅使用。
下一篇我将重点介绍人员管理系统的链表方法以及顺序表方法的制作, 以对比二者的优缺点。
以上就是今天分享的内容,谢谢。