参考文章:使用C语言实现“泛型”链表

文章目录

  • jiang工给的泛型链表例子,有点看不怎么懂,自己写个看看:
  • 实现方法
    • 方法1:链表指针指向整个结点,结点中存放指向数据的指针
    • 方法2:结构体数据作为结点,结点中存放指向prev、next的指针(好像这样的话结构体数据确实不能直接作为结点)

jiang工给的泛型链表例子,有点看不怎么懂,自己写个看看:

#include <stdio.h>
struct list_head {struct list_head *next, *prev;
};#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)//根据structd的成员获取struct的地址
#define container_of(ptr, type, member) ((type *)(((char *)ptr) - (int)(&(((type*)0)->member))))//链表遍历#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_prev(pos, head) \for (pos = (head)->prev; pos != (head); pos = pos->prev)#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{next->prev = new;new->next = next;new->prev = prev;prev->next = new;
}static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;prev->next = next;
}static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);
}typedef struct  _student {int data ;struct list_head mylist;
}student;int main()
{LIST_HEAD(header_task);student s1 ={.data =1};student s2 ={.data =2};student s3 ={.data =3};struct list_head* pos;student* s;list_add(&s1.mylist,&header_task);list_add(&s2.mylist,&header_task);list_add(&s3.mylist,&header_task);list_for_each(pos, &header_task){s = container_of(pos, student, mylist);printf("data is %d\n",s->data);}printf("----------\n");list_del(&s2.mylist);list_for_each(pos, &header_task){s = container_of(pos, student, mylist);printf("data is %d\n",s->data);}printf("Hello World!\n");return 0;
}

实现方法

有一点懵逼,我的思路是,在结点中的数据域存放指向自定义数据结构的指针

另一种思路是在自定义数据结构中存放prev和next指针

思考一个问题,是先有数据,我们把数据串起来就,成了链表?

还是先有链表,我们再将数据一个个放进去?(好无聊的问题( ̄、 ̄))

那么我自己实现两个版本吧,其中一个版本是链表指针指向整个结点,结点中存放指向数据的指针;另一个版本是将数据作为结点,像jianggong写的那样,但是可以将mylist(包含prev和next指针)写在最上面,这样就不必用相对地址去计算了

方法1:链表指针指向整个结点,结点中存放指向数据的指针

#include <stdio.h>
#include <stdlib.h>
#include <String.h>//定义结点
struct Node
{void* data;struct Node* prev;struct Node* next;
};//尾插结点
void list_add_tail(Node* p, void* e) {struct Node* n = (Node*)malloc(sizeof(Node));if (NULL != n) {n->data = e;Node* tmp = p->prev;p->prev = n;n->prev = tmp;n->next = p;tmp->next = n;}
}//删除结点
void list_del(Node* h, void* u) {while (NULL != h->next->data) {if (u == h->next->data) {Node* tmp = h->next;h->next = h->next->next;h->next->prev = h;if (NULL != tmp) {//if (NULL != tmp->data) {//free(tmp->data);free(tmp);printf("成功删除结点!\n");return;//}}}else {h = h->next;}}printf("没有找到要删除的结点!\n");
}int main() {//创建链表Node header_task1 = { NULL, &header_task1, &header_task1 };//定义自定义结构体struct User{char name[20];char phone[20];};//创建自定义结构体u1(不是用malloc动态分配堆空间,不用free)User u1 = { "唐三藏", "18944443333" };User u2 = { "白骨精", "18922223333" };User u3 = { "猪八戒", "18911113333" };User u4 = { "牛魔王", "18900003333" };//尾插list_add_tail(&header_task1, &u1);list_add_tail(&header_task1, &u2);list_add_tail(&header_task1, &u3);list_add_tail(&header_task1, &u4);//遍历//条件也可以是:node != &header_task1for (Node* node = header_task1.next; node->data != NULL; node = node->next) {printf("姓名:%s\t电话号码:%s\n", ((User*)node->data)->name, ((User*)node->data)->phone);}//删除某个结点list_del(&header_task1, &u1);//成功list_del(&header_task1, &u1);//没有找到//遍历//条件也可以是:node != &header_task1for (Node* node = header_task1.next; node->data != NULL; node = node->next) {printf("姓名:%s\t电话号码:%s\n", ((User*)node->data)->name, ((User*)node->data)->phone);}return 0;
}

运行结果:

姓名:唐三藏    电话号码:18944443333
姓名:白骨精    电话号码:18922223333
姓名:猪八戒    电话号码:18911113333
姓名:牛魔王    电话号码:18900003333
成功删除结点!
没有找到要删除的结点!
姓名:白骨精    电话号码:18922223333
姓名:猪八戒    电话号码:18911113333
姓名:牛魔王    电话号码:18900003333

方法2:结构体数据作为结点,结点中存放指向prev、next的指针(好像这样的话结构体数据确实不能直接作为结点)

#include <stdio.h>
#include <stdlib.h>
#include <String.h>struct list_head {struct list_head* next;struct list_head* prev;
};//尾插结点
void list_add_tail(list_head* head, list_head* new_node) {/*list_head* tmp = head->prev;head->prev = new_node;new_node->prev = tmp;tmp->next = new_node;new_node->next = head;*///根本不用temp啊!head->prev->next = new_node;new_node->prev = head->prev;head->prev = new_node;new_node->next = head;
}//删除结点
void list_del(list_head* head, list_head* del) {list_head* i = head;for (i = i->next; i != head; i = i->next) {if (i == del) {i->prev->next = i->next;i->next->prev = i->prev;//删除结点也用不到tmp(只有单向链表增删才用到tmp吧!)printf("删除结点成功!\n");}}
}int main() {//创建链表list_head header_task1 = {&header_task1, &header_task1 };//定义自定义结构体struct User{char name[20];char phone[20];list_head my_list;};//创建自定义结构体u1(不是用malloc动态分配堆空间,不用free)User u1 = { "唐三藏", "18944443333", {NULL, NULL} };User u2 = { "白骨精", "18922223333", {NULL, NULL} };User u3 = { "猪八戒", "18911113333", {NULL, NULL} };User u4 = { "牛魔王", "18900003333", {NULL, NULL} };//尾插list_add_tail(&header_task1, &u1.my_list);list_add_tail(&header_task1, &u2.my_list);list_add_tail(&header_task1, &u3.my_list);list_add_tail(&header_task1, &u4.my_list);list_head* pos1;User* u;//遍历for (pos1 = header_task1.next; pos1 != &header_task1; pos1 = pos1->next) {u = (User*)((int)pos1 - (int)&(((User*)0)->my_list));printf("姓名:%s\t电话:%s\t\n", u->name, u->phone);}//删除list_del(&header_task1, &u1.my_list);for (pos1 = header_task1.next; pos1 != &header_task1; pos1 = pos1->next) {u = (User*)((int)pos1 - (int)&(((User*)0)->my_list));printf("姓名:%s\t电话:%s\t\n", u->name, u->phone);}return 0;
}
姓名:唐三藏    电话:18944443333
姓名:白骨精    电话:18922223333
姓名:猪八戒    电话:18911113333
姓名:牛魔王    电话:18900003333
删除结点成功!
姓名:白骨精    电话:18922223333
姓名:猪八戒    电话:18911113333
姓名:牛魔王    电话:18900003333

C语言 泛型链表的实现相关推荐

  1. C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)

    示例: typedef struct _user {char name[20];char sex[20];int age;struct list_head mylist;//自定义结构体里保存双向循环 ...

  2. 用c语言实现单链表的初始化,建表,查找,求长度,插入,删除等操作,【YTU+2430+C语言习题+链表建立+插入+删除+输(5)...

    的打印.判断链表是否为空.计算链表长度.插入节点.删除节点.删除整个链表.(2) 线性表adt顺序存储实现中的创建.查找.插入和删除等基本操作及相关算法,线性表adt链式存储实现中单链表.循环链表和双 ...

  3. C语言打印链表的中间节点的算法(附完整源码)

    C语言打印链表的中间节点的算法 C语言打印链表的中间节点的算法完整源码(定义,实现,main函数测试) C语言打印链表的中间节点的算法完整源码(定义,实现,main函数测试) #include < ...

  4. C语言通过链表指针删除链表节点的算法(附完整源码)

    C语言通过链表指针删除链表节点的算法 C语言通过链表指针删除链表节点的算法完整源码(定义,实现,main函数测试) C语言通过链表指针删除链表节点的算法完整源码(定义,实现,main函数测试) #in ...

  5. C语言删除链表的算法(附完整源码)

    C语言删除链表的算法 C语言删除链表的算法完整源码(定义,实现,main函数测试) C语言删除链表的算法完整源码(定义,实现,main函数测试) #include <iostream>st ...

  6. C语言实现链表(附完整源码)

    C语言实现链表 链表 C语言实现链表完整源码 链表 链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用.链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定 ...

  7. c语言在文本每一行末尾追加字符串,c语言在末尾添加 C语言 在链表尾部添加节点...

    怎么用C语言在一个文件后面添加内容 怎么用C语言在一个文件后面添加内容 使用fopen函数打开文件,用fseek函数将文件位置调整到文件末尾,然后用fwrite函数写入数据即可.下面的示例代码,向1. ...

  8. 剑指offer之C语言实现链表(两种方式)

    1 问题 用C语言实现链表 2 代码实现 #include <stdio.h> #include <stdlib.h>#define true 0 #define false ...

  9. c语言将链表写入二进制文件_通过逐级遍历将二进制树转换为单链表的C程序

    c语言将链表写入二进制文件 Problem statement: Write a C program to convert a binary tree into a single linked lis ...

最新文章

  1. ios 如何在cell中去掉_IOS之表视图单元格删除、移动及插入
  2. 用一维数组统计五个人的成绩中的最大值最小值平均值_昨天为了整理这份教程,我放弃了参加一个几亿人的大项目。...
  3. python自学入门教程-Python学习教程(一)自学资源分享
  4. [转]NS2仿真过程中解决动画仿真节点未定义问题
  5. Uva 11077 Find the Permutation
  6. 做ppt用的小插图_如何用PPT做随机抽奖?
  7. 【人脸识别】Center Loss详解
  8. java hashset 实现_HashSet实现原理分析(Java源码剖析)
  9. Java之品优购课程讲义_day12(2)
  10. 拼多多上市关你什么事?
  11. php 网上支付之易宝支付
  12. 计算机上的字体怎么安装,电脑怎么安装字体
  13. win7 Pro 英文版添加中文语言包
  14. 关于小程序区服登录账号换模拟器登录的操作
  15. 简单美化 Win 10 的 CMD 命令行终端界面
  16. 7张图让你看懂互联网营销思维与传统思维本质区别
  17. ROS的几个重要概念:节点、消息、主题、服务
  18. 类和对象:类与对象定义
  19. 程序员财富自由之路 自媒体篇 | 3000字干货分享
  20. Ubuntu 10.04 在 Vmware 虚拟机下安装 vmware tools

热门文章

  1. Linux中/proc目录下文件详解(二)
  2. SQL结构化查询语言中的LIKE语句
  3. 自己编译redhat 9.0内核心得
  4. vue 虚拟服务器,vue+webpack项目中使用dev-server搭建虚拟服务器,请求json文件数据,实现先后台分离开发...
  5. android 恶意广告,CheckPoint:Android恶意广告软件SimBad被下载近1.5亿次
  6. 自由自在带你品尝一种能长出果蔬的冰淇淋
  7. 【收藏】SAP记账码
  8. SAP MB51物料凭证清单程序增强增加四个字段
  9. 释疑の采购订单的批量修改
  10. 如何用CS07进行BOM工厂分配