1、基本叙述
1.1概念介绍
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
以“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。
1.2链接存储方法
链接方式存储的线性表简称为链表(Linked List)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
1.3结点结构
┌───┬───┐
│data │next │
└───┴───┘
data域
–存放结点值的数据域
next域-
-存放结点的直接后继的地址(位置)的指针域(链域)
链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked List)
2、数据储存
3、代码实现
3.1创建一个结构体
typedef int Node_Data;
typedef struct node{
Node_Data data;
struct node* next;
}Lnode;
我们使用了typedef的两个用法:为基本数据类型定义新的类型名
和为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
,这样会使代码更简洁,而typedef int Node_Data
方便更改链表储存其它数据类型
3.2创建头节点
//创建链表头节点,返回值为struct node*
Lnode* Create_Head_Node()
{
//动态内存申请
Lnode* Head_Node = (Lnode *)malloc(sizeof(Lnode));
if(Head_Node == NULL)
return NULL;
else
{
//初始化头节点
// Head_Node->data = 1; //这个可以随意赋值
Head_Node->next = NULL;
return Head_Node;
}
}
3.3创建新的节点
//创建新的节点,并给此节点赋值
Lnode* Create_New_Node(Node_Data data)
{
Lnode* New_Node = (Lnode *)malloc(sizeof(Lnode));
if(New_Node == NULL)
return NULL;
else
{
New_Node->data = data;
New_Node->next = NULL;
return New_Node;
}
}
把创建新的节点封装成一个函数,方便后续使用
3.4头插法插入数据
//头插法插入数据
void Insert_Data_List(Lnode* Head_Node,Node_Data data)
{
Lnode* New_Node = Create_New_Node(data);
if(Head_Node == NULL || New_Node == NULL)
{
printf("插入失败\n");
return ;
}
else
{
New_Node->next = Head_Node->next;
Head_Node->next = New_Node;
//printf("插入成功\n");
return ;
}
}
所谓的头插法,就是每次从Head_Node
后面插入.
大概思路为:先创建一个待插入的节点New_Node
,再把头节点Head_Node
指针域的地址赋值给待插入节点New_Node
的next
,最后把头节点Head_Node
的next
指向New_Node
3.5按指定值删除
//按值删除
void Delete_AccordValue_List(Lnode* Head_Node,Node_Data posdata)
{
Lnode* posNode = Head_Node->next;
Lnode* posNodeFront = Head_Node;
if(posNode == NULL)
{
printf("此链表为空,删除失败\n");
return ;
}
else
{
while(posNode->data != posdata)
{
posNodeFront = posNode;
posNode = posNode->next;
//遍历到链表尾部,代表该值不存在
if(posNode == NULL)
{
printf("删除失败,不存在该值\n");
return ;
}
}
posNodeFront->next = posNode->next;
free(posNode);
printf("删除成功\n");
}
}
删除节点:假设posNode
为待删除的节点,posNodeFront
为待删除的节点的前一个节点,如要删除posNode
,只需要把posNode
所指向的节点赋值给posNodeFront
,然后释放posNode
这块内存,free(posNode)
思路如下:
1.判断该链表是否为空
2.遍历链表,确保posNode
与posNodeFront
一前一后
3.while(posNode->data != posdata)
找到待删除的节点时,跳出此循环,若没跳岀循环,则代表该值不存在
4.删除节点posNode
3.6打印链表
//打印链表
void Printf_List(Lnode* Head_Node)
{
Lnode* pMove = Head_Node->next;
if(pMove == NULL)
{
printf("此链表为空,打印失败\n");
return ;
}
else
{
while(pMove != NULL)
{
printf("%d->",pMove->data);
pMove = pMove->next;
}
printf("NULL\n");
}
}
4、全部代码如下
#include<stdio.h>
#include<malloc.h>
typedef int Node_Data;
typedef struct node{
Node_Data data;
struct node* next;
}Lnode;
//创建链表头节点,返回值为struct node*
Lnode* Create_Head_Node()
{
//动态内存申请
Lnode* Head_Node = (Lnode *)malloc(sizeof(Lnode));
if(Head_Node == NULL)
return NULL;
else
{
//初始化头节点
// Head_Node->data = 1; //这个可以随意赋值
Head_Node->next = NULL;
return Head_Node;
}
}
//创建新的节点,并给此节点赋值
Lnode* Create_New_Node(Node_Data data)
{
Lnode* New_Node = (Lnode *)malloc(sizeof(Lnode));
if(New_Node == NULL)
return NULL;
else
{
New_Node->data = data;
New_Node->next = NULL;
return New_Node;
}
}
//打印链表
void Printf_List(Lnode* Head_Node)
{
Lnode* pMove = Head_Node->next;
if(pMove == NULL)
{
printf("此链表为空,打印失败\n");
return ;
}
else
{
while(pMove != NULL)
{
printf("%d->",pMove->data);
pMove = pMove->next;
}
printf("NULL\n");
}
}
//头插法插入数据
void Insert_Data_List(Lnode* Head_Node,Node_Data data)
{
Lnode* New_Node = Create_New_Node(data);
if(New_Node == NULL)
{
printf("插入失败\n");
return ;
}
else
{
New_Node->next = Head_Node->next;
Head_Node->next = New_Node;
//printf("插入成功\n");
return ;
}
}
//按值删除
void Delete_AccordValue_List(Lnode* Head_Node,Node_Data posdata)
{
Lnode* posNode = Head_Node->next;
Lnode* posNodeFornt = Head_Node;
if(posNode == NULL)
{
printf("此链表为空,删除失败\n");
return ;
}
else
{
while(posNode->data != posdata)
{
posNodeFornt = posNode;
posNode = posNode->next;
if(posNode == NULL)
{
printf("删除失败,不存在该值\n");
return ;
}
}
posNodeFornt->next = posNode->next;
free(posNode);
printf("删除成功\n");
}
}
int main()
{
Lnode* Head_Node = Create_Head_Node();
Insert_Data_List(Head_Node,1);
Insert_Data_List(Head_Node,2);
Insert_Data_List(Head_Node,3);
Insert_Data_List(Head_Node,4);
Insert_Data_List(Head_Node,5);
Insert_Data_List(Head_Node,6);
Insert_Data_List(Head_Node,7);
Printf_List(Head_Node);
return 0;
}
查找、按位置插入请查看 【C语言】单链表(二)