注意:
(1)单链表的查阅,删除,插入,都是先将工作指针移动到要操作的节点的前一个节点。
(2)链表的空表判定是num==0 或者 head->next=NULL
指针的移动:
for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
{
g=g->next;
}
一、链表的操作
1、链表的节点结构
分为两个域,数据域保存线性表的数据,指针域存放下一个节点的地址
//链表节点结构
typedef struct node
{
int dat;// 数据域
struct node *next;//指针域
}listjd;
int num;//节点计数
2、头结点的初始化
头结点的存在,是可有可无的,存在的意义是统一删除插入操作
//链表头节点的初始化,返回头节点的位置
listjd* Init()
{
listjd* hst=(listjd*)malloc(sizeof(listjd));//头结点的内存申请,并赋给头指针hst
hst->dat=0;//头结点的数据域一般不用,或者用来存放链表的长度
hst->next=NULL;//避免野指针
return hst;//返回头指针的地址
}
3、增
//增 (头指针,选择头插还是尾插,增加的数据值)
void addlist(listjd* hst,int n,int data)
{
int j;
listjd *x;//新增节点的地址
listjd *g=hst;//工作指针
if(!hst || n>num+1 || n<1)//头节点地址申请失败 或要插入的位置超出表尾 或 插入位置在头节点前 非法
{
printf("!!!!!!\n");
return;
}
//新节点的初始化
x=(listjd*)malloc(sizeof(listjd));//申请新新节点的空间
x->dat=data;//将数据放入新节点的数据域
x->next=NULL;//将新节点的指针域指向空,避免野指针
for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
{
g=g->next;
}
x->next=g->next;//将工作指针(要新增节点地址的前一个节点地址)的数据域指向赋给新节点的数据域
g->next=x;//将新节点的地址赋给前一个节点的数据域
num++;//链表长度增加1
}
4、删
//删(头指针,删除的位置),返回删除的节点数据
int dellist(listjd* hst,int n)
{
int j;
int m;//删除的节点数据
listjd *g=hst;//工作指针
listjd *L;//留守指针
if(!hst || n>num || n<1)//头节点地址申请失败 或 要删除的位置超出表尾 或 删除位置在头节点前 非法
{
printf("非法!!!\n");
return 0;
}
for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
{
g=g->next;
}
L=g;//留守指针同工作指针的指向
g=g->next;//工作指针移动到要删除的节点
m=g->dat;//将删除的节点的数据保存
L->next=g->next;//将删除节点的指针域赋给前一个节点,断开了前一个节点和删除节点的链接
g->next=NULL;//断开删除节点和下一个节点的链接
free(g);//释放删除的节点内存
num--;//表长度减1
g=NULL;
return m;//返回删除的节点数据
}
5、查
//查(头指针,查阅的数据),返回数据所在的节点位置
int redlist(listjd* hst,int n)
{
int j=0;//查阅节点的计数
listjd *g=hst;//工作指针指向头节点
if(!hst)//头节点地址申请失败
{
printf("!!!!!!\n");
return 0;
}
while(n!=g->dat)//查阅的数字和工作指针指向的节点 的数据域中数据不相同
{
g=g->next;//移动工作指针到下一个节点
j++;//节点位置计数增加
if(g==NULL)//如果到了表尾还没有查到
{
return j=0;
}
}
return j;//返回查到的节点位置
}
6、清
//清除链表,返回链表长度
int clearalllist(listjd* hst)
{
listjd* g;//工作指针
while(num!=0 || hst->next!=NULL)//不为空表
{
//相当于执行num次删除第一个节点的工作
g=hst->next;//工作指针指向第一个节点
hst->next=g->next;//将第一个节点的指针域赋给头节点,断开了头节点和删除节点的链接
g->next=NULL;
free(g);
num--;
}
if((num==0) || (hst->next=NULL))//为空表时
{
hst->next=NULL;
}
return num;//返回此时为0的表长度
}
二、总函数
#include <stdio.h>
#include <stdlib.h>
//链表节点结构
typedef struct node
{
int dat;// 数据域
struct node *next;//指针域
}listjd;
int num;//节点计数
//链表头节点的初始化,返回头节点的位置
listjd* Init()
{
listjd* hst=(listjd*)malloc(sizeof(listjd));//头结点的内存申请,并赋给头指针hst
hst->dat=0;//头结点的数据域一般不用,或者用来存放链表的长度
hst->next=NULL;//避免野指针
return hst;//返回头指针的地址
}
//增 (头指针,选择头插还是尾插,增加的数据值)
void addlist(listjd* hst,int n,int data)
{
int j;
listjd *x;//新增节点的地址
listjd *g=hst;//工作指针
if(!hst || n>num+1 || n<1)//头节点地址申请失败 或要插入的位置超出表尾 或 插入位置在头节点前 非法
{
printf("!!!!!!\n");
return;
}
//新节点的初始化
x=(listjd*)malloc(sizeof(listjd));//申请新新节点的空间
x->dat=data;//将数据放入新节点的数据域
x->next=NULL;//将新节点的指针域指向空,避免野指针
for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
{
g=g->next;
}
x->next=g->next;//将工作指针(要新增节点地址的前一个节点地址)的数据域指向赋给新节点的数据域
g->next=x;//将新节点的地址赋给前一个节点的数据域
num++;//链表长度增加1
}
//删(头指针,删除的位置),返回删除的节点数据
int dellist(listjd* hst,int n)
{
int j;
int m;//删除的节点数据
listjd *g=hst;//工作指针
listjd *L;//留守指针
if(!hst || n>num || n<1)//头节点地址申请失败 或 要删除的位置超出表尾 或 删除位置在头节点前 非法
{
printf("非法!!!\n");
return 0;
}
for(j=1;j<n;j++)//移动工作指针到要新增节点地址的前一个节点地址
{
g=g->next;
}
L=g;//留守指针同工作指针的指向
g=g->next;//工作指针移动到要删除的节点
m=g->dat;//将删除的节点的数据保存
L->next=g->next;//将删除节点的指针域赋给前一个节点,断开了前一个节点和删除节点的链接
g->next=NULL;//断开删除节点和下一个节点的链接
free(g);//释放删除的节点内存
num--;//表长度减1
g=NULL;
return m;//返回删除的节点数据
}
//查(头指针,查阅的数据),返回数据所在的节点位置
int redlist(listjd* hst,int n)
{
int j=0;//查阅节点的计数
listjd *g=hst;//工作指针指向头节点
if(!hst)//头节点地址申请失败
{
printf("!!!!!!\n");
return 0;
}
while(n!=g->dat)//查阅的数字和工作指针指向的节点 的数据域中数据不相同
{
g=g->next;//移动工作指针到下一个节点
j++;//节点位置计数增加
if(g==NULL)//如果到了表尾还没有查到
{
return j=0;
}
}
return j;//返回查到的节点位置
}
//清除链表,返回链表长度
int clearalllist(listjd* hst)
{
listjd* g;//工作指针
while(num!=0 || hst->next!=NULL)//不为空表
{
//相当于执行num次删除第一个节点的工作
g=hst->next;//工作指针指向第一个节点
hst->next=g->next;//将第一个节点的指针域赋给头节点,断开了头节点和删除节点的链接
g->next=NULL;
free(g);
num--;
}
if((num==0) || (hst->next=NULL))//为空表时
{
hst->next=NULL;
}
return num;//返回此时为0的表长度
}
void main()
{
int m;
int j;
listjd* hst=Init();////链表头节点的初始化,返回头节点的位置
listjd* p=hst;//工作指针指向头节点
addlist(hst,1,10);//增 (头指针,选择头插还是尾插,增加的数据值)
addlist(hst,2,20);
addlist(hst,3,30);
m=dellist(hst,3);//删(头指针,删除的位置),返回删除的节点数据
printf("被删除的数据为:%d\n",m);
j=redlist(hst,50);//查(头指针,查阅的数据),返回数据所在的节点位置
if(j==0)
{printf("查询失败,没有对应数据\n");}
else
{printf("查阅的数据位置为:%d\n",j);}
clearalllist(hst);//清除链表,返回链表长度
printf("链表长度为:%d\n",num);
while(p!=NULL)//展示链表的数据
{
p=p->next;
printf("%d ",p->dat);
}
}
这篇博客详细介绍了单链表的基本操作,包括如何初始化头节点,增加、删除、查阅和修改节点,以及清空整个链表的函数实现。通过工作指针的移动和节点指针的更新,确保了操作的正确性,并提供了错误检查。示例代码展示了链表的动态操作过程。
748

被折叠的 条评论
为什么被折叠?



