很多人,一接触到数据结构就难懂,就说有难度,还有就说,链表有什么用?今天我就详细的说下,这个链表有什么用。
一、链表介绍
1、链表有地址不连续的结点序列,必须通过指针相互连接。
2、链表的分类:
(1)单向线性链表
每个节点中除了存储数据结构内容以外,还需要保存指向下一个节点的指针,叫做后指针。最后一个节点的后指针为NULL。其中第一个节点叫做头节点,指向头结点的指针叫做头指针。最后一个节点叫做尾节点。
(2)单向循环链表
与单向线性链表不同的是,链表尾节点的后指针指向头节点。首尾相接构成环状结构。
(3)双向线性链表
每个节点除了存放本身元素以外,还需要保存指向下一个节点的指针,叫做后指针,以及指向前一个节点的指针,叫做前指针。双向线性链表中头节点的前指针为空,以及尾节点后指针也是空指针。
(4)双向循环链表
与双向线性链表相比,头节点中的前指针指向尾节点,尾节点的后指针指向头节点,构成环状结构。
(5)其他
除了以上链表以外,还有很多链表,如数组链表、链表数组等等。
简单介绍完了,下面开始一一讲解下。
二、单向线性链表 (重点)
1、参看:C中链表
链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链表指向列表中的下一个节点,而最后一个节点则指向一个空值。如下:
一个单向链表的节点被分成两个部分。第一部分保存或者显示关于节点的信息,第二部分存储下一个节点的地址。单向链表只可向一个方向遍历。
链表最基本的结构是在每个节点保存数据和到下一个节点的地址,在最后一个节点保存一个特殊的结束标记,另外在一个固定的位置保存指向第一个节点的指针,有的时候也会同时存储指向最后一个节点的指针。一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。但是也可以提前把一个节点的位置另外保存起来,然后直接访问。当然如果只是访问数据就没有必要了,不如在链表上存储指向实际数据的指针。这样一般是为了访问链表中的下一个或者前一个(需要存储反向的指针,见下面的双向链表)节点。
相对于下面的双向链表,这种普通的,每个节点只有一个指针的链表也叫单向链表,或者单链表。通常用在每次只会按顺序遍历这个链表的时候(例如图的邻接表,通常都是按固定顺序访问的)。
举个例子:建立链表保存学生的信息,并且可以进行,插入、删除操作,并将学生的信息输出。
参看:链表实现学生信息管理
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node
{
int number;
char name[10];
char sex[5];
int classes;
int tel;
struct node *next;
};
typedef struct node NODE;
void scanning(NODE *head); /*申明浏览函数*/
NODE *insert(NODE *head); /*申明插入函数*/
void del(NODE *head); /*申明删除函数*/
void fix(NODE *head); /*申明修改函数*/
int main (void)
{
int choice;
int flag=1;
NODE *head;
head=(NODE *)malloc(sizeof(NODE));
head->next=NULL;
while(flag)
{
printf("请选择功能: 1—信息浏览 2—插入信息 3—删除信息 4-修改信息 0—退出程序 ");
scanf("%d",&choice);
switch(choice)
{
case 1:
scanning(head);break;
case 2:
head=insert(head);break;
case 3:
del(head);break;
case 4:
fix(head);break;
case 0:
flag=0; break;
}
}
printf(" ");
printf("谢谢使用! ");
return 0;
}
void scanning(NODE *head) /*定义浏览函数*/
{
NODE *t;
t=head;
t=t->next;
if(t==NULL)
{
printf(" ");
printf("无记录!请先输入学生信息: ");
printf(" ");
}
while(t!=NULL)
{
printf("学号:%d ",t->number);
printf("姓名:%s ",t->name);
printf("性别:%s ",t->sex);
printf("班级:%d ",t->classes);
printf("联系方式:%d ",t->tel);
printf(" ");
t=t->next;
}
}
NODE *insert(NODE *head) /*定义插入函数*/
{
NODE *t,*p;
int a,b,c;
char e[10],f[5];
t=(NODE *)malloc(sizeof(NODE));
p=head;
if(p->next==NULL) /*原本无元素*/
{
printf("请输入学号: ");
scanf("%d",&a);
printf("请输入姓名: ");
scanf("%s",e);
printf("请输入性别: ");
scanf("%s",f);
printf("请输入班级: ");
scanf("%d",&b);
printf("请输入号码: ");
scanf("%d",&c);
t->number=a;
strcpy(t->name,e);
strcpy(t->sex,f);
t->classes=b;
t->tel=c;
p->next=t;
t->next=NULL;
}
else /*原本有元素*/
{
printf("请输入学号: ");
scanf("%d",&a);
printf("请输入姓名: ");
scanf("%s",e);
printf("请输入性别: ");
scanf("%s",f);
printf("请输入班级: ");
scanf("%d",&b);
printf("请输入号码: ");
scanf("%d",&c);
t->number=a;
strcpy(t->name,e);
strcpy(t->sex,f);
t->classes=b;
t->tel=c;
t->next=p->next;
p->next=t;
}
return head;
}
void del(NODE *head) /*定义删除函数*/
{
int m;
NODE *s,*t;
s=head;
t=head->next;
printf("请输入你要删除的同学的学号: ");
scanf("%d",&m);
while(t!=NULL)
{
if((t->number)!=m)
{
s=s->next;
t=t->next;
}
else
{
s->next=t->next;
free(t);
break;
}
}
}
void fix(NODE *head) /*定义修改函数*/
{
NODE *p,*t;
int m,q,z=1;
p=head;
t=(NODE *)malloc(sizeof(NODE));
printf("请输入你要修改的学生的学号: ");
scanf("%d",&m);
p=p->next;
while(p!=NULL)
{
if((p->number)==m)
{
while(z)
{
printf("你想要修改哪项数据? 1代表学号 2代表姓名 3代表性别 4代表班级 5代表联系方式 (注意:修改完毕请输入0) ");
scanf("%d",&q);
switch(q)
{
case 1:
printf("请输入修改后的学号! ");
scanf("%d",&t->number);
p->number=t->number;
break;
case 2:
printf("请输入修改后的姓名! ");
scanf("%s",t->name);
strcpy(p->name,t->name);
break;
case 3:
printf("请输入修改的性别! ");
scanf("%s",t->sex);
strcpy(p->sex,t->sex);
break;
case 4:
printf("请输入修改的班级! ");
scanf("%d",&t->classes);
p->classes=t->classes;
break;
case 5:
printf("请输入修改后的联系方式! ");
scanf("%d",&t->tel);
p->tel=t->tel;
break;
case 0:
z=0;
break;
}
}
}
p=p->next;
}
}