C语言链表基础用法

链表的构造

利用结构体构造链表

对于初学者接触的最先都是单链表,所以我们在这里所讲的都为基础单链表

下面,我们来构造链表

#include <stdio.h>
#include <stdlib.h>
struct link_node
{
	int num;
	struct link_node *next;
};

利用指针进行空间申请和释放定义链表头指针

这里struct link_node *next 就是该类型的指针,进行穿线,记录下一个结构体的地址。这时候我们就需要一个指针来当起始点,就是头,一般定义为pHead,同时简单介绍一下申请和释放内存的相关知识。

函数名函数原型功能返回值
callocvoid * calloc (unsigned n,unsigned size);分配n个数据项的连续内存空间,每个数字项的大小为size个字节分配内存单元的起始地址。如不成功,返回0
freevoid free (void *p);释放p所指向的内存区
mallocvoid * malloc (unsigned size);分配size个字节的内存区所分配的内存地址,如内存不够,返回0
reallocvoid * realloc (void *p,unsigned size);将p所指向的已分配的内存区的大小改为size。size可以比原来分配的空间大或小返回指向该内存区的指针。若重新分配失败,返回NULL

定义头指针和申请空间;

int main ()
{
    struct link_node *pHead;
    pHead=(struct link_node *)malloc(sizeof(struct link_node));
    pHead->next=NULL; //指针初始化,养成好习惯
    return 0;
}

这样一个头指针就完成了

链表的插入

链表的存储有两种方法,头插法和尾插法。

头插法

可以把链表头想成火车头,需要插入的数据当成车厢,把车厢就插到火车头后面。如果火车头后面原本有车厢,我们定义原车厢为1号,插入为2号,把火车头与1号车厢的联系传递给2号车厢与1号车厢联系,并将2号车厢再与火车头联系。

上图
头插法

通过图片,我们看到了二号车厢在一号车厢前面,所以头插法就是越先插入越靠后(逆序),下面我们通过函数来实现;

void CreatLink_node(struct link_node *pHead,int n)//n为插入的数据数量
{
	struct link_node *pNew,*p=pHead;
	while(n--)
	{
		int ans;
		scanf("%d",&ans);
		pNew=(struct link_node*)malloc(sizeof(struct link_node));
		pNew->num=ans;
		pNew->next=pHead->next;
		pHead->next=pNew;
	}
}

尾插法

与头插法相反,尾插法是在火车尾部插入,比头插法简单,直接上代码

void CreatLink_node(struct link_node *pHead,int n)
{
    struct link_node *pTail=pHead,*pNew;//只存在火车头,也是车尾
    while(n--)
    {
        int ans;
        scanf("%d",&ans);
        pNew=(struct link_node*)malloc(sizeof(struct link_node));
        pNew->num=ans;
        pNew->next=NULL;
        pTail->next=pNew;
        pTail=pNew;
    }
}

随机插入

随机插入就是我们自己来决定在哪节车厢插入,若在第几节车厢后插入,那我们把这节车厢当作火车头,那么就和头插法一样,这个问题就迎刃而解了。

链表的查询

从火车头走到火车尾,找到符合关系的数据

int SearchLink_node(struct link_node *pHead,int k) //查询链表中元素等于k的个数
{
    struct link_node *p=pHead->next;
    int ans=0;
    while(p!=NULL)
    {
        if(p->num==k) ans++;
        p=p->next;
    }
    return ans;
}

链表的输出

链表输出就是通过火车头与车厢的关系,来进行向下传递,到达每个车厢都进行一次输出,代码如下。

void OutputLink_node(struct link_node *pHead)
{
    struct link_node *p=pHead->next;//火车头不存数据
    while(p!=NULL)
    {
        printf("%d ",p->num);
        p=p->next;
    }
}

但是一般情况下我们要输出的数据并不是全部,而是个别,那么我们可以先判断一下该车厢的数据是否符合规定,如果事的话,那么就输出,和全输出代码相差不大,大家可以私下进行。

链表的删除

这里介绍的是链表的全删除,称为清空。
代码如下

void DeleteLink_node(struct link_node *pHead)
{
    struct link_node *p=pHead->next,*pCut;
    pHead->next=NULL;
    while(p!=NULL)
    {
        pCut=p;
        p=p->next;
        free(pCut);
    }
}

大家若要删除个别车厢,可以把要删除的车厢定义为2号,前面的车厢定义为1号,后面的定义为3号,把2号与3号车厢的关系转移到1号与3号车厢的关系上,再把2号车厢内存释放,就成功实现了。

void DeleteLink_node(struct link_node *pHead,int k) //k为要删除的第几节车厢
{
    struct link_node *p=pHead,*pCut;
    int i=1;
    for(int i=1; i<k; i++)//找到要删除车厢的前一个车厢
    	p=p->next;
    pCut=p->next;//pCut为要删除的车厢
    p->next=pCut->next;//转移关系
    free(pCut);//释放内存
}

上述所说的车厢,在链表中称为结点,不要被我的比喻所迷惑。

链表的习题

这里我们联系一道题,大家如果想尝试的话我建议先自己写并且测试,再看下面的代码
查询链表中有多少个值为偶数的结点

  • 输入数据有多组
    每组先输入n,之后输入n个整数,利用头插法建立链表。

  • 输出格式
    输出链表中值为偶数的结点(我所比喻的车厢)的个数,没有则输出0。

  • intput
    5
    1 2 3 4 5
    9
    1 1 1 0 0 0 1 1 1
    6
    321 123 655 457 51 55

  • output
    2
    3
    0

代码如下

#include <stdio.h>
#include <stdlib.h>
struct link_node
{
    int num;
    struct link_node *next;
};
void CreatLink_node(struct link_node *pHead,int n)
{
	struct link_node *pNew,*p=pHead;
	while(n--)
	{
		int ans;
		scanf("%d",&ans);
		pNew=(struct link_node*)malloc(sizeof(struct link_node));
		pNew->num=ans;
		pNew->next=pHead->next;
		pHead->next=pNew;
	}
}
int SearchLink_node(struct link_node *pHead)
{
    struct link_node *p=pHead->next;
    int ans=0;
    while(p!=NULL)
    {
        if(p->num%2==0) ans++;
        p=p->next;
    }
    return ans;
}
void DeleteLink_node(struct link_node *pHead)
{
    struct link_node *p=pHead->next,*pCut;
    pHead->next=NULL;
    while(p!=NULL)
    {
        pCut=p;
        p=p->next;
        free(pCut);
    }
}
int main ()
{
    struct link_node *pHead;
    pHead=(struct link_node *)malloc(sizeof(struct link_node));
    pHead->next=NULL;
    int n;
    while(~scanf("%d",&n))
    {
        CreatLink_node(pHead,n);
        int number=SearchLink_node(pHead);
        printf("%d\n",number);
        DeleteLink_node(pHead);
    }
    return 0;
}

总结

上述内容就是链表的基础知识,大家熟悉之后就可以像数组一样灵活应用它,并且感受链表的魅力与优点,唯一不好的就是代码量稍长。

欢迎大家提出错误与想法,我会及时修改与回复。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兵蕊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值