不带头结点的单链表的操作
不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样。
- 不带头结点的单链表结构示意图
1.结构体定义
/*单链表的结构定义*/
typedef int ElemType;
typedef struct Node{
ElemType data; //节点数据域
struct Node *next; //节点指针域
}Node,*LinkList;
2.初始化单链表
void InitList(LinkList *L)
{
(*L) = NULL; //*L即表示头指针
}
3.判断元素位置的合法性
int getElem(LinkList L,int i,ElemType *e)//L为这个单链表、i为第i个元素、*e为存放第i个元素数据域的指针变量
/*
个人感觉“*e”这个参数可有可无,因为此函数返回的值是0或-1,
与节点的值没关系,而且会多定义变量造成内存浪费,
但课本上都是这样写的哈哈就照着写呗
*/
{
LinkList p=L;
int j=1;
//寻找第i个节点
while(p && j<i)
{
p=p->next;
j++;
}
//位置非法情况
if(!p || j>i)
{
return -1; //非法
}
//此时j==i,已经找到第i个节点
*e=p->data;
return 0; //合法
}
4.在第i个位置之前的插入元素e
- 插入位置为第一个节点前(头指针后)
- 插入位置在中间
int ListInsert(LinkList *L,int i,ElemType e)//*L为这个单链表、i为要插入的位置、e为要插入节点的数据域
{
int j;
LinkList p,s;
p=*L;
j=1;
//初始化要插入的节点
s=(LinkList)malloc(sizeof(Node));
s->data=e;
//插入位置为第一个节点前
if (i==1)
{
s->next=p;
*L=s;
}
else
{
while(p && j<i) //p后移
{
p=p->next;
j++;
}
//位置非法情况
if(!p || j>i)
{
return -1; //失败
}
//指针p不为空,插入位置为中间
s->next=p->next;
p->next=s;
return 0; //成功
}
}
5.删除第i个元素,并由e返回其值
-
链表为空时,不能进行删除操作
-
删除第一个节点(以下两种情况代码相同)
-
删除中间或最后的节点(两种情况代码相同)
int ListDelete(LinkList *L,int i,ElemType *e)//*L为这个单链表、i为要删除的位置、*e为其返回值
{
int j;
LinkList p,q;
p=*L;
j=1;
if(*L==NULL)
{
printf("链表为空,无法进行删除操作!");
return -1;
}
//删除位置为第一个节点
if(i==1)
{
*L=p->next;
free(p);
return 0;
}
while(p->next && j<i) //p后移
{
p=p->next;
j++;
}
//非法情况
if(!(p->next) || j>i)
return -1;
//删除中间或最后的节点
q=p->next; //q为p后的节点
p->next=q->next;
*e=q->data;
free(q);
return 0;
}
参考链接:c语言实现–不带头结点的单链表操作