最完整C语言单链表

程序人入行第一篇

第一章:单链表篇



前言

   在开始之前我想问大家一个问题:谈到链表,你想到了什么?先思考三秒。 ……
   嗯!我想,你心中已经有了一个答案。而我的答案是——指针。
我认为链表是普通人从普通过渡到一萌新的第一个阶段。这里说的普通人指的是那些会能够理解基础程序语法和逻辑的人,但是止步于指针的人,相信大多数初学者都是这种状态,害怕理解指针或者理解了指针但是写程序总是不用。
   当然,上边这些只代表我的个人观点,也代表了我的历程。我依稀记得我第一次接触链表的时候,大受震撼,脑子混隆隆一下就炸开了——原来程序还能这样写,小新我跪了。
   在我看来,链表,他的重要性不亚于炒菜时厨师放的油盐酱醋,想要跻身程序员一行,学会链表不可或缺。
   废话到此为止,下面我们直接上程序。


温馨提示:关注并私信小新,免费得源码……

一、确定框架

作为一个优秀的成员,写任何一个程序之前首先要确定基本的框架,这将决定我们的程序走向。
温馨提示:如果看不懂下发的框架,建议小萌新们可以先了解下链表的原理。
这个应该没人看不懂吧!

二、展开框架

1.定义结点

代码如下(示例):
这里可以看懂吧,一个简单的结构体

温馨提示:手动敲写代码快速学会链表

2.创建一个结点

写这个代码前,我们首先要确定两个地方

1:函数返回值
2:函数参数表


具体怎么操作还得看你自己的想法,本程序以传入地址,数据,返回空为例。
//创建一个结点
void createNode(List *node,int a)
{
    List p = calloc(1,sizeof(mallocnode));//申请一个内存空间,大小为sizeof(mallocnode);
    p->data = a;//传入数据
    p->next=*node;//指向头结点
    *node=p;//把结果传给头结点
    return;
}
//主函数中的使用方式
<注意传入参数:node为指针,a为int类型变量>createNode(&node,a);

赶紧手动敲一敲吧!

3:打印结点

写之前干什么?老两步——思考返回值,思考参数表,给大家三秒钟思考一下

void printfNode(List node)
{
    List p = node;
    int i=0;
    while(p)//当前结点的地址为空的时候,结束循环
    {
        printf("node->data[%d]=%d\n",i++,p->data);
        p=p->next;//循环结束进入下一个结点
    }
    if(i==0)printf("空链表");
    return;
}
//下面是主函数中的使用
    createNode(&node,1);
    createNode(&node,2);
    createNode(&node,3);
    createNode(&node,4);
    createNode(&node,5);
    printfNode(node);//打印之前创建的五个结点内容

4:删除

这里依然是老二步:确定返回值,确定参数表

在写之前,我们在大脑中回忆一下链表的存储结构

在这里插入图片描述

   现在,我们大致有了一个思路,如果要删除结点2,只需要让指向结点2的箭头跳过2直接指向结点3即可。
   那么这个箭头是什么?
   没错,是指针p->next,只需要让结点1的p->next指向结点3的p,然后让结点2的p->next断开和3的链接就OK了。 因为链表是单向的,所以,在这个过程中,我们必须用在用一个指针记住结点1的地址 [原理:p,p->next是两个地址,但是图中有三个地址]。

理论结束,实验开始

//删除当前结点
void deleteNode(List *node,int a)
{
    List p = *node;//当前指针位置
    List q=NULL;//记录前一个结点的地址
    if(*node==NULL)//判断是空链表直接退出,提高程序运行速度
    {
        printf("这是一个空链表");
        return;
    }
    while(p)
    {
        if(p->data==a)//找到了
        {
            if(p==*node)//如果当前位置是头结点的话,q为空,单独处理
            {
                if(p->next!=NULL)//表示当前链表不止一个结点
                {
                    (*node)=(*node)->next;//头结点指向第二个结点的地址
                    p->next=NULL;//把头结点的箭头置空
                }
                    free(p);
                    p=NULL;
            }
            else
            {
                if(p->next==NULL)//判断是不是最后一个结点
                {
                    q->next=NULL;
                }
                else
                {
                    q->next=p->next;//第一个结点的箭头指向第三个结点的箭头 
                    p->next=NULL;//打断当前结点的箭头                
                }
                free(p);
                p=NULL;
            }
            return ;//一个执行完毕需要退出,原因是已经操作了p.和q,接线来不能继续指向
        }
        q=p;//每一次,记住前一个位置的地址
        p=p->next;
    }
    printf("没有找到");
    return;
}

//主函数部分的使用
int main(int argc, char* argv[])
{
    int a=5;
    for(int i=5;i>=0;i--)
    {
        createNode(&node,i);
    }
    printfNode(node);
    deleteNode(&node,2);
    printfNode(node);
    return 1;
}

5:排序

链表的排序一般采用插入法:这就需要再新建一个链表,不了解原理的同学可先去百度一下插入法排序的原理。
这里我就不多说了,直接上程序:

//排序
void rankNode(List *node)
{
    List p = *node;
    List New=NULL;//新链表
    if(p==NULL) 
    {
        printf("空链表哦");
        return;
    }
    while(*node)//排序一定会遍历链表
    {
        p=*node;
        (*node)=(*node)->next;
        p->next=NULL;
        rank(p,&New);//将当前结点扔进单独的函数进行排序
    }
    *node=New;
    return;
}
void rank(List p,List *new)
{
    List pNew= *new;
    List pAnd = NULL;//记录当前位置
    while(pNew)
    {
        if(pNew->data>p->data)//发现了第一个他大的值
        {
            if(pNew==*new)//第一个位置就发现了,用头插法
            {
               *new=p;//给头指针赋值传入内容
            }
            else
            {
                pAnd->next=p;
            }
            p->next=pNew;
            return;
        }
        pAnd=pNew;
        pNew=pNew->next;
    }
    if(*new==NULL)
    {
        *new=p;
    }
    else//没有在循环中找到,直接插在最后一个
    {
        pAnd->next=p;
    }
    return ;
}
//这里是用了两个函数来来完成任务,下面是主程序的使用

int main(int argc, char* argv[])
{
    int a=5;
    createNode(&node,2);
    createNode(&node,1);
    createNode(&node,6);
    createNode(&node,4);
    createNode(&node,7);
    printfNode(node);
    rankNode(&node);
    printfNode(node);
    return 1;
}

修改结点

  相对来说,修改结点就比较简单了,大家可以不看教程自己试一试,整个过程还是老二步骤:
  返回值,参数列表,其实这里还应该多加一个步骤,梳理实现功能。

void setNode(List *node,int a)
{
    List p = *node;
    int setNumber=0;
    while(p)
    {
        if(p->data==a)
        {
            printf("修改当前%d值为:",p->data);
            scanf("%d",&setNumber);
            p->data=setNumber;
        }
        p=p->next;//这个移动到下一结点的命令相信大家已经都能看懂了吧
    }
    return;
}

//主函数的使用
int main(int argc, char* argv[])
{
    int a=5;
    createNode(&node,2);
    createNode(&node,1);
    createNode(&node,6);
    createNode(&node,4);
    createNode(&node,7);
    printfNode(node);
    setNode(&node,1);
    printfNode(node);
    return 1;
}

查询一个结点

  学会了前面的,这个再简单不过了

//查询一个结点
void seek(List node,int a)
{
    List p = node;
    while(p)
    {
        if(p->data==a)
        {
            printf("数据为:%d,地址为%p",p->data,p);
        }
        p=p->next;
    }
    return ;
}
//主函数中的使用
int main(int argc, char* argv[])
{
    int a=5;
    createNode(&node,2);
    createNode(&node,1);
    createNode(&node,6);
    createNode(&node,4);
    createNode(&node,7);
    printfNode(node);
    seek(node,6);
    return 1;
}

第二章:带头C链表【点击学习】

加入我们:QQ群:928357277

  • 7
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

亿只萌新

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

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

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

打赏作者

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

抵扣说明:

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

余额充值