当前位置: 首页 > news >正文

自学嵌入式 day20-数据结构 链表

注:gdb调试工具用法

3.链表的常规操作

(6)尾部插入

int InsertTailLinkList(LinkList* ll, DATATYPE* data)
{
  if (IsEmptyLinkList(ll))//判断链表是否为空
    {
      return InsertHeadLinkList(ll, data);
    }
  else
    {
      LinkNode* newnode = malloc(sizeof(LinkNode));//定义一个新结点,并申请空间
      if (NULL == newnode)//判断空间是否申请成功
        {
          fprintf(stderr, "InsertTailLinkList malloc");
          return 1;
        }

      memcpy(&newnode->data, data, sizeof(DATATYPE));//将data复制到新结点
      newnode->next = NULL;//将新结点下一位指向空指针

      LinkNode* tmp = ll->head;//定义新结点并指向头指针
      while (tmp->next)//遍历链表
        {
          tmp = tmp->next;  // tmp++;
        }
      tmp->next = newnode;//将新结点接在链表的尾部
      ll->clen++;
    }
  return 0;
}

(7)按指定位置插入

int InsertPosLinkList(LinkList* ll, DATATYPE* data, int pos)
{
  int len = GetSizeLinkList(ll);//获得链表的长度

  if (pos < 0 || pos > len)//判断输入位置是否正确
    {
      return 1;
    }
  if (0 == pos)  // 头部插入
    {
      return InsertHeadLinkList(ll, data);
    }
  else if (pos == len)  // 尾部插入
    {
      return InsertTailLinkList(ll, data);
    }
  else
    {
      LinkNode* newnode = malloc(sizeof(LinkNode));//定义并申请新结点的空间
      if (NULL == newnode)//判断空间是否申请成功
        {
          fprintf(stderr, "InsertPosLinkList malloc");
          return 1;
        }
      memcpy(&newnode->data, data, sizeof(DATATYPE));
      newnode->next = NULL;
      int i = 0;
      LinkNode* tmp = ll->head;
      for (i = 0; i < pos - 1; ++i)//定位需插入的指定位置
        {
          tmp = tmp->next;
        }
      newnode->next = tmp->next;//将新结点连接在指定位置前后
      tmp->next = newnode;
    }
  ll->clen++;
  return 0;
}

(8)销毁

int DestroyLinkList(LinkList **ll)
{
    while(1)
    {
        LinkNode *tmp = (*ll) -> head;
        if(NULL == tmp)
        {
            break;
        }
        (*ll) -> head = (*ll) -> head -> next;
        free(tmp);
    }
    free(*ll);
    *ll = NULL;
    return 0;
}
 

(9)找中间结点

LinkNode *MidFindLinkList(LinkList *ll)
{
    LinkNode *slow = ll -> head;//定义新指针,指向头指针
    LinkNode *fast = ll -> head;//定义新指针,指向头指针
    while(fast)//每次循环fast结点向后移2位,slow结点向后移1位,fast位移距离是slow的两倍
    {
        fast = fast -> next;
        if(NULL == fast)
        {
            break;
        }
        fast = fast -> next;
        slow = slow -> next;
    }
    return slow;//slow所处位置即链表中间位置
}

(10)查找倒数第k个结点

LinkNode *LaskFindLinkList(LinkList *ll,int k)
{
    LinkNode *slow = ll -> head;
    LinkNode *fast = ll -> head;
    for(int i = 0;i < k;++i)//让fast从制定k处结点开始向后移动
    {
        fast = fast ->next;
    }
    while(fast)
    {
        fast = fast -> next;
        slow = slow -> next;
    }
    return slow;//slow所处结点即倒数第k结点
}

(11)链表的逆序

int RevertLinkList(LinkList *ll)
{
    LinkNode *prev = NULL;//定义一个指向被逆转结点的指针,初始为空指针
    LinkNode *tmp = ll -> head;//定义一个指向待逆转结点的指针
    LinkNode *next = ll -> head -> next;//定义待逆转节点next指向的指针
    int len = GetSizeLinkList(ll);
    if(len < 2)//逆序链表长度必须大于1
    {
        return 1;
    }
    while(1)
    {
        tmp -> next = prev;//将待逆转结点指向被逆转节点
        prev = tmp;//prev++
        tmp = next;//tmp++
        if(NULL == tmp)//判断tmp是否是空指针
        {
            break;
        }
        next = next -> next;//next++

    }
    ll -> head = prev;//将头指针指向以逆转的链表首位
    return 0;
}

练习:

(1)链表的排序

int InsertSortLinkList(LinkList* ll)
{
    LinkNode *pins = ll -> head;//定义一个指针指向头指针,代表已排序的链表
    LinkNode *ptmp = pins -> next;//定义一个指针指向pins->next,代表需要排序的链表
    LinkNode *next = ptmp -> next;//定义一个指针指向ptmp->next,协助遍历需要排序的结点
    ptmp -> next = NULL;//提取需要排序的结点
    ll -> head -> next = NULL;//协助首次遍历已排序的链表
    while(1)
    {
        pins = ll -> head;
        while(pins -> next && ptmp -> data.age >pins -> data.age && ptmp -> data.age > pins ->next -> data.age)//遍历已排序的链表,并使pins指向待排序结点连接的正确的位置
        {
            pins = pins -> next;
        }
        if(pins -> data.age > ptmp -> data.age)//首插
        {
            ptmp -> next = ll -> head;
            ll -> head = ptmp;
        }
        else//将结点插入pins指向的结点和pins ->next指向的结点
        {
            ptmp -> next = pins -> next;
            pins -> next = ptmp;
        }

        ptmp = next;//遍历需排序的结点
        if(NULL == ptmp)//循环终止条件
        {
            break;
        }
        next = next -> next;
         ptmp -> next = NULL;//提出需排序的结点
    }
}

(2)判断链表是否有环

int IsRingLinkList(LinkList*ll)
{
    LinkNode* fast = ll->head;
    LinkNode * slow =ll->head;

    while(fast)
    {
        fast  =fast->next;
        if(NULL == fast)
        {
            return 0;;
        }

        if(slow == fast)
        {
            return 1;
        }
        fast =fast->next;
        slow = slow->next;


    }
    return 0;
}

http://www.xdnf.cn/news/524143.html

相关文章:

  • Ubuntu服务器部署多语言项目(Node.js/Python)方式实践
  • 【android bluetooth 协议分析 01】【HCI 层介绍 7】【ReadLocalName命令介绍】
  • day53—二分法—搜索旋转排序数组(LeetCode-81)
  • Java 后端基础 Maven
  • 2024CCPC吉林省赛长春邀请赛 Java 做题记录
  • 软件设计师“UML”真题考点分析——求三连
  • 在linux里上传本地项目到github中
  • ORPO:让大模型调优更简单高效的新范式
  • R语言+贝叶斯网络:涵盖贝叶斯网络的基础、离散与连续分布、混合网络、动态网络,Gephi可视化,助你成为数据分析高手!
  • Grafana之Dashboard(仪表盘)
  • ThreadLocal作一个缓存工具类
  • 【聚类】层次聚类
  • 三键标准、多键usb鼠标数据格式
  • 从产品展示到工程设计:3DXML 转 STP 的跨流程数据转换技术解析
  • WPF中的ObjectDataProvider:用于数据绑定的数据源之一
  • Regmap子系统之六轴传感器驱动-编写icm20607.c驱动
  • 【云实验】Excel文件转存到RDS数据库
  • 【大数据】MapReduce 编程--索引倒排--根据“内容 ➜ 出现在哪些文件里(某个单词出现在了哪些文件中,以及在每个文件中出现了多少次)
  • .NET 函数:检测 SQL 注入风险
  • 关于能管-虚拟电厂的概述
  • Win10 安装单机版ES(elasticsearch),整合IK分词器和安装Kibana
  • 【android bluetooth 协议分析 01】【HCI 层介绍 8】【ReadLocalVersionInformation命令介绍】
  • 【Android构建系统】Soong构建系统,通过.bp + .go定制编译
  • MySQL 故障排查与生产环境优化
  • verify_ssl 与 Token 验证的区别详解
  • Node 服务监控及通过钉钉推送告警提醒
  • 3.安卓逆向2-安卓文件目录
  • WPF点击按钮弹出一个窗口
  • 深入理解 Hadoop 核心组件 Yarn:架构、配置与实战
  • 物联网简介:万物互联的未来图景