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.结构
  • 创建:创建空白节点即可
  • 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
  • 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址
相关推荐
laplaya8 小时前
使用 vcpkg 管理 C++ 项目中的依赖
开发语言·c++
鹤落晴春8 小时前
RH124问答5:管理本地用户和组
linux·运维·服务器
feixing_fx8 小时前
选择器的威力——深入理解优先级计算与层叠规则
开发语言·前端·css·前端框架·html
其实防守也摸鱼8 小时前
软件安全与漏洞--Windows底层原理与软件逆向工程基础
linux·网络·数据库·算法·安全·安全架构·软件安全与漏洞
6v6-博客8 小时前
C语言字符串中空格的表示方法
c语言·开发语言
geovindu8 小时前
python: speech to text offline
开发语言·python·语音识别
云栖梦泽8 小时前
Linux内核与驱动:pinctl子系统和GPIO子系统
linux·单片机·嵌入式硬件
女神下凡8 小时前
这是 Cursor(Composer) 的五种核心交互模式
服务器·人工智能·windows·vscode·microsoft
于指尖飞舞8 小时前
java后端面试题(多线程极简)
java·开发语言
techdashen8 小时前
从 Windows 的 ping.exe 入手:动态库、调用约定与 Rust FFI
开发语言·windows·rust