头文件:

#pragma once

#include<stdlib.h>

//链表结点
struct LinkNode{
void *data;
struct LinkNode *next;
}; //链表
struct _Linklist{
struct LinkNode header;
int size; //链表结点的数目
}; typedef void *LinkList; #ifdef __cplusplus
extern "C" {
#endif //初始化链表
LinkList Init_LinkList();
//指定位置插入
int InsertByPos_LinkList(LinkList list, int pos, void *data);
//头插
int PushFront_LinkList(LinkList list, void *data);
//尾插
int PushBack_LinkList(LinkList list, void *data);
//在指定值的前面插入
int InsertByVal_LinkList(LinkList list, void *oldval, void *newval, int(*isequal)(void*,void*));
//指定位置删除
int RemoveByPos_LinkList(LinkList list, int pos);
//根据值删除
int RemoveByVal_LinkList(LinkList list, void *data, int(*compare)(void *, void *));
//头删
void PopFront_LinkList(LinkList list);
//尾删
void PopBack_LinkList(LinkList list);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *));
//销毁
void Destroy_LinkList(LinkList list); #ifdef __cplusplus
}
#endif

头文件实现:

#include"LinkList.h"

//初始化链表
LinkList Init_LinkList(){ struct _Linklist *list = malloc(sizeof(struct _Linklist));
if (NULL == list){
return NULL;
} list->header.data = NULL;
list->header.next = NULL;
list->size = 0; return list;
}
//指定位置插入 0代表插入到第一个位置
int InsertByPos_LinkList(LinkList list, int pos, void *data){ if (NULL == list){
return -1;
} if (NULL == data){
return -2;
} struct _Linklist *llist = (struct _Linklist *)list; if (pos < 0 || pos > llist->size){
pos = llist->size;
} //辅助指针变量
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos;i ++){
pCurrent = pCurrent->next;
} //创建新结点
struct LinkNode *newnode = malloc(sizeof(struct LinkNode));
newnode->data = data;
newnode->next = NULL; //新结点入链表
newnode->next = pCurrent->next;
pCurrent->next = newnode; //size
llist->size++; return 0;
}
//头插
int PushFront_LinkList(LinkList list, void *data){
return InsertByPos_LinkList(list, 0, data);
}
//尾插
int PushBack_LinkList(LinkList list, void *data){
if (NULL == list){
return -1;
}
struct _Linklist *llist = (struct _Linklist *)list;
return InsertByPos_LinkList(list,llist->size - 1,data);
}
//在指定值的前面插入
int InsertByVal_LinkList(LinkList list, void *oldval, void *newval, int(*isequal)(void*, void*)){
if(NULL ==list){
return -1;
} if (NULL == oldval){
return -2;
} if (NULL == newval){
return -3;
} if (NULL == isequal){
return -4;
} struct _Linklist *llist = (struct _Linklist *)list; //辅助指针变量
struct LinkNode *pPrev = &(llist->header);
struct LinkNode *pCurrent = pPrev->next;
while (pCurrent != NULL){ if (isequal(pCurrent->data, oldval)){ //创建新结点
struct LinkNode *newnode = malloc(sizeof(struct LinkNode));
newnode->data = newval;
newnode->next = NULL; //新结点入链表
pPrev->next = newnode;
newnode->next = pCurrent; llist->size++; break;
} pPrev = pCurrent;
pCurrent = pCurrent->next;
} return 0;
}
//指定位置删除
int RemoveByPos_LinkList(LinkList list, int pos){ if (NULL == list){
return -1;
} struct _Linklist *llist = (struct _Linklist *)list; if (llist->size == 0){
return 0;
} if (pos < 0 || pos > llist->size - 1){
return 0;
} //辅助指针变量
//找到待删除结点的前一个结点
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos;i ++){
pCurrent = pCurrent->next;
} //缓存下待删除结点
struct LinkNode *pDel = pCurrent->next;
//重新建立待删除结点的前驱后继结点关系
pCurrent->next = pDel->next;
//删除结点内存
free(pDel);
pDel = NULL; llist->size--; return 0;
}
//根据值删除
int RemoveByVal_LinkList(LinkList list, void *data, int(*compare)(void *, void *)){ if (NULL == list){
return -1;
} if (NULL == data){
return -2;
} if (NULL == compare){
return -3;
} struct _Linklist *llist = (struct _Linklist *)list;
//辅助指针变量
struct LinkNode *pPrev = &(llist->header);
struct LinkNode *pCurrent = pPrev->next; while (pCurrent != NULL){ if (compare(pCurrent->data, data)){ pPrev->next = pCurrent->next;
free(pCurrent);
llist->size--;
break;
} pPrev = pCurrent;
pCurrent = pPrev->next; } return 0;
}
//头删
void PopFront_LinkList(LinkList list){
RemoveByPos_LinkList(list, 0);
}
//尾删
void PopBack_LinkList(LinkList list){
if (NULL == list){
return;
}
struct _Linklist *llist = (struct _Linklist *)list;
RemoveByPos_LinkList(list, llist->size - 1);
}
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){ if (NULL == list){
return;
} if (NULL == foreach){
return;
} struct _Linklist *llist = (struct _Linklist *)list; //辅助指针变量
struct LinkNode *pCurrent = llist->header.next;
while (pCurrent != NULL){
foreach(pCurrent->data);
pCurrent = pCurrent->next;
} }
//销毁
void Destroy_LinkList(LinkList list){ if (NULL == list){
return;
} struct _Linklist *llist = (struct _Linklist *)list; //辅助指针变量
struct LinkNode *pCurrent = llist->header.next;
while (pCurrent != NULL){ //缓存下一个结点
struct LinkNode *pNext = pCurrent->next;
//释放当前结点内存
free(pCurrent);
//指针移动到下一个结点的位置
pCurrent = pNext; } free(llist);
llist = NULL;
}

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkList.h" struct Person{
char name[64];
int age;
}; void MyPrint(void *data){
struct Person *person = (struct Person *)data;
printf("Name:%s Age:%d\n", person->name,person->age);
} int MyCompare(void *d1,void *d2){
struct Person *p1 = (struct Person *)d1;
struct Person *p2 = (struct Person *)d2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
} void test(){ //创建测试数据
struct Person p1 = { "aaa", 10 };
struct Person p2 = { "bbb", 20 };
struct Person p3 = { "ccc", 30 };
struct Person p4 = { "ddd", 40 };
struct Person p5 = { "eee", 50 };
struct Person p6 = { "fff", 60 };
struct Person p7 = { "ggg", 70 }; //初始化链表
LinkList list = Init_LinkList();
//将数据插入链表
InsertByPos_LinkList(list, 0, &p1);
InsertByPos_LinkList(list, 0, &p2);
InsertByPos_LinkList(list, 0, &p3);
InsertByPos_LinkList(list, 1, &p4);
InsertByPos_LinkList(list, 0, &p5);
InsertByPos_LinkList(list, 0, &p6);
//遍历 6 5 3 4 2 1
Foreach_LinkList(list, MyPrint);
printf("-------------------\n");
printf("在name为ccc,age为30的数据前面插入:\n");
InsertByVal_LinkList(list, &p3, &p7, MyCompare);
Foreach_LinkList(list, MyPrint);
printf("删除位置4的数据:\n");
RemoveByPos_LinkList(list,4);
Foreach_LinkList(list, MyPrint);
printf("删除name为ggg age为70的数据:\n");
RemoveByVal_LinkList(list, &p7, MyCompare);
Foreach_LinkList(list, MyPrint); //销毁链表
Destroy_LinkList(list);
} int main(){ test(); system("pause");
return EXIT_SUCCESS;
}

链表版本二:通过修改指针的指向的区域的大小,实现数据链接,给用户使用

头文件:

#pragma once

#include<stdlib.h>

//链表小节点

//目的 : 第一,让用户数据包含 第二,我需要把用户指针类型转换成struct LinkNode*类型
struct LinkNode{
struct LinkNode *next;
}; //链表结构体
struct LList{
struct LinkNode header;
int size;
}; typedef void *LinkList; //初始化
LinkList Init_LinkList(); //指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data);
//位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)); //销毁
void Destroy_LinkList(LinkList list);

头文件实现:

#include"LinkList.h"

//初始化
LinkList Init_LinkList(){ struct LList *list = malloc(sizeof(struct LList));
if (NULL == list){
return NULL;
}
list->header.next = NULL;
list->size = 0; return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data){ if (NULL == list){
return;
} if (NULL == data){
return;
} struct LList *llist = (struct LList *)list; if (pos < 0 || pos >llist->size){
pos = llist->size;
} //查找pos位置前一个位置的节点
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos;i ++){
pCurrent = pCurrent->next;
} //将新节点插入到链表
data->next = pCurrent->next;
pCurrent->next = data; llist->size++;
} //位置删除
void RemoveByPos_LinkList(LinkList list, int pos){ if (NULL ==list){
return;
} struct LList *llist = (struct LList *)list; if (llist->size == 0){
return;
} if (pos < 0 || pos > llist->size - 1){
return;
} //找到pos位置的前一个节点
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos; i ++){
pCurrent = pCurrent->next;
} //缓存下待删除节点
struct LinkNode *pDel = pCurrent->next;
//重新建立待删除的节点前驱后继节点关系
pCurrent->next = pDel->next; llist->size--;
} //遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){
if (NULL == list){
return;
} struct LList *llist = (struct LList *)list;
//辅助指针变量
struct LinkNode *pCurrent = llist->header.next;
while (pCurrent != NULL){
foreach(pCurrent);
pCurrent = pCurrent->next;
}
}

测试函数:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkList.h" struct Person{
struct LinkNode node;
char name[64];
int age;
}; void MyPrint(void *data){
struct Person *person = (struct Person *)data;
printf("Name:%s Age:%d\n",person->name,person->age);
} void ChanageValue(void *data){
struct Person *person = (struct Person *)data;
person->age += 100;
} //#define ISSTACK void test(){ //创建测试数据
#ifdef ISSTACK
struct Person p1 = { NULL , "aaa", 10 };
struct Person p2 = { NULL , "bbb", 20 };
struct Person p3 = { NULL , "ccc", 30 };
struct Person p4 = { NULL , "ddd", 40 };
struct Person p5 = { NULL , "eee", 50 };
#else
struct Person *p1 = malloc(sizeof(struct Person));
struct Person *p2 = malloc(sizeof(struct Person));
struct Person *p3 = malloc(sizeof(struct Person));
struct Person *p4 = malloc(sizeof(struct Person));
struct Person *p5 = malloc(sizeof(struct Person)); strcpy(p1->name, "aaa");
strcpy(p2->name, "bbb");
strcpy(p3->name, "ccc");
strcpy(p4->name, "ddd");
strcpy(p5->name, "eee"); p1->age = 10;
p2->age = 20;
p3->age = 30;
p4->age = 40;
p5->age = 50; #endif //初始化链表
LinkList list = Init_LinkList();
#ifdef ISSTACK
//数据插入到链表
Insert_LinkList(list, 0, (struct LinkNode *)&p1);
Insert_LinkList(list, 0, (struct LinkNode *)&p2);
Insert_LinkList(list, 0, (struct LinkNode *)&p3);
Insert_LinkList(list, 0, (struct LinkNode *)&p4);
Insert_LinkList(list, 0, (struct LinkNode *)&p5);
#else
Insert_LinkList(list, 0, (struct LinkNode *)p1);
Insert_LinkList(list, 0, (struct LinkNode *)p2);
Insert_LinkList(list, 0, (struct LinkNode *)p3);
Insert_LinkList(list, 0, (struct LinkNode *)p4);
Insert_LinkList(list, 0, (struct LinkNode *)p5);
#endif
//遍历
Foreach_LinkList(list, MyPrint); //删除2号位置
printf("------------------\n");
RemoveByPos_LinkList(list, 3);
Foreach_LinkList(list, MyPrint); //遍历修改数据
printf("---------------------\n");
//Foreach_LinkList(list, ChanageValue);
//Foreach_LinkList(list, MyPrint); //销毁链表
Destroy_LinkList(list); free(p1);
free(p2);
free(p3);
free(p4);
free(p5); } int main(){ test(); system("pause");
return EXIT_SUCCESS;
}

以链表为底层容器实现栈

头文件:

容器头文件:

#pragma once

#include<stdlib.h>

//链表小节点

//目的 : 第一,让用户数据包含 第二,我需要把用户指针类型转换成struct LinkNode*类型
struct LinkNode{
struct LinkNode *next;
};

//链表结构体
struct LList{
struct LinkNode header;
int size;
};

typedef void *LinkList;

//初始化
LinkList Init_LinkList();

//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data);
//位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *));
//根据位置获得值
void *Get_LinkList(LinkList list,int pos);
int Size_LinkList(LinkList list);

//销毁
void Destroy_LinkList(LinkList list);

栈头文件:

#pragma once

#include"LinkList.h"

struct StackNode{
struct LinkNode node;
}; typedef void *LinkStack; //初始化
LinkStack Init_LinkStack();
//入栈
void Push_LinkStack(LinkStack stack, void *data);
//出栈
void Pop_LinkStack(LinkStack stack);
//获得栈顶元素
void *Top_LinkStack(LinkStack stack);
//大小
int Size_LinkStack(LinkStack stack);
//销毁栈
void Destroy_LinkStack(LinkStack stack);

头文件实现:

容器头文件实现:

#include"LinkList.h"

//初始化
LinkList Init_LinkList(){ struct LList *list = malloc(sizeof(struct LList));
if (NULL == list){
return NULL;
}
list->header.next = NULL;
list->size = 0; return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data){ if (NULL == list){
return;
} if (NULL == data){
return;
} struct LList *llist = (struct LList *)list; if (pos < 0 || pos >llist->size){
pos = llist->size;
} //查找pos位置前一个位置的节点
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos;i ++){
pCurrent = pCurrent->next;
} //将新节点插入到链表
data->next = pCurrent->next;
pCurrent->next = data; llist->size++;
} //位置删除
void RemoveByPos_LinkList(LinkList list, int pos){ if (NULL ==list){
return;
} struct LList *llist = (struct LList *)list; if (llist->size == 0){
return;
} if (pos < 0 || pos > llist->size - 1){
return;
} //找到pos位置的前一个节点
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos; i ++){
pCurrent = pCurrent->next;
} //缓存下待删除节点
struct LinkNode *pDel = pCurrent->next;
//重新建立待删除的节点前驱后继节点关系
pCurrent->next = pDel->next; llist->size--;
} //根据位置获得值
void *Get_LinkList(LinkList list, int pos){
if (NULL == list){
return NULL;
} struct LList *llist = (struct LList *)list;
if (pos < 0 || pos > llist->size - 1){
return NULL;
} //辅助指针变量
struct LinkNode *pCurrent = &(llist->header);
for (int i = 0; i < pos; i++){
pCurrent = pCurrent->next;
} return pCurrent->next;
} int Size_LinkList(LinkList list){
if (NULL == list){
return -1;
} struct LList *llist = (struct LList *)list;
return llist->size;
} //遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){
if (NULL == list){
return;
} struct LList *llist = (struct LList *)list;
//辅助指针变量
struct LinkNode *pCurrent = llist->header.next;
while (pCurrent != NULL){
foreach(pCurrent);
pCurrent = pCurrent->next;
}
} //销毁
void Destroy_LinkList(LinkList list){
if (NULL == list){
return;
} free(list);
list = NULL;
}

栈头文件实现:

#include"LinkStack.h"

//初始化
LinkStack Init_LinkStack(){
return Init_LinkList();
}
//入栈
void Push_LinkStack(LinkStack stack, void *data){
Insert_LinkList(stack, 0, data);
}
//出栈
void Pop_LinkStack(LinkStack stack){
RemoveByPos_LinkList(stack, 0);
}
//获得栈顶元素
void *Top_LinkStack(LinkStack stack){
return Get_LinkList(stack, 0);
}
//大小
int Size_LinkStack(LinkStack stack){
return Size_LinkList(stack);
}
//销毁栈
void Destroy_LinkStack(LinkStack stack){
Destroy_LinkList(stack);
}

测试文件

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkStack.h" struct Person{
struct StackNode node;
char name[64];
int age;
}; void test(){ //创建测试数据
struct Person p1 = { NULL, "aaa", 10 };
struct Person p2 = { NULL, "bbb", 20 };
struct Person p3 = { NULL, "ccc", 30 };
struct Person p4 = { NULL, "ddd", 40 };
struct Person p5 = { NULL, "eee", 50 };
//初始化栈
LinkStack stack = Init_LinkStack();
//数据入栈
Push_LinkStack(stack , &p1);
Push_LinkStack(stack, &p2);
Push_LinkStack(stack, &p3);
Push_LinkStack(stack, &p4);
Push_LinkStack(stack, &p5);
//输出栈中元素
while (Size_LinkStack(stack) > 0){ //获得栈顶元素
struct Person *person = (struct Person*)Top_LinkStack(stack);
//输出元素
printf("Name:%s Age:%d\n",person->name,person->age);
//弹出栈顶元素
Pop_LinkStack(stack); } printf("Size%d\n",Size_LinkStack(stack)); //销毁栈
Destroy_LinkStack(stack);
} int main(){ test(); system("pause");
return EXIT_SUCCESS;
}

数据结构 传统链表实现与Linux内核链表的更多相关文章

  1. 链表的艺术——Linux内核链表分析

    引言: 链表是数据结构中的重要成员之中的一个.因为其结构简单且动态插入.删除节点用时少的长处,链表在开发中的应用场景许多.仅次于数组(越简单应用越广). 可是.正如其长处一样,链表的缺点也是显而易见的 ...

  2. 数据结构开发(10):Linux内核链表

    0.目录 1.老生常谈的两个宏(Linux) 1.1 offsetof 1.2 container_of 2.Linux内核链表剖析 3.小结 1.老生常谈的两个宏(Linux) Linux 内核中常 ...

  3. [国嵌攻略][108][Linux内核链表]

    链表简介 链表是一种常见的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入 ...

  4. linux内核链表分析

    一.常用的链表和内核链表的区别 1.1  常规链表结构        通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...

  5. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

  6. Linux内核链表深度分析【转】

    本文转载自:http://blog.csdn.net/coding__madman/article/details/51325646 链表简介: 链表是一种常用的数据结构,它通过指针将一系列数据节点连 ...

  7. linux内核链表的使用

    linux内核链表:链表通常包括两个域:数据域和指针域.struct list_head{struct list_head *next,*prev;};include/linux/list.h中实现了 ...

  8. 深入分析 Linux 内核链表--转

    引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...

  9. 深入分析 Linux 内核链表

    转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/   一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...

  10. linux内核链表的移植与使用

    一.  Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...

随机推荐

  1. Spring的自动装配和注解

    Bean的自动装配 自动装配说明 自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean. Spring的自动装配需要从两个角度来实现,或 ...

  2. day51-正则表达式02

    正则表达式02 5.4正则表达式语法02 5.4.6捕获分组 详见5.3.3 例子 package li.regexp; import java.util.regex.Matcher; import ...

  3. LcdTools如何导出内置画面为bmp图片

    运行LcdTools,先设置好图片所需分辨率参数,点击"画面设置"栏,修改下图所示参数 点击"画面设置"栏,在"画面资源"栏找到需要导出的画 ...

  4. Optimize(优化实验)

    十大优化法则 1.更快(本课程重点!) 2.更省(存储空间.运行空间) 3.更美(UI 交互) 4.更正确(本课程重点!各种条件下) 5.更可靠 6.可移植 7.更强大(功能) 8.更方便(使用) 9 ...

  5. nrf52——DFU升级OTA升级方式详解(基于SDK开发例程)

    在我们开始前,默认你已经安装好了一些基础工具,如nrfutil,如果你没有安装过请根据官方中文博客去安装好这些基础工具,连接如下:Nordic nRF5 SDK开发环境搭建(nRF51/nRF52芯片 ...

  6. 深度优先搜索(Depth-First-Search)dfs代码模板

    void dfs()//参数用来表示状态 { if(到达终点状态) { ...//根据需求添加 return; } if(越界或者是不合法状态) return; if(特殊状态)//剪枝,去除一些不需 ...

  7. 2022,一个Java程序猿的外设配置

    工欲善其事,必先利其器. 是的没错,我就是个器材党,哈哈.正赶上搬家布置了新桌面,经过我的精心挑选和安装,也是凑齐了我新一套的桌面外设.写下来记录一下. 键盘 套件:腹灵MK870 轴体:佳达隆G白P ...

  8. .NET7 一个实用功能-中央包管理

    依赖管理是 NuGet 的核心功能.Nuget管理单个项目的依赖关系很容易.管理多项目解决方案的依赖关系可能会变得很困难,因为它们的规模和复杂性开始扩大. 在您管理许多不同项目的公共依赖项的情况下,您 ...

  9. 干货,深入剖析ReentrantLock源码,推荐收藏

    ReentrantLock和Synchronized都是Java开发中最常用的锁,与Synchronized这种JVM内置锁不同的是,ReentrantLock提供了更丰富的语义.可以创建公平锁或非公 ...

  10. K8s如何启用cgroup2支持?

    什么是 cgroup ️Reference: control groups(控制组),通常被称为cgroup,是Linux内核的一项功能.它允许将进程组织成分层的组,然后限制和监控各种资源的使用. 内 ...