Redian新闻
>
数据存储,链表还是数组?

数据存储,链表还是数组?

公众号新闻

来源 | OSCHINA 社区

作者 | 中移物联OneOS

原文链接:https://my.oschina.net/u/5443273/blog/7782411


引言

链表和数组是两种不同的数据存储方式。链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。数组是把具有相同类型的若干元素按有序的形式组织起来的一种形式,数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。本文将对这两种存储方式的优缺点做一个大致的介绍,并详细介绍链表在操作系统中定义和使用的方式。

一、链表和数组

链表是链式的存储结构,数组是顺序的存储结构,其在内存存储上的不同形式决定了其各自的特点。

  1. 链表通过指针来链接元素,链表中的结点顺序关系由指针来体现;数组将元素按次序依次存储,元素顺序关系由元素在数组中的位置(下标)确定。
  2. 链表节点的存储单元在程序执行时动态向系统申请,链表的结点个数可按需要增减;数组元素的存储单元在数组定义时分配,其元素个数是固定的,对于不是固定长度的列表,用可能最大长度的数组来描述。
  3. 链表插入删除元素不需要移动元素,且较为容易实现长度扩充,但是寻找某个元素较为困难;数组寻找某个元素较为简单,但插入与删除比较复杂。

总体来说,链表使用指针将一系列数据节点链接成数据链,相对于数组,它具有良好的动态性,建立链表时不需要提前知道数据量,可以随时分配空间,可以高效地在链表中的任意位置插入或者删除数据。操作系统中存在着大量的基础数据结构链表和链表项,理解链表对理解操作系统至关重要。

二、单向链表和双向链表

通常链表数据结构包含两部分,一部分是数据域,用于存储数据;另外一部分是指针域,用于建立与其它节点的关系。链表项中可以包含一个指向下一个链表项的指针而不包含指向上一个链表的指针,也可以两者都包含,前者称为单向链表,后者为双向链表。

OneOS 物联网操作系统中提供的链表不包含数据域,使用时不是在链表结构中包含数据,而是在用户的数据结构中包含链表节点,操作系统中提供了双向链表及单向链表的一些比较通用的操作接口。

2.1 单向链表

OneOS 操作系统中的单向链表包含一个节点指针,这个节点指针指向下一个节点。OneOS 操作系统中的单向链表是一个非循环链表,单向链表本身首尾并非相连,单向链表中的最后一个节点指向 OS_NULL(循环链表单向链表中的最后一个节点指向单向链表中的第一个节点),其示意图如下所示。

OneOS 操作系统中单向链表节点的结构体如下所示。

struct os_slist_node
{
struct os_slist_node *next; /* Point to next node */
};

2.2 双向链表

OneOS 操作系统中的双向链表包含了两个结点指针,一个节点指针指向下一个节点,另一个节点指针指向上一个节点。OneOS 操作系统中的双向链表是一个循环链表,双向链表本身首尾相连,双向链表最后一个节点的指向下一个节点的节点指针指向第一个节点,第一个节点的指向上一个节点的节点指针指向最后一个节点,其示意图如下所示。
OneOS 操作系统中双向链表节点的结构体如下所示。
struct os_list_node
{
struct os_list_node *next; /* Point to next node */
struct os_list_node *prev; /* point to previous node */
};

三、应用示例

单向链表应用示例

#include <oneos_config.h>#include <dlog.h>#include <os_errno.h>#include <shell.h>#include <string.h>#include <os_memory.h>#include <os_list.h>
#define TEST_TAG "TEST"
#define STUDENT_NUM 10#define TEST_NAME_MAX 16
char *name[STUDENT_NUM] = {"xiaoming", "xiaohua", "xiaoqiang", "xiaoli", "xiaofang", "zhangsan", "lisi", "wangwu", "zhaoliu", "qianqi"};uint32_t score[STUDENT_NUM] = {70, 83, 68, 80, 88, 86, 78, 92, 55, 82};
struct student_score
{

os_slist_node_t list_node;
char name[TEST_NAME_MAX];
uint32_t id;
uint32_t score;
};typedef struct student_score student_score_t;
void single_list_sample(void)
{
uint32_t i = 0;
os_slist_node_t list_head = OS_SLIST_INIT(list_head);
student_score_t *data;
os_slist_node_t *node_temp;
os_slist_node_t *node;

LOG_W(TEST_TAG, "single_list_sample insert data");
for (i = 0; i < STUDENT_NUM; i++)
{
data = os_malloc(sizeof(student_score_t));
data->id = i;
memset(data->name, 0, TEST_NAME_MAX);
strncpy(data->name, name[i], TEST_NAME_MAX);
data->score = score[i];
if (i < STUDENT_NUM/2)
{
LOG_W(TEST_TAG, "insert tail -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_slist_add_tail(&list_head, &data->list_node);
}
else
{
LOG_W(TEST_TAG, "insert front-- id:%d score:%d name:%s", data->id, data->score, data->name);
os_slist_add(&list_head, &data->list_node);
}
}

LOG_W(TEST_TAG, "single_list_sample show result");
os_slist_for_each(node, &list_head)
{
data = os_slist_entry(node, student_score_t, list_node);
LOG_W(TEST_TAG, "id:%d score:%d name:%s", data->id, data->score, data->name);
}

LOG_W(TEST_TAG, "single_list_sample list_len is:%d", os_slist_len(&list_head));
LOG_W(TEST_TAG, "single_list_sample delete the score less than 60");
os_slist_for_each_safe(node, node_temp, &list_head)
{
data = os_slist_entry(node, student_score_t, list_node);
if (data->score < 60)
{
LOG_W(TEST_TAG, "delete -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_slist_del(&list_head, &data->list_node);
os_free(data);
}
}

LOG_W(TEST_TAG, "single_list_sample list_len is:%d", os_slist_len(&list_head));
LOG_W(TEST_TAG, "single_list_sample show result, and then delete");
os_slist_for_each_safe(node, node_temp, &list_head)
{
data = os_slist_entry(node, student_score_t, list_node);
LOG_W(TEST_TAG, "delete -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_slist_del(&list_head, &data->list_node);
os_free(data);
}

LOG_W(TEST_TAG, "single_list_sample list_len is:%d", os_slist_len(&list_head));
}

SH_CMD_EXPORT(test_single_list, single_list_sample, "test single list");
运行结果
sh>test_single_list
W/TEST: single_list_sample insert data
W/TEST: insert tail -- id:0 score:70 name:xiaoming
W/TEST: insert tail -- id:1 score:83 name:xiaohua
W/TEST: insert tail -- id:2 score:68 name:xiaoqiang
W/TEST: insert tail -- id:3 score:80 name:xiaoli
W/TEST: insert tail -- id:4 score:88 name:xiaofang
W/TEST: insert front-- id:5 score:86 name:zhangsan
W/TEST: insert front-- id:6 score:78 name:lisi
W/TEST: insert front-- id:7 score:92 name:wangwu
W/TEST: insert front-- id:8 score:55 name:zhaoliu
W/TEST: insert front-- id:9 score:82 name:qianqi
W/TEST: single_list_sample show result
W/TEST: id:9 score:82 name:qianqi
W/TEST: id:8 score:55 name:zhaoliu
W/TEST: id:7 score:92 name:wangwu
W/TEST: id:6 score:78 name:lisi
W/TEST: id:5 score:86 name:zhangsan
W/TEST: id:0 score:70 name:xiaoming
W/TEST: id:1 score:83 name:xiaohua
W/TEST: id:2 score:68 name:xiaoqiang
W/TEST: id:3 score:80 name:xiaoli
W/TEST: id:4 score:88 name:xiaofang
W/TEST: single_list_sample list_len is:10
W/TEST: single_list_sample delete the score less than 60
W/TEST: delete -- id:8 score:55 name:zhaoliu
W/TEST: single_list_sample list_len is:9
W/TEST: single_list_sample show result, and then delete
W/TEST: delete -- id:9 score:82 name:qianqi
W/TEST: delete -- id:7 score:92 name:wangwu
W/TEST: delete -- id:6 score:78 name:lisi
W/TEST: delete -- id:5 score:86 name:zhangsan
W/TEST: delete -- id:0 score:70 name:xiaoming
W/TEST: delete -- id:1 score:83 name:xiaohua
W/TEST: delete -- id:2 score:68 name:xiaoqiang
W/TEST: delete -- id:3 score:80 name:xiaoli
W/TEST: delete -- id:4 score:88 name:xiaofang
W/TEST: single_list_sample list_len is:0
双向链表应用示例
#include <oneos_config.h>#include <dlog.h>#include <os_errno.h>#include <shell.h>#include <string.h>#include <os_memory.h>#include <os_list.h>
#define TEST_TAG "TEST"
#define STUDENT_NUM 10#define TEST_NAME_MAX 16
char *name[STUDENT_NUM] = {"xiaoming", "xiaohua", "xiaoqiang", "xiaoli", "xiaofang", "zhangsan", "lisi", "wangwu", "zhaoliu", "qianqi"};uint32_t score[STUDENT_NUM] = {70, 83, 68, 80, 88, 86, 78, 92, 55, 82};
struct student_score
{

os_list_node_t list_node;
char name[TEST_NAME_MAX];
uint32_t id;
uint32_t score;
};typedef struct student_score student_score_t;
void list_sample(void)
{
uint32_t i = 0;
os_list_node_t list_head = OS_LIST_INIT(list_head);
student_score_t *data;
student_score_t *data_temp;
os_list_node_t *node;
os_list_node_t *node_temp;

LOG_W(TEST_TAG, "list_sample insert data");
for (i = 0; i < STUDENT_NUM; i++)
{
data = os_malloc(sizeof(student_score_t));
data->id = i;
memset(data->name, 0, TEST_NAME_MAX);
strncpy(data->name, name[i], TEST_NAME_MAX);
data->score = score[i];
if (i < STUDENT_NUM/2)
{
LOG_W(TEST_TAG, "insert tail -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_list_add_tail(&list_head, &data->list_node);
}
else
{
LOG_W(TEST_TAG, "insert front-- id:%d score:%d name:%s", data->id, data->score, data->name);
os_list_add(&list_head, &data->list_node);
}
}

LOG_W(TEST_TAG, "list_sample show result");
os_list_for_each_entry(data, &list_head, student_score_t, list_node)
{
LOG_W(TEST_TAG, "id:%d score:%d name:%s", data->id, data->score, data->name);
}

LOG_W(TEST_TAG, "list_sample list_len is:%d", os_list_len(&list_head));
LOG_W(TEST_TAG, "list_sample delete the score less than 60");
os_list_for_each_entry_safe(data, data_temp, &list_head, student_score_t, list_node)
{
if (data->score < 60)
{
LOG_W(TEST_TAG, "delete -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_list_del(&data->list_node);
os_free(data);
}
}

LOG_W(TEST_TAG, "list_sample list_len is:%d", os_list_len(&list_head));
LOG_W(TEST_TAG, "list_sample show result, and then delete");
os_list_for_each_safe(node, node_temp, &list_head)
{
data = os_list_entry(node, student_score_t, list_node);
LOG_W(TEST_TAG, "delete -- id:%d score:%d name:%s", data->id, data->score, data->name);
os_list_del(&data->list_node);
os_free(data);
}

LOG_W(TEST_TAG, "list_sample list_len is:%d", os_list_len(&list_head));
}

SH_CMD_EXPORT(test_list, list_sample, "test list");
运行结果
sh>test_list
W/TEST: list_sample insert data
W/TEST: insert tail -- id:0 score:70 name:xiaoming
W/TEST: insert tail -- id:1 score:83 name:xiaohua
W/TEST: insert tail -- id:2 score:68 name:xiaoqiang
W/TEST: insert tail -- id:3 score:80 name:xiaoli
W/TEST: insert tail -- id:4 score:88 name:xiaofang
W/TEST: insert front-- id:5 score:86 name:zhangsan
W/TEST: insert front-- id:6 score:78 name:lisi
W/TEST: insert front-- id:7 score:92 name:wangwu
W/TEST: insert front-- id:8 score:55 name:zhaoliu
W/TEST: insert front-- id:9 score:82 name:qianqi
W/TEST: list_sample show result
W/TEST: id:9 score:82 name:qianqi
W/TEST: id:8 score:55 name:zhaoliu
W/TEST: id:7 score:92 name:wangwu
W/TEST: id:6 score:78 name:lisi
W/TEST: id:5 score:86 name:zhangsan
W/TEST: id:0 score:70 name:xiaoming
W/TEST: id:1 score:83 name:xiaohua
W/TEST: id:2 score:68 name:xiaoqiang
W/TEST: id:3 score:80 name:xiaoli
W/TEST: id:4 score:88 name:xiaofang
W/TEST: list_sample list_len is:10
W/TEST: list_sample delete the score less than 60
W/TEST: delete -- id:8 score:55 name:zhaoliu
W/TEST: list_sample list_len is:9
W/TEST: list_sample show result, and then delete
W/TEST: delete -- id:9 score:82 name:qianqi
W/TEST: delete -- id:7 score:92 name:wangwu
W/TEST: delete -- id:6 score:78 name:lisi
W/TEST: delete -- id:5 score:86 name:zhangsan
W/TEST: delete -- id:0 score:70 name:xiaoming
W/TEST: delete -- id:1 score:83 name:xiaohua
W/TEST: delete -- id:2 score:68 name:xiaoqiang
W/TEST: delete -- id:3 score:80 name:xiaoli
W/TEST: delete -- id:4 score:88 name:xiaofang
W/TEST: list_sample list_len is:0
更详细的 API 介绍欢迎前往 OneOS 官网文档中心查看:https://os.iot.10086.cn/v2/doc/detailPage/documentHtml?proId=2000000000&proName=OneOS&idss=718&versionName=v3.0.1&versionId=3000000012
OneOS 源码仓库:https://gitee.com/cmcc-oneos/OneOS


往期推荐



开源方案低成本复现ChatGPT流程,仅需1.6GB显存即可体验

顶流开源项目作者全职做开源的“血泪史”:入狱、耗尽积蓄、被网暴……

质疑我违规窃取开源代码?拉黑你!



这里有最新开源资讯、软件更新、技术干货等内容

点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
回归阅读|这就是数学存储器大突破!全球存储芯片巨头率先反弹,这些A股公司被两路资金盯上令人心动的AI offer(六):小红书、京东科技、华为数据存储、蚂蚁安全事业群等校招、社招与实习生职位用ChatGPT,链接了百度前员工...谁是数字经济一线城市?张忆东:今年A股当红炸子鸡是数字经济,央国企价值重估行情才刚开始米莱新书《这就是数学》:解决1~4年级娃概念、数量关系、思维转换的数学难题懒人花园:姹紫嫣红的岁月MLOps主要是数据工程不等澳联储,联邦及国民银行相继宣布加息!即刻生效乌克兰来美国,俄罗斯去中国,巧合吗?深夜大利空!突然暴跌20%,拜登即将出手!华尔街巨头"炮轰"美联储,什么情况?时尚米兰,现代米兰你以为AI是在画画吗?它画的是数学声明数组的最佳方式是什么如何进入电影导演组?OpenAI 买下AI.com域名,链接直转至 ChatGPT李连杰「师父」、武术家于海81岁去世 吴京哀悼!华 为小公主带资进剧组?和刘亦菲变「情敌」抢李现!成 龙女儿与母闹翻 拒回家过年有没有可能,东野圭吾不是个人,而是个写作小组?北京沦陷后谈疫苗和体制优势美国宾州葛底斯堡国家军事公园,秋色田园刀法品效峰会全览 | 一站获取品牌营销前沿干货及资讯,链接行业优质资源!蚂蚁集团韦韬:数据密态是数据要素产业安全发展的关键技术路径​张新成付辛博被嘲?丑奶狗和白月光要结婚?少班主紧急封口?孙俪即将进组?LeetCode 力扣官方题解 | 2104. 子数组范围和关注 | 立足纽约,链接世界:哥伦比亚大学开启全球新布局129亿元!国家大基金二期入股长江存储,长江存储增资至1052.70亿元存储,到明年都好不了?炸了!不等澳联储,联邦及国民银行自己宣布加息!即刻生效!澳洲人骂疯了!兆易创新vs北京君正vs长江存储:谁能扛起国产存储大旗?国家出手了!发改委启动中央冻猪肉收储,猪价4月迎拐点?为什么数组下标是从 0 开始,而不从 1 开始?进军类ChatGPT,成立项目组?腾讯回应江波龙强化车用、AI存储,已与近30家国内车规领域客户合作国家数据局建立,医疗数据存在资产化的可能吗?
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。