实现一个链表数据结构,并提供了插入、删除和搜索操作
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//定义链表结点
typedef struct tlinknode
{
int data;
struct tlinknode*next;
}linknode;
//查找链表中x所在位置
bool searchPrev(linknode*plinklist,int x,linknode**p)//linknode 是一个结构体类型,plinklist 是一个指向 linknode 结构体的指针,表示一个链表的头指针,linknode** 表示一个指向 linknode* 的指针,也就是一个指向链表头指针的指针,p 是这个指针的变量名,它可能指向一个链表的头指针。
{
linknode*t=plinklist;//将链表的头指针赋给t
while(t->next)//头指针指向链表结点的指针域
{
if(t->next->data==x)
{
*p=t;
return true;
}
t=t->next;
}
*p=t;
return false;
}
bool insert(linknode*plinklist,int x,int y)
{
linknode*prev=NULL;
searchPrev(plinklist,x,&prev);
linknode*pnew=(linknode*)malloc(sizeof(linknode));
pnew->data=y;
pnew->next=prev->next;
prev->next=pnew;
return true;
}
bool delete(linknode*plinklist,int x)
{
linknode*prev=NULL;
searchPrev(plinklist,x,&prev);
if(prev==NULL||prev->next==NULL)
{
return false;
}else if(prev->next!=NULL)
{
linknode*p=prev->next->next;
free(prev->next);
prev->next=p;
}
return true;
}
int main()
{
int n,x,y;
char s[10];
scanf("%d",&n);
linknode*plinklist=(linknode*)malloc(sizeof(linknode));
plinklist->next=NULL;
while(n--)
{
scanf("%s",s);
if(strcmp(s,"insert")==0)
{
scanf("%d%d",&x,&y);
insert(plinklist,x,y);
}
else if(strcmp(s,"delete")==0)
{
scanf("%d",&x);
delete(plinklist,x);
}
}
linknode*p=plinklist;
if(p->next==NULL)
{
printf("NULL");
}
while(p->next)
{
p=p->next;
printf("%d ",p->data);
}
return 0;
}
在单链表的结构定义中,每个节点包含一个数据元素和一个指向下一个节点的指针。其中,LinkNode是结构体类型,p是一个指向LinkNode类型的指针,因此需要使用两个星号(**)来表示。
具体来说,LinkNode是一种自定义的数据类型,它可能包含一些特定于应用程序的数据成员和函数成员。在这种情况下,使用两个星号可以将p声明为指向LinkNode类型的指针,使其可以指向LinkNode类型的对象或节点。
这种使用方式在C语言中并不常见,但在某些特定的应用程序中可能会遇到。
链表的初始化
初始化主要完成以下工作:创建一个单链表的前置节点并向后逐步添加节点,一般指的是申请结点的空间,同时对一个结点赋空值(NULL),其代码可以表示为:
text
LinkedList listinit(){
Node *L;
L=(Node*)malloc(sizeof(Node)); //开辟空间
if(L==NULL){ //判断是否开辟空间失败,这一步很有必要
printf("申请空间失败");
//exit(0); //开辟空间失败可以考虑直接结束程序
}
L->next=NULL; //指针指向空
}
==注意:==一定要判断是否开辟空间失败,否则生产中由于未知的情况造成空间开辟失败,仍然在继续执行代码,后果将不堪设想啦,因此养成这样的判断是很有必要的。