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.结构
  • 创建:创建空白节点即可
  • 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
  • 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址
相关推荐
xfmtznfl2165pv14 分钟前
如何在VSCode中设置工作区特定的选项?
ide·vscode·编辑器
菜鸟祥哥20 分钟前
xfs文件系统磁盘损坏修复
linux
Y淑滢潇潇26 分钟前
RHCE Day2 时间管理服务器 NFS服务器
linux·运维·服务器
mit6.82427 分钟前
一些C++的学习资料备忘
开发语言·c++
Adellle31 分钟前
Java中同步和异步的区别,以及阻塞和非阻塞的区别
java·开发语言
铭哥的编程日记34 分钟前
【Linux网络】五种IO模型与非阻塞IO
linux·服务器·网络·tcp/ip·udp
闲人编程36 分钟前
用Python分析你的Spotify/网易云音乐听歌数据
开发语言·python·ai·数据分析·spotify·网易云·codecapsule
Js_cold1 小时前
(* MARK_DEBUG=“true“ *)
开发语言·fpga开发·debug·verilog·vivado
snakecy1 小时前
二叉树、动态规划与链表学习
学习·链表·动态规划
Mr.H01271 小时前
快速排序的常见构思
数据结构·算法