带头尾指针的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;

}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gmapping——从原理到实践

概述 在SLAM中&#xff0c;机器人位姿和地图都是状态变量&#xff0c;我们需要同时对这两个状态变量进行估计&#xff0c;即机器人获得一张环境地图的同时确定自己相对于该地图的位置。我们用x表示机器人状态&#xff0c;m表示环境地图&#xff0c;z表示传感器观测情况&#xf…

关于git分支

1.关于git分支 git的“分支”乍一听是一个特别容易让人产生错觉的概念&#xff0c;以为它和树枝一样是分叉的枝节&#xff0c;其实Git中的分支本质上是个指向commit对象的指针,每次commit&#xff0c;git都把它们串成一条时间线&#xff0c;这条时间线就是一个分支。 2.直接切换…

【机器学习经典算法源码分析系列】-- 逻辑回归

1.逻辑回归&#xff08;Logistic Regression&#xff09;又常被成为“逻辑斯蒂回归”&#xff0c;实质上是一个二元分类问题。 逻辑回归代价函数&#xff1a; 代价函数导数&#xff1a; Matlab实现&#xff1a; 采用matlab中自带的无约束最小化函数fminunc来代替梯度下降法&…

求特殊自然数

总时间限制: 1000ms 内存限制: 65536kB 描述一个十进制自然数,它的七进制与九进制表示都是三位数&#xff0c;且七进制与九进制的三位数码表示顺序正好相反。编程求此自然数,并输出显示。 输入无。输出三行&#xff1a;第一行是此自然数的十进制表示&#xff1b;第一行是此自然…

ROS——不同版本间ROS进行通信

在相同版本间的ROS进行通信不在赘述了&#xff0c;修改/etc/hosts文件即可。 最近项目遇到在Ubuntu16.04 与Ubuntu18.04两个系统间进行ROS通信&#xff0c;ROS版本分别为Kinetic和Melodic。配置网络后&#xff0c;两边都能够ping通&#xff0c;但是在获取ros数据是&#xff0c…

大数据开发实战:数据流图及相关数据技术

1、大数据流程图 2、大数据各个环节主要技术 2.1、数据处理主要技术 Sqoop&#xff1a;&#xff08;发音&#xff1a;skup&#xff09;作为一款开源的离线数据传输工具&#xff0c;主要用于Hadoop(Hive) 与传统数据库&#xff08;MySql,PostgreSQL&#xff09;间的数据传递。它…

oracle 中时间类型 date 与 long 互转

我们在保存时间到数据库时&#xff0c;有时候会保存long型的数据&#xff0c;固定长度是13位&#xff0c;是用当前时间减去1970-01-01&#xff0c;再换算成毫秒得到的结果。 但是要考虑到时区问题中国的时区时8区所以时间要加上8小时 oracle中的实现方式&#xff1a; ---------…

Linux对包管理阐述

Centos/Redhat/Fedora的软件包&#xff0c;都是rpm后缀的文件。包管理器rpm(Redhat packages manager) linux的哲学思想是简单命令解决复杂任务&#xff0c;因此每个软件的功能较单一&#xff0c;所以各种包之间有着复杂的依赖关系&#xff0c;为了解决这种可以使用前端工具&am…

跨时钟域电路设计——亚稳态及双锁存器

一、同步电路 定义&#xff1a;电路中所有受时钟控制的单元&#xff0c;全部由一个统一的时钟控制。 优点&#xff1a;在同步设计中&#xff0c;EDA工具可以保证电路系统的时序收敛&#xff0c;避免电路设计中的竞争冒险。 缺点&#xff1a;时钟树综合需要加入大量延迟单元&…

linux setsockopt详解

1.closesocket&#xff08;一般不会立即关闭而经历TIME_WAIT的过程&#xff09;后想继续重用该socket&#xff1a; BOOL bReuseaddrTRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已经处于连接状态的soket在调用closes…

[TOOLS] 移动端调试进行时 - whistle

1、本地安装、启动whistle 安装实操请查看官方文档不赘述 复制代码 2、手机设置代理 实操请查看官方文档 !!!注意&#xff1a;代理ip填写whistle右上角online选项中的ip 复制代码 3、whistle上设置对应rules、weinre whistle设置代理(!!!注意支持tunnel协议)&#xff1a; rules…

函数动态参数实现format

变量赋值一种是字符串格式化&#xff0c;一种是通过format的方式 1.字符串格式化 s"i am %s,age %d"%(Jasper,23)print(s)打印输出&#xff1a;i am Jasper,age 232.format格式化 s"i am {name},age {age}".format(namejasper,age23)print(s)或 s2"i …

跨时钟域电路设计——单bit信号

前面提到了简单的双电平锁存器&#xff0c;下面是一些单bit同步电路。 一、慢时钟域向快时钟域 边沿检测同步器 将慢时钟域的脉冲搬移并缩小为快时钟域的脉冲。 既可以检测上升沿&#xff0c;也可以检测下降沿。 如上图&#xff0c;慢时钟下一个有效脉冲的最短周期为慢时钟的…

数据同步 rsync+notify架构

rsync 同步命令&#xff0c;非常好用 notify是监控本地文件的变化的 、安装配置 1. 安装rsync&#xff0c;inotify-tools sudo apt-get install rsync inotify-tools 2. 拷贝rsync配置文件 mkdir /etc/rsync cp /usr/share/doc/rsync/examples/rsyncd.conf /etc/rsync/ 3. 服…

OC_KVC与KVO简单介绍

KVC KVC概述 KVC 即 Key-value coding 键值编码&#xff0c;是指iOS的开发中&#xff0c;可以允许开发者通过Key名直接访问对象的属性&#xff0c;或者给对象的属性赋值。 KVC案例 interface Person : NSObjectproperty (nonatomic,assign) int age; property (nonatomic,copy)…

C语言100例01 PHP版(练习)

题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; 程序分析&#xff1a;可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 代码&#xff1a; 1 for($i1;$i&l…

嵌入式根文件系统制作

1:文件系统分类&#xff1a; 基于flash的文件系统&#xff1a;flash有两种&#xff0c;一种是NOR,另一种NAND。NOR型 FLASH主要用于存放程序。NAND型 FLASH主要用于存放数据。NOR的特点是可在芯片内执行。这样应用程序可以直接在flash内存内运行&#xff0c;不必再把代码读到…

跨时钟域电路设计——结绳法

信号从快时钟域到慢时钟域过渡时&#xff0c;慢时钟可能无法对快时钟变化太快的信号进行采样。 之前的同步器法对两个时钟间的关系有要求&#xff0c;结绳法适用于任何时钟域之间的过渡。 结绳法的原理是将快时钟信号的脉冲周期延长&#xff0c;等到慢时钟周期采样后再“解绳”…

我之理解---计时器setTimeout 和clearTimeout

今天在写个图片切换的问题 有动画滞后的问题&#xff0c;才动手去查setTimeout 和clearTimeout。之前写的图片播放器也有类似的问题&#xff0c;有自动start按钮 和stop按钮&#xff0c; 其他都正常&#xff0c;问题出在每次多次快速的点击start按钮时&#xff0c;图片播放的速…

002服务提供者Eureka

1、POM配置 和普通Spring Boot工程相比&#xff0c;仅仅添加了Eureka、Spring Boot Starter Actuator依赖和Spring Cloud依赖管理 <dependencies><!--添加Eureka Server依赖--><dependency><groupId>org.springframework.cloud</groupId><art…