文章目录
- 1. 链表插入元素
- 2. 链表删除元素
- 3. 链表查找元素
- 4. 链表更新元素
1. 链表插入元素
向链表中增添元素,根据添加位置不同,可分为以下 3 种情况:
- 插入到链表的头部(头节点之后),作为首元节点;
- 插入到链表中间的某个位置;
- 插入到链表的最末端,作为链表中最后一个数据元素;
虽然新元素的插入位置不固定,但是链表插入元素的思想是固定的,只需做以下两步操作,即可将新元素插入到指定的位置:
- 将新结点的
next
指针指向插入位置后的结点; - 将插入位置前结点的
next
指针指向插入结点;
例如,在链表 {1,2,3,4}
的基础上分别实现在头部、中间部位、尾部插入新元素 5,其实现过程如图所示:
注意:链表插入元素的操作必须是先步骤 1,再步骤 2;否则会导致插入位置后的这部分链表丢失,无法再实现步骤 1。
编写 C 语言代码来实现链表插入元素的操作:
//L为原链表,elem表示新数据元素,position表示新元素要插入的位置
Node *LinkInsert(Node *L, int elem, int position)
{
Node *temp = L; //创建临时结点temp
//首先找到要插入位置的上一个结点
for(int i = 1; i< position; i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("插入位置无效\n");
return L;
}
}
//创建插入结点a
Node *a = (Node*)malloc(sizeof(Node));
a->elem = elem;
//向链表中插入结点
a->next = temp->next;
temp->next = a;
return L;
}
2. 链表删除元素
从链表中删除指定数据元素时,实则就是将存有该数据元素的节点从链表中摘除,然后释放该节点的存储空间。因此,从链表中删除数据元素需要进行以下 2 步操作:
- 将结点从链表中摘下来;
- 手动释放掉结点,回收被结点占用的存储空间;
从链表上摘除某节点的实现非常简单,只需找到该节点的直接前驱节点 temp
,执行一行程序:
temp->next = temp->next->next;
例如,从存有{1,2,3,4}
的链表中删除元素 3,则此代码的执行效果如图所示:
链表删除元素的 C 语言实现如下所示:
//L为原链表,position为要删除元素的值
Node *LinkDelete(Node *L, int position)
{
Node *temp = L;
//遍历到被删除结点的上一个结点
for(int i = 1; i < position; i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("删除位置无效\n");
return L;
}
}
Node *a = temp->next; //单独设置一个指针指向被删除结点,以防丢失
temp->next = temp->next->next; //删除某个结点的方法就是更改前一个结点的指针域
free(a); //手动释放该结点,防止内存泄漏
return L;
}
3. 链表查找元素
在链表中查找指定数据元素,最常用的方法是:从表头依次遍历表中节点,用被查找元素与各节点数据域中存储的数据元素进行比对,直至比对成功或遍历至链表最末端的 NULL
(比对失败的标志)。
链表中查找特定数据元素的 C 语言实现代码为:
//L为原链表,elem表示被查找元素
int LocateElem(Node *L, int elem)
{
//新建一个指针temp,初始化为头指针L
Node *temp = L;
int position = 1;
//由于头节点的存在,因此while中的判断为t->next
while(temp->next)
{
temp = temp->next;
if(temp->elem == elem)
{
return position;
}
position += 1;
}
//程序执行至此处,表示查找失败
return -1;
}
4. 链表更新元素
更新链表中的元素,只需通过遍历找到存储此元素的节点,对节点中的数据域做更改操作即可。
链表中更新数据元素的 C 语言实现代码:
//更新函数,其中,position 表示更改结点在链表中的位置,newElem 为新的数据域的值
Node *LinkModify(Node *L, int position, int NewElem)
{
Node *temp = L;
temp = temp->next; //在遍历之前,temp指向首元结点
//遍历到待更新节点
for(int i = 1; i < position; i++)
{
temp = temp->next;
}
temp->elem = NewElem;
return L;
}
以上就是对链表中数据元素做"增删查改"的实现过程及 C 语言代码,如下是完整的代码清单:
#include<stdio.h>
#include<stdlib.h>
//链表中节点的结构
typedef struct node
{
int elem; //代表数据域
struct Node *next; //代表指针域,指向直接后继元素
}Node; //Node为节点名,每个节点都是一个Node结构体
//初始化链表的函数
Node *InitLink();
Node *InitLinkWithHead();
//用于输出链表的函数
void DisplayLink(Node *L);
//链表插入的函数,p是链表,elem是插入的结点的数据域,position是插入的位置
Node *LinkInsert(Node *L, int elem, int position);
//删除结点的函数,L代表操作链表,position代表删除节点的位置
Node *LinkDelete(Node *L, int position);
//查找节点的函数,elem为目标结点的数据域的值
int LocateElem(Node *L, int Elem);
//更新结点的函数,newElem为新的数据域的值
Node *LinkModify(Node *l, int OldElem, int NewElem);
int main()
{
//初始化链表(1,2,3,4)
printf("初始化链表为:\n");
Node *L = InitLinkWithHead();
DisplayLink(L);
printf("在第4的位置插入元素5:\n");
L = LinkInsert(L, 5, 4);
DisplayLink(L);
printf("删除元素3:\n");
L = LinkDelete(L, 3);
DisplayLink(L);
printf("查找元素2的位置为:\n");
int position = LocateElem(L, 2);
if (position == -1)
{
printf("没有该元素");
}
else
{
printf("元素2的位置为:%d\n", position);
}
printf("更改第3的位置上的数据为7:\n");
L = LinkModify(L, 3, 7);
DisplayLink(L);
return 0;
}
Node *InitLink()
{
Node *p = NULL; //创建头指针
Node *temp = (Node*)malloc(sizeof(Node)); //创建首元节点
//首元节点先初始化
temp->elem = 1;
temp->next = NULL;
p = temp; //头指针指向首元节点
//从第二个节点开始创建
for(int i = 2; i < 5; i++)
{
//创建一个新节点并初始化
Node *a = (Node*)malloc(sizeof(Node));
a->elem = i;
a->next = NULL;
//将temp节点与新建立的a节点建立逻辑关系
temp->next = a;
//指针temp每次都指向新链表的最后一个节点,其实就是 a节点,这里写temp=a也对
temp = temp->next;
}
//返回建立的节点,只返回头指针 p即可,通过头指针即可找到整个链表
return p;
}
Node *InitLinkWithHead()
{
Node *p = (Node*)malloc(sizeof(Node)); //创建一个头结点
Node *temp = p; //声明一个指针指向头结点
//生成链表
for(int i = 1; i < 5; i++)
{
Node *a = (Node*)malloc(sizeof(Node));
a->elem = i;
a->next = NULL;
temp->next = a;
temp = temp->next;
}
return p;
}
//p为原链表,elem表示新数据元素,position表示新元素要插入的位置
Node *LinkInsert(Node *L, int elem, int position)
{
Node *temp = L; //创建临时结点temp
//首先找到要插入位置的上一个结点
for(int i = 1; i< position; i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("插入位置无效\n");
return L;
}
}
//创建插入结点a
Node *a = (Node*)malloc(sizeof(Node));
a->elem = elem;
//向链表中插入结点
a->next = temp->next;
temp->next = a;
return L;
}
//p为原链表,add为要删除元素的值
Node *LinkDelete(Node *L, int position)
{
Node *temp = L;
//遍历到被删除结点的上一个结点
for(int i = 1; i < position; i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("删除位置无效\n");
return L;
}
}
Node *a = temp->next; //单独设置一个指针指向被删除结点,以防丢失
temp->next = temp->next->next; //删除某个结点的方法就是更改前一个结点的指针域
free(a); //手动释放该结点,防止内存泄漏
return L;
}
//L为原链表,elem表示被查找元素
int LocateElem(Node *L, int elem)
{
//新建一个指针temp,初始化为头指针L
Node *temp = L;
int position = 1;
//由于头节点的存在,因此while中的判断为t->next
while(temp->next)
{
temp = temp->next;
if(temp->elem == elem)
{
return position;
}
position += 1;
}
//程序执行至此处,表示查找失败
return -1;
}
//更新函数,其中,add 表示更改结点在链表中的位置,newElem 为新的数据域的值
Node *LinkModify(Node *L, int position, int NewElem)
{
Node *temp = L;
temp = temp->next; //在遍历之前,temp指向首元结点
//遍历到待更新结点
for(int i = 1; i < position; i++)
{
temp = temp->next;
}
temp->elem = NewElem;
return L;
}
void DisplayLink(Node *L) {
Node* temp = L;//将temp指针指向头结点
//只要temp指针指向的结点的next不是Null,就执行输出语句。
while (temp->next)
{
temp = temp->next;
printf("%d ", temp->elem);
}
printf("\n");
}
代码运行结果:
初始化链表为:
1 2 3 4
在第4的位置插入元素5:
1 2 3 5 4
删除元素3:
1 2 5 4
查找元素2的位置为:
元素2的位置为:2
更改第3的位置上的数据为7:
1 2 7 4