Linux学习-数据结构(链表)

1.双向链表

1.空链表的创建

参考单向链表

cs 复制代码
linknode *creat_empty_doulist(void)
{
    linknode *ptmpnode = NULL;

    ptmpnode = malloc(sizeof(linknode));
    if(NULL == ptmpnode)
    {
        perror("fail to malloc");
        return NULL;
    }

    ptmpnode->pnext = NULL;
    ptmpnode->ppre = NULL;

    return ptmpnode;
}

2.头插法插入节点

参考单向链表

cs 复制代码
int insert_head_doulist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;
    //申请空间
    ptmpnode = malloc(sizeof(linknode));

    if(NULL == ptmpnode)
    {
        perror("fail to malloc");
        return -1;
    }

    ptmpnode->data = tmpdata;
    ptmpnode->pnext = phead->pnext;
    ptmpnode->ppre = phead;

    phead->pnext = ptmpnode;

    if(ptmpnode->pnext != NULL)
    {
       ptmpnode->pnext->ppre == ptmpnode;
    }
    
    return 0;
}

3.链表的遍历

参考单向链表

cs 复制代码
int show_doulist(linknode *phead)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode != NULL)
    {
        printf("%d ", ptmpnode->data);
        ptmpnode = ptmpnode->pnext;
    }
    printf("\n");
    return 0;
}

4.链表的查询

参考单向链表

cs 复制代码
linknode *find_doulist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;

    while(ptmpnode->data != tmpdata)
    {
        if(ptmpnode == NULL || ptmpnode->pnext == NULL)
        {
            return NULL;
        }
        ptmpnode = ptmpnode->pnext;
    }

    return ptmpnode;
}

5.链表的修改

cs 复制代码
int update_doulist(linknode *phead, datatype olddata, datatype newdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode->data != olddata)
    {
        if(ptmpnode == NULL || ptmpnode->pnext == NULL)
        {
            return 0;
        }
        ptmpnode = ptmpnode->pnext;
    }
    ptmpnode->data = newdata;

    return 0;
}

6.链表的删除

  • 找到要删除的节点
  • 让删除的节点的前一个节点的pnext等于要删除节点的后一个节点的地址
  • 让删除的节点的后一个节点的ppre等于要删除节点的前一个节点的地址
  • 释放删除的节点
cs 复制代码
int delete_doulist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;
    linknode *pfreenode = NULL;

    ptmpnode = phead->pnext;

    while(ptmpnode != NULL)
    {
        if(ptmpnode->data == tmpdata)
        {   
            ptmpnode->ppre->pnext = ptmpnode->pnext; 
            if(ptmpnode->pnext != NULL)
            {
                ptmpnode->pnext->ppre = ptmpnode->ppre;     
            }
            pfreenode = ptmpnode;
            ptmpnode = ptmpnode->pnext;
            free(pfreenode);
        }
        else
        {
            ptmpnode = ptmpnode->pnext;
        }
        
    }

    return 0;
}

7.链表的销毁

cs 复制代码
int destroy_doulist(linknode **pphead)
{
    linknode *ptmpnode = NULL;
    linknode *pfreenode = NULL;

    ptmpnode = *pphead;
    pfreenode = *pphead;

    while(pfreenode != NULL)
    {
        ptmpnode = ptmpnode->pnext;
        free(pfreenode);
        pfreenode = ptmpnode;
    }

    *pphead = NULL;

    return 0;
}

8.链表的尾插法

cs 复制代码
int insert_last_doulist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;
    linknode *pinsertnode = NULL;

    pinsertnode = malloc(sizeof(linknode));
    if(pinsertnode == NULL)
    {
        perror("fail to malloc");
        return -1;
    }

    ptmpnode = phead->pnext;
    while(ptmpnode->pnext != NULL)
    {
        ptmpnode = ptmpnode->pnext;
    }
    pinsertnode->ppre = ptmpnode;
    pinsertnode->data = tmpdata;
    pinsertnode->pnext = NULL;
    ptmpnode->pnext = pinsertnode;

    return 0;
}

2.循环链表

1.特点

  • 头节点的ppre指向链表的最后一个节点
  • 最后节点的pnext指向链表的第一个节点
    2.节点定义

与双向链表保持一致

cs 复制代码
typedef int datatype;

typedef struct node
{
    datatype data;
    struct node *ppre;
    struct node *pnext;
}linknode;

3.链表创建

cs 复制代码
linknode *creat_cirlist(void)
{
    linknode *ptmpnode = NULL;

    ptmpnode = malloc(sizeof(linknode));
    if(ptmpnode == NULL)
    {
        perror("fail to malloc");
        return NULL;
    }

    ptmpnode->pnext = ptmpnode;
    ptmpnode->ppre = ptmpnode;

    return ptmpnode;
}

4.链表的头插法

  • 申请空间
  • 存放数据
  • 将pnext赋值为空白节点的pnext
  • 将ppre指向前面的节点
  • 将前面的节点的pnext指向新申请的节点
  • 将空白节点的ppre指向新申请的节点
cs 复制代码
int insert_head_cirlist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = malloc(sizeof(linknode));
    if(ptmpnode == NULL)
    {
        perror("fail to malloc");
        return -1;
    }

    ptmpnode->data = tmpdata;
    ptmpnode->pnext = phead->pnext;
    ptmpnode->ppre = phead;
    ptmpnode->ppre->pnext = ptmpnode;
    ptmpnode->pnext->ppre = ptmpnode;

    return 0;
}

5.链表的尾插法

cs 复制代码
int insert_tail_cirlist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = malloc(sizeof(linknode));
    if(ptmpnode == NULL)
    {
        perror("fail to malloc");
        return -1;
    }

    ptmpnode->data = tmpdata;
    ptmpnode->pnext = phead;
    ptmpnode->ppre = phead->ppre;
    ptmpnode->ppre->pnext = ptmpnode;
    ptmpnode->pnext->ppre = ptmpnode;

    return 0;
}

6.链表的遍历

cs 复制代码
int show_cirlist(linknode *phead)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode != phead)
    {
        printf("%d ",ptmpnode->data);
        ptmpnode = ptmpnode->pnext;
    }
    printf("\n");

    return 0;
}

7.链表的查找

cs 复制代码
linknode *find_cirlist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode != phead)
    {
        if(ptmpnode->data == tmpdata)
        {
            return ptmpnode;
        }
        ptmpnode = ptmpnode->pnext;
    }

    return NULL;
}

8.链表的修改

cs 复制代码
int update_cirlist(linknode *phead, datatype olddata, datatype newdata)
{
    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode != phead)
    {
        if(ptmpnode->data == olddata)
        {
            ptmpnode->data = newdata;
        }
        ptmpnode = ptmpnode->pnext;
    }

    return 0;
}

9.链表的删除

cs 复制代码
int delete_tmpdata_cirlist(linknode *phead, datatype tmpdata)
{
    linknode *ptmpnode = NULL;
    linknode *pfreenode = NULL;

    ptmpnode = phead->pnext;
    while(ptmpnode != phead)
    {
        if(ptmpnode->data == tmpdata)
        {
            ptmpnode->ppre->pnext = ptmpnode->pnext;
            ptmpnode->pnext->ppre = ptmpnode->ppre;
            pfreenode = ptmpnode;
            ptmpnode = ptmpnode->pnext;
            free(pfreenode);
        }
        else
        {
            ptmpnode = ptmpnode->pnext;
        } 
    }

    return 0;
}

10.链表的销毁

cs 复制代码
int destroy_cirlist(linknode **pphead)
{
    linknode *ptmpnode = NULL;
    linknode *pfreenode = NULL;

    ptmpnode = (*pphead)->pnext;
    pfreenode = (*pphead)->pnext;

    while(ptmpnode != *pphead)
    {
        ptmpnode = ptmpnode->pnext;
        free(pfreenode);
        pfreenode = ptmpnode;
    }
    free(*pphead);
    *pphead = NULL;

    return 0;
}

3.内核链表

1.概念

  • Linux内核中所使用的一种链表结构
  • 使用同一种结构可以存放不同类型的链表
  • 普通链表:链表节点中包含数据
  • 内核链表:数据中包含链表节点
    2.结构
  • 创建:创建空白节点即可
  • 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
  • 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址
相关推荐
hkhkhkhkh1233 分钟前
Git push 失败(remote unpack failed: Missing tree)解决方案
linux·git
Eloudy3 分钟前
制作 Bash Shell 方式的软件发布安装包的原理和方法
linux·bash
霖.2415 分钟前
K8s实践中的重点知识
linux·云原生·kubernetes
truesnow19 分钟前
速通 awk:一篇文章带你理解 awk 原理,大量实战案例让你马上成为 awk 专家
linux
Lyre丶1 小时前
Ubuntu 24.04 LTS 安装GAMIT
linux·经验分享·学习·ubuntu·gamit
namekong81 小时前
ubuntu 通过下面几种方式查看系统 重启时间/开机时间:
linux·运维·ubuntu
qiu_zhongya1 小时前
iree 用C++来运行Qwen 2.5 0.5b
开发语言·c++·人工智能
汪宁宇1 小时前
giflib5.2.2 在Qt与VS C++中实现Gif缩放示例
开发语言·c++·qt
啊?啊?1 小时前
C/C++练手小项目之倒计时与下载进度条模拟
c语言·开发语言·c++
爱奥尼欧1 小时前
【Linux】网络部分——网络基础(协议与网络传输)
linux·网络·arm开发