写在前面:

最近正在学习数据结构中的单链表,看书(《数据结构(第二版)》,下称课本)的时候理解的挺快的。直到自己敲的时候才发现,笔者看懂的只是书上的类C语言,且个人觉得书上的各个基本操作的实现表现得较为简略,导致自己去实现的时候一塌糊涂。笔者认为最难的是创建单链表后,结点数据在其中的存储以及结点之间逻辑关系的存储。

写此博客,录笔者实现单链表的历程。此篇是第一篇,也是第一步,创建带头结点的单链表,且可输入数据。

:笔者刚上大一,学习c语言没多久,内容比较基础,表达没那么专业到位,更多的是帮助自己记录思路,如有错误,欢迎指正。

实现

思路

创建结构体变量

定义一个链表

创建头结点

创建新结点

打印链表

具体步骤(文末有具体代码及运行效果)

  • 创建结构体

typedef struct node

{

int data;//数据域

struct node *next;//指针域

}LNode,*LinkList;//命名原因如下(出自课本)

笔者的理解LNode表示结点,个数不限;LinkList表示指向头结点的指针,仅有一个

此时,结构体变量创建完成。

  • 定义一个链表

LNode* list;

定义一个LNode类型的list指针变量,用于在函数之间的传递,以储存单链表的每一次改动。

  • 创建头结点

list=createhead()//创建的头结点赋值给list链表

LNode* createhead()

{

LinkList L;//创建头指针

L=(LinkList)malloc(sizeof(LinkList));//为头结点开辟空间,L作为头指针指向这块空间

L->next=NULL;//空链表的尾指针指向空

return L;//将L返回

}

此时,list为一个有头结点的空链表。

  • 创建新结点

createnode(list);//将list传进去,此时list是个指针,传的是单链表的首地址,在函数内部就可改变它;

void createnode(LinkList L)//此处将形参命名为L,且类型为LinkList,意在提示我们传过来的是指

//向头结点的指针;

{

//开辟新结点

LNode* new=(LNode*)malloc(sizeof(LNode));

//安置new的数据域

int data1;

printf(“请输入要放入的值”);

scanf(“%d”,&data1);

new->data=data1;

//安置new的指针域,此处使用前插法(后有解释以及后插法的具体实现)

new->next=L->next;//L的指针域赋值给new,即new指向NULL;

L->next=new;//L指向new

}

//由下图不难看出其关系,

  • 至此,一个可以存储数据及逻辑关系的单链表已创建完成。

*****下面解释一下前插法与后插法的区别

首先要明确一点,每次将单链表传到函数内部,单链表都是从头结点开始访问各个元素的,这取决于单链表的有序存储结构

前插法,每次进去新的结点都是插在头结点后面,成为新的首元结点,而链表的访问又是从头结点开始的,则使用前插法会比较方便。

而后插法,每次都要插在尾结点的后面,成为新的尾结点。这就需要我们每次调用时都找到当前尾结点的所在之处。故需要加入一个函数实现遍历的功能。

后插法版本的createnode:

void createnode(list)

{

LNode* new=(LNode*)malloc(sizeof(LNode));

//安置new的数据域

int data1;

printf(“请输入要放入的值”);

scanf(“%d”,&data1);

new->data=data1;

//安置new的指针域,此处使用后插法

LNode *tail;//t用来遍历,tail定位尾指针

tail=search(L);

tail->next=new;

new->next=NULL;

tail=new;

}

由下图不难看出。

LNode* search(LinkList L)

{

LNode *p=L;

while(p->next)

p=p->next;

return p;

}

*以下细微差距,第二种方法会让tail为nullptr,造成非法访问,*

*逻辑上没有太大问题,但是仔细分析是有问题的*

  • 打印链表

即遍历

void print(LinkList L)

{

LNode *p=L->next;//不指向L,因为L的数据域没数据,就不必输出

while(p)

{

printf(“%d”,p->data);

p=p->next;

}

}

  • 此时,单链表的创建已全部完成,以下是顺序完整的代码(用前插法演示

typedef struct node{struct node* next;int data;}LNode,*LinkList;#include #include LNode* createhead(){LinkList L = (LinkList)malloc(sizeof(LinkList));L->next = NULL;return L;}void createnode(LinkList L) {LNode* new = (LNode*)malloc(sizeof(LNode));int data1;printf("请输入要放入的值");scanf("%d", &data1);new->data = data1;new->next = L->next;L->next = new;}void print(LinkList L){LNode* p = L->next;while (p){printf("%d\n", p->data);p = p->next;}}int main(){LNode* list;list = createhead();while (1)//此处加入死循环,看看是否已经构建起单链表的逻辑结构了{createnode(list);print(list);}}

此为输出的效果,可见单链表已构建成功。

最难的创建单链表已完成,接下来几篇文章将介绍在学生管理系统下的单链表的按姓名查找、按姓名删除、修改、记录学生人数等功能。

谢谢观看!