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.结构
  • 创建:创建空白节点即可
  • 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
  • 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址
相关推荐
Yyyy4826 小时前
Ubuntu安装Jenkis
linux·运维·ubuntu
长安第一美人6 小时前
C 语言可变参数(...)实战:从 logger_print 到通用日志函数
c语言·开发语言·嵌入式硬件·日志·工业应用开发
Larry_Yanan6 小时前
Qt多进程(一)进程间通信概括
开发语言·c++·qt·学习
superman超哥7 小时前
仓颉语言中基本数据类型的深度剖析与工程实践
c语言·开发语言·python·算法·仓颉
不爱吃糖的程序媛7 小时前
Ascend C开发工具包(asc-devkit)技术解读
c语言·开发语言
bu_shuo7 小时前
MATLAB奔溃记录
开发语言·matlab
zhuzewennamoamtf7 小时前
Linux SPI设备驱动
android·linux·运维
春日见7 小时前
在虚拟机上面无法正启动机械臂的控制launch文件
linux·运维·服务器·人工智能·驱动开发·ubuntu
你的冰西瓜7 小时前
C++标准模板库(STL)全面解析
开发语言·c++·stl
阿昭L7 小时前
leetcode链表相交
算法·leetcode·链表