单链表是从头指针(head)指向后继到无后继的尾节点(NULL)结束的线性表,数据单元之间是由节点中的指针指示的(即指针是来链表数据结构的映像)简而言之就是由指针链接起来的线性表结构。
1.链表的简介
链表节点中包含两个域,一个是指针域,另一个是数据域。虽然是线性表结构但是存储结构不一定和顺序表一样的连续存储空间,而是可以连续也可以是不连续
2.单链表的实现
(1)单链表的结构定义
typedef struct Lnode {
int data;//数据域
struct Lnode* next;//指针域
}Lnode;//单链表节点结构定义
定义单链表的节点分别要定义它的数据域(可以自定义确定数据域的元素类型),指针域用来指向下一节点
(2)单链表链接结构定义
typedef struct LnodeLink {
struct Lnode* head;//定义表中的头结点
int size;//定义链表的长度
}LnodeLink;
(3)单链表的初始化
先将头结点(L->head)置为空指针(开始表内没有元素),并且将表长(L->size)设置为0
void LnodeLink_init(LnodeLink* L)
{
L->head = NULL;
L->size = 0;
}
(4)单链表的插入元素
void LnodeLink_creat(LnodeLink* L,int index,int data)
{
if (index < 0 || index < L->size)//判断是否插入值是否存在
{
printf("插入失败\n");
return;
}
Lnode* newLnode = (Lnode*)malloc(sizeof(Lnode));//动态分配节点
newLnode->data = data;//传入数据进入节点
if (index == 0)
{
newLnode->next = L->head;直接将节点接在头结点前面
L->head = newLnode;//把头结点分配给newLnode节点
}
else
{
Lnode* cur = L->head;//定义一个新节点来进行查找操作
for (int i = 0; i < index-1; ++i)
{
cur = cur->next;
}
newLnode->next = cur->next;
cur->next = newLnode;
}
++L->size;//将表长加一
}
单链表的实现中,我觉得比较实用的方法就是重新定义一个节点在表中进行查找操作
Lnode* cur = L->head;
for (int i = 0; i < index-1; ++i)
{
cur = cur->next;
}
newLnode->next = cur->next;
cur->next = newLnode;
上面这个代码是定义了一个新节点(cur)来进行单链表的查找过程(因为表中的head指针没有办法进行移动,就需要一个新的指针来代替head进行遍历操作)
(5)单链表的删除元素
void LnodeLink_delect(LnodeLink* L, int index)
{
if (index < 0 || index > L->size)//判断删除节点是否存在表中
{
printf("删除失败\n");
return ;
}
if (index == 0)
{
Lnode* next = L->head->next;//定义一个新节点来保存新的头结点
free(L->head);//删除原来头结点
L->head = next;//将保存节点赋为头结点
}
else
{
Lnode* cur = L->head;\\定义一个节点来进行查找,与插入操作一样
for (int i = 0; i < index - 1; ++i)
{
cur = cur->next;
}
Lnode* next = cur->next->next;//定义节点接收删除节点后一个元素
free(cur->next);//删除节点
cur->next = next;//跨过删除节点连接好删除后的表
}
--L->size;//表长减一
}
(6)单链表的删除(整表删除)
void LnodeLink_distory(LnodeLink* L)
{
if (L->head)//只要头结点存在就一直删除
{
Lnode* temp=L->head;
L->head = L->head->next;
free(temp);
}
}
构建表的malloc要和free配套存在,不然可能会存在数据泄漏导致最后的结果出错,在构建完表后都要进行删除操作
(7)单链表按下标查找数据
int LnodeLink_find(LnodeLink* L,int index)
{
if (index<0 || index>L->size)//判断表是否存在
{
printf("查找失败\n");
return -1;
}
Lnode* cur = L->head;
for (int i = 0; i < index; ++i)//定义一个节点进行遍历
{
cur = cur->next;
}
return cur->data;
}
这些操作中都包含着定义一个新节点来代替头结点进行遍历的方法
(8)单链表按数据查找节点
Lnode* LnodeLink_get(LnodeLink* L, int data)
{
Lnode* cur = L->head;
while (cur)
{
cur = cur->next;
if (cur->data == data)
{
printf("%d存在表内",data);
return cur;
}
}
return NULL;
}
(9)单链表整表输出
void LnodeLink_display(LnodeLink* L)
{
if (L == NULL)
{
return;
}
Lnode* cur = L->head;//定义一个新节点进行遍历
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL"); //最后输出尾指针NULL
}
3.单链表实现全代码
#include<stdio.h>
#include<stdlib.h>
typedef struct Lnode {
int data;
struct Lnode* next;
}Lnode;
typedef struct LnodeLink {
struct Lnode* head;
int size;
}LnodeLink;
void LnodeLink_init(LnodeLink* L)//初始化
{
L->head = NULL;
L->size = 0;
}
void LnodeLink_distory(LnodeLink* L)//删除
{
if (L->head)//只要头结点存在就一直删除
{
Lnode* temp=L->head;
L->head = L->head->next;
free(temp);
}
}
void LnodeLink_creat(LnodeLink* L,int index,int data)//插入
{
if (index < 0 || index < L->size)
{
printf("插入失败\n");
return;
}
Lnode* newLnode = (Lnode*)malloc(sizeof(Lnode));
newLnode->data = data;
if (index == 0)
{
newLnode->next = L->head;
L->head = newLnode;
}
else
{
Lnode* cur = L->head;
for (int i = 0; i < index-1; ++i)
{
cur = cur->next;
}
newLnode->next = cur->next;
cur->next = newLnode;
}
++L->size;
}
void LnodeLink_delect(LnodeLink* L, int index)//删除
{
if (index < 0 || index > L->size)
{
printf("删除失败\n");
return ;
}
if (index == 0)
{
Lnode* next = L->head->next;
free(L->head);
L->head = next;
}
else
{
Lnode* cur = L->head;
for (int i = 0; i < index - 1; ++i)
{
cur = cur->next;
}
Lnode* next = cur->next->next;
free(cur->next);
cur->next = next;
}
--L->size;
}
int LnodeLink_find(LnodeLink* L,int index)//按下标寻找值
{
if (index<0 || index>L->size)
{
printf("查找失败\n");
return -1;
}
Lnode* cur = L->head;
for (int i = 0; i < index; ++i)
{
cur = cur->next;
}
return cur->data;
}
Lnode* LnodeLink_get(LnodeLink* L, int data)//按值查找表
{
Lnode* cur = L->head;
while (cur)
{
cur = cur->next;
if (cur->data == data)
{
printf("%d存在表内",data);
return cur;
}
}
return NULL;
}
void LnodeLink_display(LnodeLink* L)//输出全表
{
if (L == NULL)
{
return;
}
Lnode* cur = L->head;
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL"); //最后输出尾指针NULL
}
int main() {
LnodeLink L;
LnodeLink_init(&L);//单链表初始化
for (int i = 0; i < 10; ++i)
{
LnodeLink_creat(&L, i, i * 10);//遍历插入元素构建实验表
}
LnodeLink_display(&L); //输出表看看有没有构建成功
printf("\n");
printf("%d",LnodeLink_find(&L,9));//输出下标为九的单元格的元素
printf("\n");
LnodeLink_delect(&L,1);//删除下标为一的单元格内的元素
LnodeLink_display(&L);//输出修改后的表,检验删除操作的实现
return 0;
}
如有错漏敬请指正,感谢观看。