//完整代码
#include<stdio.h>
#include<stdlib.h>
typedef struct lianbiao
{
int score;
struct lianbiao*next;
}Linklist;
//创造结点
Linklist*creat(int n)
{
Linklist *head,*node,*end;
head=(Linklist*)malloc(sizeof(Linklist));
end=head;//让尾结点等于头结点
printf("请输入要创造的值:\n");
for(int i=0;i<n;i++)
{
node=(Linklist*)malloc(sizeof(Linklist));
scanf("%d",&node->score);
end->next=node;//将尾/头结点的指针域指向刚创建好的普通结点。
end=node;//令尾结点等于现在的普通结点,来实现连接下一个结点。
}
end->next=NULL;//所有结点创好后,让最后一个结点的指针域为空。
return head;//返回头结点(的地址)
}
//删除 (为了看起来更简便,易理解,这里我没有写判空,也没有free)
void delet(Linklist*list,int score,int n)
{
Linklist *t=list->next,*m=list,*p;//定义两个指针,一个承载的头结点的指针域指向的下一个结点地址。 个承载的头结点的地址
for(int i=0;i<n;i++)
{
if(t->score==score)
{
m->next=t->next;
}
else
m=t;//移动m指针
t=t->next;//移动t指针
}
}
//打印 (主要理解如何用另外的指针来前进(遍历)的)
void print(Linklist*list)
{
Linklist *t=list;
while(t->next!=NULL)
{
printf("%d ",t->next->score);
t=t->next;
}
}
//主函数
int main()
{
printf("请选择创建的结点数(不包含头节点):\n");
int n;
scanf("%d",&n);
Linklist*list=creat(n);//创建链表 (这里用list指针来接收头结点的地址)
printf("请输入要删除的值:\n");
int s;
scanf("%d",&s);
delet(list,s,n);
printf("现在的结点的值:\n");
print(list);
return 0;
}
- 如何创建一个链表
#include<stdio.h>
#include<stdlib.h>
typedef struct lianbiao
{
int score;
struct lianbiao*next;
}Linklist;
说明 :
一,typedef之后的"struct lianbiao"这是一个结构体。很多新手同志不知道怎么去理解结构体。其实很简单,你可以理解为这是一个类型
比如我们使用int去定义一个变量a,那a便是整型。
如果用char,那a就是字符型。
而如果我们用结构体去定义a,那么a便是结构体类型,例如struct lianbiao a,这种类型的好处就是,可以使变量a具有多种类型的属性。
二,这里的typedef不过多讲解,想了解更多可以去搜索。为了帮助你理解,你可以把它当成一个"取别名"的标识符。比如在没有用typedef时,我们定义变量a是这样:
struct lianbiao a;可以发现这个定义实在太长了,所以为了简化,我们给struct lianbiao取个别名Linklist,然后定义a就可以是:Linklist a;
//创造结点
Linklist*creat(int n)
{
Linklist *head,*node,*end;
head=(Linklist*)malloc(sizeof(Linklist));
end=head;//让尾结点等于头结点
printf("请输入要创造的值:\n");
for(int i=0;i<n;i++)
{
node=(Linklist*)malloc(sizeof(Linklist));
scanf("%d",&node->score);
end->next=node;//将尾/头结点的指针域指向刚创建好的普通结点。
end=node;//令尾结点等于现在的普通结点,来实现连接下一个结点。
}
end->next=NULL;//所有结点创好后,让最后一个结点的指针域为空。
return head;//返回头结点(的地址)
}
创造结点的难点:
1,Linklist*creat(int n)
可以这样理解,这是一个由Linklist*的类型定义的一个creat函数,参数为n。为什么是
Linklist*的类型而不是Linklist类型呢?因为我们待会儿返回的是头结点的地址,所以用
Linklist*这种结构体指针类型来接收。
2,head=(Linklist*)malloc(sizeof(Linklist));
这是动态内存分配,用head指针,去接收一个大小为结构体类型Linklist的空间大小的地址。
3,创建头指针(结点),普通指针(结点),尾指针(结点)的目的。
(注:这里说明一下为什么又叫指针又叫结点,因为我们创建的结点要以地址的方式返回,所以用指针来接收地址)
1,创建头结点,因为会将它作为返回值,我们知道头结点,就可以通过它访问整个链表,头结点的数据域(score)可以不用赋值。
2,普通结点,这个是我们需要给数据域(score)赋值的结点。
3,尾结点,或者说指针,我们用它来将链表串起来(具体步骤看代码注释)
//删除
void delet(Linklist*list,int score,int n)
{
Linklist *t=list->next,*m=list,*p;//定义两个指针,一个承载的头结点的指针域指向的下一个结点地址。 个承载的头结点的地址
for(int i=0;i<n;i++)
{
if(t->score==score)
{
m->next=t->next;
}
else
m=t;//移动m指针
t=t->next;//移动t指针
}
}
删除功能难点:
1,通过什么方式来删除
这里可以直接将 需要删除的结点 的 上一个结点的指针域 指向 需要删除的结点 的下一个结点。
Linklist *t=list->next,*m=list;
m->next=t->next;
以此来实现一个逻辑上的删除。
(这个结点空间其实并没有删掉,所以我说逻辑上删除,如果要释放删除结点的空间可以用free。刚接触的同志只需要理解这个逻辑上面删除就行了)
2,如何让寻找目标结点的指针前进(或者说遍历)
m=t;
t=t->next;
//打印 (主要理解如何用另外的指针来前进(遍历)的)
void print(Linklist*list)
{
Linklist *t=list;
while(t->next!=NULL)
{
printf("%d ",t->next->score);
t=t->next;
}
}
本人也刚接触编程不久,如有错误,请大佬们指正