目录
📎list.rar
链表的作用
使用list.h使用例
练习
答案:
📎list.rarhttps://www.yuque.com/attachments/yuque/0/2023/rar/35243076/1687947573309-b0609eda-c0ac-475d-8d13-b901a3359cad.rar
链表的作用
链表在动态内存分配、插入删除操作、构建其他数据结构、高效查找、缓存和回收等方面发挥着重要作用。它是一种灵活、高效的数据结构,适用于各种场景和问题的解决方案。
下面是一个简单的链表应用:
假设学生结构体信息如下,封装一个单链表的插入接口
和遍历输出的接口
,在主函数中利用封装的接口生成一个学生链表,并遍历输出链表的学生信息。
struct stu_node
{
int age;
char name[64];
};
//定义一个链表头节点
static xxx head;
//头插法插入,参数为新插入的节点信息
int insert_head(struct xxx data)
{
}
//遍历输出节点的信息
void print_list()
{
}
int main(int argc, char const *argv[])
{
head.next = NULL;
//定义新的节点并赋值
//调用插入方法
insert_head(data1);
insert_head(data2);
//遍历输出
print_list();
}
上面是一个学生结构体,假设我们换了一个老师结构体,上面的链表的实现逻辑不变,但还是需要进行大量修改。
为了提高开发效率,减少重复工作,linux内核给我们提供了链表。
https://www.cnblogs.com/wangzahngjun/p/5556448.htmlhttps://www.cnblogs.com/wangzahngjun/p/5556448.html
但是linux提供的内核链表还是不太满足初学者需求,我从某些途径获取到了一个修改后的内核链表,能满足一些需求。(放到文章顶部了)
使用list.h使用例
#include <stdio.h>
#include <string.h>
#include "list.h"
// 定义学生结构体
struct student
{
int age; // 年龄
char name[64]; // 姓名
struct list_head list; // 链表节点
};
int main()
{
struct list_head head;
INIT_LIST_HEAD(&head); // 初始化链表头部
// 创建学生节点
struct student stu1;
strcpy(stu1.name, "张三");
stu1.age = 1;
struct student stu2;
strcpy(stu2.name, "李四");
stu2.age = 2;
struct student stu3;
strcpy(stu3.name, "王五");
stu3.age = 3;
// 将学生节点添加到链表头部
list_add(&stu1.list, &head);
list_add(&stu2.list, &head);
list_add(&stu3.list, &head);
struct list_head *pos;
struct student *tmp;
printf("初始化链表\n");
// 遍历链表并打印每个节点的信息
list_for_each(pos, &head)
{
tmp = list_entry(pos, struct student, list);
printf("姓名:%s,年龄:%d\n", tmp->name, tmp->age);
}
printf("\n");
pos = get_first(&head);
tmp = list_entry(pos, struct student, list);
printf("第一个节点是:%s\n\n", tmp->name);
pos = get_last(&head);
tmp = list_entry(pos, struct student, list);
printf("最后一个节点是:%s\n\n", tmp->name);
puts("删除最后一个节点");
// 删除最后一个节点
list_del(pos);
printf("删除后:");
// 再次遍历链表确认删除操作的效果
list_for_each(pos, &head)
{
tmp = list_entry(pos, struct student, list);
printf("%d ", tmp->age);
}
puts("\n");
return 0;
}
练习
将下面的数据节点信息转换为链表结构,并遍历输出。要求根据type的值来决定val的类型。type为1代表bool类型,2代表整形,3代表浮点型。无需解析文本,直接赋值形成节点即可。
"data":
[
{
"key": 1,
"type": 2,
"val": "10"
},
{
"key": 2,
"type": 1,
"val": "0"
},
{
"key": 3,
"type": 3,
"val": "22.5"
}
]
答案:
#include <stdio.h>
#include <string.h>
#include<stdbool.h>
#include "list.h"
union val_t
{
bool b_val;
int i_val;
float f_val;
};
struct student
{
int key;
int type;
union val_t val;
struct list_head list;
};
void main()
{
struct list_head head; //定义头
INIT_LIST_HEAD(&head);
struct student stu1;
stu1.key=1;
stu1.type = 2; //int
stu1.val.i_val=10;
struct student stu2;
stu2.key=2;
stu2.type = 1;//bool
stu2.val.b_val=0;
struct student stu3;
stu3.key=3;
stu3.type =3;//float
stu3.val.f_val=22.5;
//使用提供函数添加,我选择头插法
list_add(&stu3.list, &head);
list_add(&stu2.list, &head);
list_add(&stu1.list, &head);
struct list_head *pos;
struct student *tmp;
list_for_each(pos, &head)
{
tmp = list_entry(pos, struct student, list);
if(tmp->type==1)
{
printf("{\nkey:%d,\ntype:%d,\nval:%d\n", tmp->key, tmp->type,tmp->val.b_val);
printf("},\n");
}else if(tmp->type==2)
{
printf("{\nkey:%d,\ntype:%d,\nval:%d\n", tmp->key, tmp->type,tmp->val.i_val);
printf("},\n");
}else if (tmp->type==3)
{
printf("{\nkey:%d,\ntype:%d,\nval:%.1f\n", tmp->key, tmp->type,tmp->val.f_val);
printf("},\n");
}
}
printf("\n");
list_del(pos);
return ;
}