从头开始嵌入式第三十八天(数据结构 双向链表)

目录

双向链表

一、结构特点

二、操作优势

三、应用场景

1.创建链表

2.头插数据

3.打印数据

4.查找数据

5.删除数据

6.更改数据

7.清空数据

8.尾插数据

9.按位插入

10.获取长度

11.是否为空


双向链表

双向链表是一种链表结构。

一、结构特点

  1. 每个节点包含两个指针,分别指向直接前驱节点和直接后继节点。这使得在双向链表中可以双向遍历,既可以向前也可以向后查找节点。

  2. 相比单向链表,双向链表在某些操作上更加灵活,比如在删除节点时,可以快速找到前驱节点进行调整,而单向链表需要从头开始遍历才能找到前驱节点。

二、操作优势

  1. 插入操作:可以快速确定插入位置的前后节点,进行指针调整,实现高效的插入操作。

  2. 删除操作:由于能够直接访问前驱节点,删除操作也更加方便快捷。

三、应用场景

  1. 需要频繁进行前后遍历的场景,如文本编辑器中对字符的双向移动和操作。

  2. 对数据的插入和删除操作较多,且要求高效的系统中。

1.创建链表

cs 复制代码
LinkList *CreateLinkList()
{
    LinkList*ll =  (LinkList*)malloc(sizeof(LinkList));
    if(NULL == ll)
    {
        perror("CreateLinkList malloc");
        return NULL;
    }

    ll->head = NULL;
    ll->clen = 0;
    return ll;
}

2.头插数据

cs 复制代码
int InsertHeadLinkList(LinkList *list, DATATYPE *data)
{
    LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
    if(NULL == newnode)
    {
        perror("InsertHeadLinkList malloc");
        return 1;
    }

    memcpy(&newnode->data,data,sizeof(DATATYPE));
    newnode->next = NULL;
    newnode->prev = NULL;

    if(IsEmptyLinkList(list))
    {
        list->head  = newnode;
    }
    else
    {
        newnode->next = list->head;
        list->head->prev = newnode;
        list->head = newnode;
    }

    list->clen++;
    return 0;
}

3.打印数据

cs 复制代码
int ShowLinkList(LinkList *list ,DIRECT dir)
{
    int i=0;
    int len =GetSizeLinkList(list);
    LinkNode* tmp = list->head;
    if(DIR_FORWARD == dir)
    {
        for(i = 0 ;i<len;i++)
        {
            printf("name:%s age:%d score:%d\n",tmp->data.name,tmp->data.age,tmp->data.score);
            tmp=tmp->next;
        }
    }
    else
    {
        while(tmp->next)
        {
            tmp=tmp->next;
        }
        while(tmp)
        {
            printf("name:%s age:%d score:%d\n",tmp->data.name,tmp->data.age,tmp->data.score);
            tmp=tmp->prev;
        }
    }
    return 0;
}

4.查找数据

cs 复制代码
LinkNode *FindLinkList(LinkList *list, char *name)
{
    int len = GetSizeLinkList(list);
       int i = 0 ;
       LinkNode*tmp = list->head;
       for(i = 0 ;i<len;i++)
       {
           if(0==strcmp(tmp->data.name,name))
           {
               return tmp;
           }
           tmp=tmp->next;
       }
       return NULL;
}

5.删除数据

cs 复制代码
int DeleteLinkList(LinkList *list, char *name)
{
    LinkNode*tmp = FindLinkList(list,name);
        if(NULL == tmp)
        {
            return 1;
        }
        if(tmp->next)
        {
            tmp->next->prev=tmp->prev;
        }
        if(tmp->prev)
        {
            tmp->prev->next = tmp->next;
        }
        else
        {
            list->head = tmp->next;
        }
        free(tmp);
        list->clen--;
        return 0;
}

6.更改数据

cs 复制代码
int ModifyLinkList(LinkList *list, char *name, DATATYPE *data)
{
    LinkNode* tmp = FindLinkList(list,name);
        if(NULL == tmp)
        {
            return 1;
        }
        memcpy(&tmp->data,data,sizeof(DATATYPE));
        return 0;
}

7.清空数据

cs 复制代码
int DestroyLinkList(LinkList *list)
{

  LinkNode* tmp = list->head;
  while(tmp)
   {
    list->head= list->head->next;
    free(tmp);
    tmp = list->head;
  }
    free(list);
    return 0;
}

8.尾插数据

cs 复制代码
int InsertTailLinkList(LinkList *list, DATATYPE *data)
{

    if(IsEmptyLinkList(list))
    {
        return InsertHeadLinkList(list,data);
    }
    else
    {

      LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
      if(NULL == newnode)
      {
        perror("inster tail malloc");
        return 1;
      }

      // newnode  init
      memcpy(&newnode->data,data,sizeof(DATATYPE));
        newnode->next = NULL;
        newnode->prev=NULL;
      LinkNode*tmp = list->head;
      while(tmp->next)
       {
        tmp = tmp->next;
         }
      newnode->prev = tmp;
      tmp->next = newnode;
    }
    list->clen++;
    return 0;
}

9.按位插入

cs 复制代码
int InsertPosLinkList(LinkList *list, DATATYPE *data, int pos) {
  int len = GetSizeLinkList(list);
  if (pos < 0 || pos > len) {
    return 1;
  }

  if (0 == pos) {
    return InsertHeadLinkList(list, data);
  } else if (len == pos) {

    return InsertTailLinkList(list, data);
  } else {
    LinkNode *tmp = list->head;
    int i = 0;
    for (i = 0; i < pos - 1; i++) {
      tmp = tmp->next;
    }

    LinkNode *newnode = (LinkNode *)malloc(sizeof(LinkNode));
    if (NULL == newnode) {

      perror("insert pos malloc");
      return 1;
    }
    memcpy(&newnode->data, data, sizeof(DATATYPE));
    newnode->next = NULL;
    newnode->prev = NULL;
    newnode->prev = tmp;
    newnode->next = tmp->next;
    tmp->next->prev = newnode;
    tmp->next = newnode;
  }
  list->clen++;
  return 0;
}

10.获取长度

cs 复制代码
int GetSizeLinkList(LinkList*list)
{
    return list->clen;
}

11.是否为空

cs 复制代码
int IsEmptyLinkList(LinkList*list)
{
    return 0 == list->clen;
}
相关推荐
Linux运维老纪1 分钟前
运维之 Centos7 防火墙(CentOS 7 Firewall for Operations and Maintenance)
linux·安全·centos·云计算·运维开发·火绒
斯普信专业组8 分钟前
Ceph异地数据同步之-RBD异地同步复制(下)
linux·服务器·ceph
counsellor13 分钟前
CentOS 7安装hyperscan
linux·centos·hyperscan
电星托马斯15 分钟前
Linux系统CentOS 6.3安装图文详解
linux·运维·服务器·程序人生·centos
啞謎专家18 分钟前
CentOS中挂载新盘LVM指南:轻松扩展存储空间,解决磁盘容量不足问题
linux·运维·服务器
javaisC25 分钟前
c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
c语言·算法·深度优先
爱爬山的老虎25 分钟前
【面试经典150题】LeetCode121·买卖股票最佳时机
数据结构·算法·leetcode·面试·职场和发展
s_little_monster30 分钟前
【Linux】进程信号的捕捉处理
linux·运维·服务器·经验分享·笔记·学习·学习方法
一大Cpp41 分钟前
Ubuntu与本地用户交流是两种小方法
linux·运维·ubuntu
小王不会写code1 小时前
CentOS 7 镜像源失效解决方案(2025年)
linux·运维·centos