对于链表的理解,在网络上有各种各样的理解,本篇文章讲解一下我自己对于链表的理解,看了本篇文章,你肯定能对链表会有不一样的理解以及恍然大悟的感觉
操作链表从某种方面来看就是操作指针,相比于直接操作指针,其实就是多了一个数据域
typedef struct link{
int data; //数据域
struct link *next; //指针域
}
上述代码实际意思就是:在数据结构体里面定义本身数据结构体类型的指针;
至此就得知道链表的概念,链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。
以结构体为一个结点,其指针域指向下一个结点的地址,循环往复就生成了链表,链表的数据就存在每个结点的数据域中
代码思路:结点初始化-->链表的插入与删除-->数据遍历输出-->其他操作
本文举个例子是以学生信息单链表存储为讲解
1.首先得先定义一个学生信息结构体,确定你需要哪些信息
typedef struct student
{
char name[20]; //学生姓名
int age; //学生年龄
struct student *next; //指针域
}student_t , *studentlist;
2.结点初始化的概念,你得清楚指针的运作方式,所以首先肯定得先有指针,再在此前提下创建结构体所需要的空间
student_t *head; //定义头指针
head = NULL;
/*
定义并申请一个头节点空间
*/
student_t *class;
class = (student_t*)malloc(sizeof(student_t));
if(class == NULL)
{
printf("申请空间失败\n");
exit(0);
}
class->next = NULL;
head = class;
3.链表表尾插入结点---(既然是插入一个结点那肯定不能少的就是申请一个结构体结点空间)
判断是否到表尾
while (class->next !=NULL)
{
class = class->next;
}
申请新的结点空间,插入表尾,实现逻辑
stu->next = NULL; //既然是在表尾,其结点指针域肯定为空
class->next = stu;
class = stu;
4.表尾删除尾部元素---(删除一个尾部结点比较简单,只需要将最后一个结点变为野指针再free()释放)
if(head == NULL || head->next == NULL)
{
printf("这是一个空链表!\n");
break;
}
std = head->next;
while (std->next !=NULL)
{
std = std->next;
}
free(std);
break;
5.链表数据的遍历输出---(当你完成上面几步并理解之后,相信你已经能够理解链表基本操作了)
std = head->next;
while (std)
{
printf("学生姓名:%s 学生年龄:%d \n", std->name,std->age);
std = std->next;
}
以上就是所有步骤的讲解,相信很多人都能很清晰的理解,并使用单链表的一些基本操作了
其实链表的主要难点跟指针一样,在于分不清容易混淆变量跟指针的区别使用,你可以这样去理解,现在我想去小明家,但是只有小红知道小明家在哪,所以你得通过小红家的地址找到小红,然后小红再给你指出了小明家的地址,这样你才能找到小明。
(该例子是说明使用指针是得到的地址,地址存的是数据)
完整代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
char name[20]; //学生姓名
int age; //学生年龄
struct student *next; //指针域
}student_t , *studentlist;
int main()
{
student_t *head ,*stu ,*class;
student_t *std,*stdp;
char choose_mode;
class = (student_t*)malloc(sizeof(student_t));
if(class == NULL)
{
printf("申请空间失败\n");
exit(0);
}
class->next = NULL;
head = class;
while (1)
{
printf("请输入cmd(a t d s q):");
choose_mode = getchar();
fflush(stdin);
switch (choose_mode)
{
case 'a':
//尾插法添加链表元素
class = (student_t*)malloc(sizeof(student_t));
class->next = NULL;
class = head;
while (class->next !=NULL)
{
class = class->next;
}
stu = (student_t*)malloc(sizeof(student_t));
printf("请输入学生姓名 年龄:");
scanf("%s%d",stu->name,&stu->age);
stu->next = NULL;
class->next = stu;
class = stu;
break;
case 'd':
//尾部删除元素
printf("删除尾部元素!!\n");
//stu = (student_t*)malloc(sizeof(student_t));
if(head == NULL || head->next == NULL)
{
printf("这是一个空链表!\n");
break;
}
std = head->next;
while (std->next !=NULL)
{
std = std->next;
}
free(std);
break;
case 's':
//遍历链表并输出
printf("输出所有学生信息!\n");
std = head->next;
while (std)
{
printf("学生姓名:%s 学生年龄:%d \n", std->name,std->age);
std = std->next;
}
break;
case 'q':
printf("退出!\n");
exit(0);
break;
default:
break;
}
}
return 0;
}