高级C语言-链表&状态机和多线程

链表的引入

链表是什么样的?
(1)链表就是用锁链链接起来的表。这里的表指的是一个个的节点,节点中有一些内存可以用来存储的数据(所以叫表,表就是数据表);这里的锁链指的是链接各个表的方法,C语言中用来链接两个表(两块内存)的方法就是指针。
(2)链表是若干个节点组成的,节点是由有效数据和指针组成的。有效数据区域是用来存储信息完成任务的,指针区域用于指向链表的下一个节点从而构成链表
链表是用来做啥的?
(1)链表就是用来解决数组的大小不能动态扩展的问题,所以链表其实就是当数组用的,链表能完成的任务用数组也能完成,数组能完成的任务用链表也能完成。
(2)链表用来存放数据相对于数组来说优点就是灵活性,需要多少个动态分配多少个,不占用额外的内存。数组的优势就是简单

单链表的实现

单链表的节点构成
(1)链表是由节点组成的,节点中包含:有效数据和指针
(2)定义的struct node只是一个结构体,本身并没有变量生成,也不占用内存。结构体定义相当于为链表节点定义了一个模板。但是没有一个结点,将来时间创建链表时需要一个节点时用这个模板来复制一个即可
堆内存的申请和使用
(1)链表的内存要求比较灵活,不能用栈,也不能用data数据段。只能用堆内存
(2)使用堆内存来创建一个链表节点的步骤:1.申请堆内存,大小为一个节点的大小(检查申请的结果是否正确);2.清理申请到的堆内存;3。把申请到的堆内存当做一个新节点;4.填充一个新节点的有效数据和指针区域
链表的头指针
(1)头指针不是节点,而是一个普通的指针,只占4个字节。头指针的类型是struct node*类型的,所以它才能指向链表的节点
(2)一个典型的链表的实现就是:头指针指向链表的第一个结点,然后第一个结点中的指针指向下一个结点,然后依次类推一直到最后一个节点。这样就构成了一个链。
构建一个简单的单链表

#include<stdio.h>
#include<strings.h>
struct node
{
   
    int data;               //有效数据
    struct node *pnext;     //指向下一个节点的指针
};


int main()
{
   
    //创建一个头指针
    struct node *phead = NULL;

    //*********************************************
    //申请内存作为堆节点的空间,空间大小为一个结构体的大小
    struct node *p = (struct node *)malloc(sizeof(struct node));
    //判断新申请的节点是否申请成功
    if(NULL == p)
    {
   
        printf("malloc error.\n");
        return -1;
    }
    //清理这段新申请的空间中的数据
    bzero(p,sizeof(struct node));
    //同时给结构体中的有效数据赋值
    p->data = 1;
    p->pnext = NULL;//将来要指向下一个节点的首地址,实际操作将下一个节点malloc返回的指针赋值给这个
    phead = p;//这里是将p也就是当前节点的首地址,赋值给头指针,进行关联

    //*********************************************
    //申请内存作为堆节点的空间,空间大小为一个结构体的大小
    struct node *p1 = (struct node *)malloc(sizeof(struct node));
    //判断新申请的节点是否申请成功
    if(NULL == p1)
    {
   
        printf("malloc error.\n");
        return -1;
    }
    //清理这段新申请的空间中的数据
    bzero(p1,sizeof(struct node));
    //同时给结构体中的有效数据赋值
    p1->data = 1;
    p1->pnext = NULL;
    p->pnext = p1;
    //*********************************************

    //申请内存作为堆节点的空间,空间大小为一个结构体的大小
    struct node *p2 = (struct node *)malloc(sizeof(struct node));
    //判断新申请的节点是否申请成功
    if(NULL == p2)
    {
   
        printf("malloc error.\n");
        return -1;
    }
    //清理这段新申请的空间中的数据
    bzero(p2,sizeof(struct node));
    //同时给结构体中的有效数据赋值
    p2->data = 1;
    p2->pnext = NULL;
    p1->pnext = p2;
    //*********************************************

    //申请内存作为堆节点的空间,空间大小为一个结构体的大小
    struct node *p3 = (struct node *)malloc(sizeof(struct node));
    //判断新申请的节点是否申请成功
    if(NULL == p3)
    {
   
        printf("malloc error.\n");
        return -1;
    }
    //清理这段新申请的空间中的数据
    bzero(p3,sizeof(struct node));
    //同时给结构体中的有效数据赋值
    p3->data = 1;
    p2->pnext = p3;
    p3->pnext = NULL;
}

单链表的算法之插入结点

访问各个结点的数据
(1)只能用头指针,不能用各个结点自己的指针,因为实际上我们保存链表的时候是不会保存各个结点的指针的,只能通过头指针来访问链表节点
(2)前一个节点内部的pnext指针能够帮我们找到下一个节点

printf("node1 data: %d.\n",phead->data);
    printf("p -> data: %d.\n",p->data);

    printf("node1 data: %d.\n",phead->pnext->data);
    printf("p1 -> data: %d.\n",p1->data);

    printf("node1 data: %d.\n",phead->pnext->pnext->data);
    printf("p2 -> data: %d.\n",p2->data);

    printf("node1 data: %d.\n",phead->pnext->pnext->pnext->data);
    printf("p3 -> data: %d.\n",p3->data);

将创建结点的代码封装成函数
(1)封装时的关键点就是函数的接口(函数参数和返回值)的设计

struct node * creat_head(int data)
{
   
    struct node *p = (struct node *)malloc(sizeof(struct
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值