带头尾指针的list的C实现

数据结构之---C语言实现广义表头尾链表存储表示 C语言实现广义表头尾链表存储表示 阅读详情

带头尾指针的list的C实现

一、缘起

很早写了一个带头尾指针的list,该list支持从尾部插入元素,在任意位置删除元素,最近用这个list时发现一个bug,修正了,并加了几个接口函数。贴出来,希望对C的初学者有用。

二、基本说明

2.1、数据结构

l         listnode

 

typedef struct listnode

{

    int data;           //you can add any type data here

    int id;

    struct listnode* next;

} *listnode, _listnode;

 

其中data、id用于测试程序,可换成任意数据类型。

l         list

 

typedef struct list

{

    struct listnode* head;

    struct listnode* tail;

    int count;           //0 --empty

    int current_id;

} *list, _list;

 

head、tail均指向实际元素,list为空时,指向NULL,current_id用于测试程序,可去。

2.2、函数说明

l         void list_init(list)

初始化list

l         void list_insert(list, listnode)

list的尾部插入元素

l         int list_delete(list, listnode)

从list上删除指定元素,删除成功返回1,删除失败返回0

l         void list_poll(list myroot)

遍历整个pool,测试用

l         listnode new_listnode(const int id, int data)

构建新的元素,并为其分配内存

l         void delete_listnode(listnode mylistnode)

删除指定元素,并释放其内存

l         listnode find_node_by_data(list myroot, const int data)

根据data在list上查找匹配的元素

l         listnode find_node_by_id(list myroot, const int id)

根据id在list上查找匹配的元素

三、代码

3.1、list.h:

 

/* list.h

** Copyright 2004 Coon Xu.

** Author: Coon Xu

** Date: 02 Feb 2005

*/

 

#ifndef LIST_H

#define LIST_H

#include <stdio.h>

#include <stdlib.h>

 

typedef struct listnode

{

    int data;           //you can add any type data here

    int id;

    struct listnode* next;

} *listnode, _listnode;

 

typedef struct list

{

    struct listnode* head;

    struct listnode* tail;

    int count;           //0 --empty

    int current_id;

} *list, _list;

 

void list_init(list);

void list_insert(list, listnode);

int list_delete(list, listnode);

void list_poll(list myroot);

listnode new_listnode(const int id, int data);

void delete_listnode(listnode mylistnode);

listnode find_node_by_data(list myroot, const int data);

listnode find_node_by_id(list myroot, const int id);

 

#endif

 

3.2、list.c:

 

/* list.c

** Copyright 2004 Coon Xu.

** Author: Coon Xu

** Date: 02 Feb 2005

*/

#include "list.h"

 

void list_init(list myroot)

{

    myroot->count = 0;

    myroot->head = NULL;

    myroot->tail = NULL;

    myroot->current_id = 1;

}

 

void list_poll(list myroot)

{

    printf("-------------------------------------------------------/n");

    listnode p_listnode = myroot->head;

    while(p_listnode != NULL)

    {

        printf("id: %d/t data: %d/n", p_listnode->id, p_listnode->data);

           

        p_listnode = p_listnode->next;

    }

}

 

 

//insert node at the tail

void list_insert(list myroot, listnode mylistnode)

{

    myroot->count++;

   

    mylistnode->next = NULL;

    if(myroot->head == NULL)

    {

        myroot->head = mylistnode;

        myroot->tail = mylistnode;

    }

    else

    {

        myroot->tail->next = mylistnode;

        myroot->tail = mylistnode;

    }   

    printf("[insert]:/tlist.cout:/t%d/n", myroot->count);

}

 

int list_delete(list myroot, listnode mylistnode)

{

    struct listnode* p_listnode = myroot->head;

    struct listnode* pre_listnode;

   

    //myroot is empty

    if(p_listnode == NULL)

    {

        return 0;

    }

 

    //delete head node   

    if(p_listnode == mylistnode)

    {

        myroot->count--;

        //myroot has only one node

        if(myroot->tail == mylistnode)

        {

            myroot->head = NULL;

            myroot->tail = NULL;

        }

        else

        {

            myroot->head = p_listnode->next;

        }

        printf("[delete]:/tlist.cout:/t%d/n", myroot->count);

        return 1;

    }

 

    while(p_listnode != NULL)

    {

        if(p_listnode == mylistnode)

        {

            break;

        }

        pre_listnode = p_listnode;

        p_listnode = p_listnode->next;

    }

    if(p_listnode == NULL)

    {

        printf("can not find the node.../n");

        return 0;

    }

    else

    {

        pre_listnode->next = p_listnode->next;

        if(myroot->tail == p_listnode)

        {

            myroot->tail = pre_listnode;

        }

        myroot->count--;

        printf("[delete]:/tlist.cout:/t%d/n", myroot->count);

        return 1;

    } 

}

 

listnode new_listnode(const int id, int data)

{

    listnode p_listnode = malloc(sizeof(_listnode));

    p_listnode->id = id;

    p_listnode->data = data;

   

    return p_listnode;

}

 

void delete_listnode(listnode mylistnode)

{

    mylistnode->next = NULL;

    free(mylistnode);

    mylistnode = NULL;

}

 

listnode find_node_by_data(list myroot, const int data)

{

    listnode p_listnode = myroot->head;

    while(p_listnode != NULL)

    {

        if( p_listnode->data == data )

        {

            printf("find the node for data: %d/n", data);

            break;

        }

        p_listnode = p_listnode->next;

    }

   

    return p_listnode;

}

 

listnode find_node_by_id(list myroot, const int id)

{

    listnode p_listnode = myroot->head;

    while(p_listnode != NULL)

    {

        if( p_listnode->id == id )

        {

            printf("find the node for id: %d/n", id);

            break;

        }

        p_listnode = p_listnode->next;

    }

   

    return p_listnode;

}

 

 

3.3、附一个测试的主程序

main.c:

 

#include <stdio.h>

#include <stdlib.h>

#include "list.h"

 

int main(int argc, char *argv[])

{

    list mylist = malloc(sizeof(_list));

    list_init(mylist);

    int ix = 0;

    for(ix = 0; ix < 10; ix++)

    {

        listnode my_listnode = new_listnode( (mylist->current_id)++, ix);

        list_insert(mylist, my_listnode);

    }

   

    list_poll(mylist);

   

    //delete head node and test

    listnode my_listnode = find_node_by_id(mylist, 1);

    list_delete(mylist, my_listnode);

    delete_listnode(my_listnode);

    list_poll(mylist);

 

    //insert a node and test

    my_listnode = new_listnode( (mylist->current_id)++, 100);

    list_insert(mylist, my_listnode);

    list_poll(mylist);

 

  

    //delete tail node and test

    my_listnode = find_node_by_id(mylist, 10);

    list_delete(mylist, my_listnode);

    delete_listnode(my_listnode);

    list_poll(mylist);

 

    //insert a node and test

    my_listnode = new_listnode( (mylist->current_id)++, 200);

    list_insert(mylist, my_listnode);

    list_poll(mylist);

 

    //delete a normal node and test   

    my_listnode = find_node_by_data(mylist, 6);

    list_delete(mylist, my_listnode);

    delete_listnode(my_listnode);

    list_poll(mylist);

 

    //insert a node and test

    my_listnode = new_listnode( (mylist->current_id)++, 300);

    list_insert(mylist, my_listnode);

    list_poll(mylist);

 

    //delete head node again and test   

    my_listnode = find_node_by_id(mylist, 2);

    list_delete(mylist, my_listnode);

    delete_listnode(my_listnode);

    list_poll(mylist);

 

    //insert a node and test 

    my_listnode = new_listnode( (mylist->current_id)++, 400);

    list_insert(mylist, my_listnode);

    list_poll(mylist);

   

  system("PAUSE"); 

  return 0;

}

 

 

FPGA进位链(Carry Chain)实战:从Xilinx CARRY8原语到性能优化全解析 本文深入解析了FPGA进位链(Carry Chain)的原理与应用,重点剖析了Xilinx CARRY8原语的端口功能与内部机制。通过实测数据揭示了进位链的真实延迟特性与温度影响,并详细阐述了如何利用DI和S信号进行动态路径优化、实现减法运算与条件进位选择,从而有效提升设计性能。最后,文章探讨了系统级的流水线拆分、布局约束等实战优化策略与常见陷阱。 阅读详情

相关推荐

【KITTI数据集中Raw_Data数据标定文件中的参数关系解读】

上一节本人将KITTI Odometry数据集中的参数文件进行了解释。本节主要针对一些做融合slam的人,将Raw_Data数据标定文件中的参数按照自己的理解做如下阐述。其中,所讲之处如有错误,欢迎各位批评指正。

weixin_43389152的博客 1526

一个简单的带头尾指针单向链表(C实现)

        用C写了一个带头尾指针的单向链表,仅在尾部进行插入操作,在任意位置进行删除操作。因为只用到这么些功能,又因为懒,所以没有扩展。因为插入是固定在尾部进行,带一个尾指针的好处是显而易见的。当然删除时要付出一些开销。list.h-------------------------------------------/* list.h** Copyright 2004 Coon

1270

USB PD快充功率监测仪:高精度嵌入式USB电压电流测量终端

USB供电已从数据接口演进为关键电源总线,尤其在PD快充场景下,工程师亟需对5V–20V宽压范围内的实时电压、电流及瞬时功率进行精准捕获。其底层原理依赖高共模抑制比的高边电流检测与分压采样+ADC数字化处理,结合LDO低噪声供电保障模拟链路精度。该类设备的技术价值在于以低成本实现协议无关的‘电气层可视化’,规避商用ASIC测试仪的黑盒局限,支撑PD充电验证、电源设计调试与教学实验等工程实践。本文介绍的开源USB表即基于N32G430 MCU与INA199电流检测芯片,覆盖USB-C输入/输出双通道监测,具备

weixin_42174098的博客 207

C语言实现带头指针的单向链表库

该链表库比较简单,链表节点数据为整型,因为这只是为了模拟链表的原理,实际中一般不会使用单向链表来储存数据,链表头为一个指针。整个库包含两个文件:SingleList.h 和 SingleList.c SingleList.h /*******************************************************************************...

王廷云的博客 1045

团结引擎+OpenHarmony 2实战篇:从零构建鸿蒙应用开发环境

本文详细介绍了如何从零开始构建鸿蒙应用开发环境,重点讲解了团结引擎与OpenHarmony 2的实战配置步骤。内容包括DevEco Studio安装、OpenHarmony SDK配置、团结引擎集成及项目创建等关键环节,帮助开发者快速搭建高效的开发环境,提升鸿蒙应用开发效率。

weixin_29294395的博客 264

weblogic 集群搭建,双机部署,相关问题记录

4.5.集群搭建1 参考网址https://wenku.baidu.com/view/76365129cd1755270722192e453610661ed95aa4.html IP地址 端口 角色 192.168.1.160 9001 AdminServer ...

zl386119974的专栏 1669

(转)一个简单的带头尾指针单向链表(C实现)

用C写了一个带头尾指针的单向链表,仅在尾部进行插入操作,在任意位置进行删除操作。因为只用到这么些功能,又因为懒,所以没有扩展。因为插入是固定在尾部进行,带一个尾指针的好处是显而易见的。当然删除时要付出一些开销。  list.h  -------------------------------------------  /* list.h  ** Copyright 2004 Coon Xu.  *

684

OpenCV图像去畸变实战指南:从原理到参数调优(附完整代码与效果对比)

本文深入解析了OpenCV图像去畸变的原理与实战技巧,详细对比了标准透视、鱼眼及全能型omnidir三种校正函数的核心参数调优方法。通过分析alpha、balance、centerX/Y及focalScale四大参数对输出效果的影响,并结合完整代码与效果对比图,帮助开发者精准校正镜头畸变,提升计算机视觉任务精度。

weixin_29046611的博客 341

C++_list简单源码剖析:list模拟实现

->

Lvision2的博客 1481

疫情数据分析的“核武器”!JHU CSSE COVID-19数据集超深度解析与实战指南(附代码)

在面对这场没有硝烟的战争时,除了医护人员在前线与病毒搏斗,还有一群默默的英雄——数据科学家和分析师,他们利用手中的“数据武器”,昼夜不停地监测、分析、预测疫情走势,为政府决策、资源调配、公众科普提供了至关重要的支撑。同时,由于某些国家(如美国、加拿大、澳大利亚、中国等)的数据细化到省/州级别,为了得到国家层面的总数据,我们需要按国家和日期进行聚合。正是在这样的背景下,经过这些步骤,我们已经得到了一个包含了累计数据、每日新增数据和活跃病例数的完整数据集,可以开始进行深入的分析和可视化了!

wylee的博客 1165

STM32实战:手把手教你移植CanFestival协议栈(附完整代码)

本文提供了一份详尽的STM32平台移植CanFestival协议栈的实战指南。文章从工程搭建、定时器驱动、CAN硬件适配到对象字典配置,手把手讲解核心步骤,并附完整代码示例。重点剖析了时间管理、报文收发等关键环节的实现与常见问题解决方案,旨在帮助开发者深入理解并成功实现CANopen通信。

kiwi8的博客 274

十一、第10章 手搓算法(3) 双向链表 支持头尾遍历、排序、增删、正负数索引、查找(C语言高级应用篇 )

本文介绍了手搓算法中双链库的设计与实现。重点讲解了侵入式链表结构的设计理念,通过将链表节点嵌入自定义数据结构实现类型无关性。文章详细说明了链表管理器的设计思路,包括初始化函数、数据获取函数的接口定义,特别强调了二级指针在节点读取中的关键作用。同时,针对函数接口易用性问题,提出了优化方案,将节点获取从参数改为返回值,简化调用方式。最后指出学习此内容可提升C语言编程能力,掌握双向链表、接口设计、错误处理等核心技能。

神圣的大喵的博客 488

电源防反接保护电路全攻略实战A04

本文深入剖析了硬件设计中电源保护电路的关键技术与实战经验。文章指出,保护电路虽小但至关重要,通过对比分析二极管与MOSFET防反接方案,揭示了MOSFET在效率、温控方面的优势。针对过压保护,重点讲解了TVS二极管选型要点,强调钳位电压而非击穿电压才是保护核心。文章结合工业案例(如48V通信模块烧毁、5V系统MOSFET过热等),详细阐述了PCB布局规范、热设计路径等工程细节,并提供了USB接口ESD防护的完整选型方案。最后强调硬件设计必须考虑最坏工况,在成本与性能间找到平衡点,避免因小失大。

启芯硬件的博客 777

list(C++)的实现

list(C++)的实现

2302_80190394的博客 1117

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

广义表 GL 采用头尾表示存储,设计一个算法,求 GL 的长度。

广义表 GL 采用头尾表示存储,设计一个算法,求 GL 的长度。 源代码: #include <stdio.h> #include <stdlib.h> typedef struct GLNode{ int tag;//公共部分,用于区分原子节点和表结点 union{ char atom;//atom原子结点的值域 str...

weixin_45963815的博客 772

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【链表】Reversing Linked List

Reversing Linked List 题目要求: Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5.

百栗.的博客 1152

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【数据结构】_C语言实现带头双向循环链表

本文介绍带头双向循环链表(简称双链表)。

m0_63299495的博客 1571

广义表的头尾链表存储表示(2)(第五章 P115 算法5.5,5.6,5.8)

下图是根据上方程序定义的广义表(a,(b,c,d))的存储结构。它的长度为2,第1 个元素为原子 a,第2个元素为子表(b,c,d)。 完整代码: 下面代码中广义表的书写形式串为HString类型,广义表的书写形式串为SString类型的请转看:https://blog.youkuaiyun.com/qq_42185999/article/details/105670079 ...

但行好事,莫问前程 1786

(C语言!)广义表(头尾链表)的建立和输出

un;}*Glist;这里懒得加注释了。

npu2022303155的博客 1087

广义表的头尾链表存储表示(第五章 P115 算法5.5,5.6,5.8)

/* 广义表的头尾链表存储表示 */ typedef enum{ATOM,LIST}ElemTag; /* ATOM==0:原子,LIST==1:子表 */ typedef struct GLNode { ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */ union /* 原子结点和表结点的联合部分 */ { AtomTyp...

但行好事,莫问前程 1962

对于模拟实现C++list类的详细解析—下

本文详细介绍了如何用C++模拟实现STL中的list双向带头链表。作者从节点类、迭代器类到list类本身,逐步拆解了各个模块的设计与实现,重点讲解了哨兵节点的作用、迭代器运算符重载、插入删除操作等核心逻辑。通过复用insert/erase函数简化了push/pop等接口,并深入分析了深拷贝、迭代器失效等关键问题。文章不仅提供了完整的实现代码,还分享了作者在开发过程中的思考与感悟,强调了"从使用者到设计者"的思维转变,以及"拆解复杂问题"的能力培养。

2503_92929084的博客 997

面试官:说说Redis的List类型的底层结构

前言 Redis的 List 数据类型,作为一种数据类型,它的底层实现是链表,由于 Redis 使用的C语言没有内置这种数据结构,所以 Redis构建了自己的链表实现。 List类型的结构就是链表,链表中的每个节点都保存了一个值。除了链表键之外,发布与订阅、慢查询、监视器等功能也用到了链表,Redis服务器本身还使用链表来保存多个客户端的状态信息,以及使用链表来构建客户端输出缓冲区( output buffer ),本文将对Redis的链表进行介绍。 链表 每个链表使用一个 listNode 结构来表示:

沸羊羊_ 905

链表操作效率翻倍:尾指针在C语言中的实战应用(附完整代码)

本文深入探讨了在C语言链表中引入尾指针(Tail Pointer)如何将尾部插入操作的效率从O(n)提升至O(1)。通过对比分析、完整可运行的代码示例及性能测试,详细展示了尾指针的原理、实现细节、边界条件处理及其在队列等场景下的实战应用,为优化数据结构操作提供了有效方案。

pear55的博客 489

C++ List容器底层实现大揭秘

详细介绍了手写STL中List容器的实现过程。文章首先分析了List的底层结构——带头双向循环链表,并解释了节点结构的设计要点。随后重点讲解了迭代器的实现原理,通过封装节点指针和运算符重载解决了链表迭代器的特殊性问题。文章还详细阐述了List核心功能的实现,包括尾插(push_back)、任意位置插入(insert)、删除(erase)等操作,并提供了深拷贝、析构函数等重要成员函数的实现方法。最后,文章探讨了const迭代器的设计策略,通过模板参数控制返回类型,实现了普通迭代器和const迭代器的统一处理。

2302_80761497的博客 1248

C语言指针与链表实战:从内存管理到链式栈、队列的完整实现

指针是C/C++中访问和操作内存的核心机制,它存储变量的地址,实现了对内存的间接访问。理解指针与内存的关系,是掌握动态内存分配和构建复杂数据结构的基础。通过malloc和free进行动态内存管理,程序可以在运行时灵活申请和释放内存,这为构建链表、栈、队列等动态数据结构提供了可能。链表作为基础数据结构,通过节点和指针实现了数据的非连续存储,解决了数组大小固定、插入删除效率低的问题。基于链表的链式栈和链式队列,则分别遵循LIFO(后进先出)和FIFO(先进先出)原则,广泛应用于函数调用、表达式求值、消息队列等场

weixin_30883311的博客 435

手撕 STL 之—— list

手撕STL——list

aaaaa_shen的博客 1110
上一篇: 通过find+exec 删除指定时间生成的文件
下一篇: linux下字符集编码转换轻松实现(ZZ)
kunp
博客等级 码龄24年 48粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值