在学习RTOS操作系统时,在任务优先级设置时用到了双向链表,说实话数据结构的东西只是停留在大学上课阶段,并未实践过,在操作系统中看得云里雾里,遂将其单独拿来了进行了一下思考,经过一个上午的摸索逐渐领会到了其中的精华。

  1.什么是双向链表

百度百科:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

  

  此表中包含两个重要信息:链表结构,节点结构

  首先定义好节点的结构体:

 typedef struct _tNode
{
int data;
struct _tNode * pre;
struct _tNode * next;
}tNode;

然后在定义链表的结构体:

 typedef struct _tList
{
tNode HeadNode;
int NodeCount;
}tList;

  这个结构体的作用就是可以在工程中创建多个这样的链表结构,结构体里包含头结点HeadNode和此链表节点的数量NodeCount用来对链表进行操作的定位。头结点并不保存数据,只是提供指向节点的指针用来连接整个链表。所以在操作链表时可以很快地进行各种操作。在操作链表时只需要对完成对节点地添加和删除即可,头结点保持不变!

  基本初始化:

void tNodeInit(tNode *Node)
{
Node->pre = Node;
Node->next = Node;
} void tListInit(tList *list)//初始化链表
{
list->HeadNode.pre = &(list->HeadNode);
list->HeadNode.next = &(list->HeadNode);
list->NodeCount = ;
} int tListCount(tList *list)//返回链表节点数量
{
return list->NodeCount;
}

节点数据的插入和删除:

tNode* FirstNode(tList *list)//返回首节点
{
tNode* node = (tNode*);
if (list->NodeCount != )
{
node = list->HeadNode.next;
}
return node;
} tNode* LastNode(tList *list)//返回最后一个节点
{
tNode* node = (tNode*);
if (list->NodeCount != )
{
node = list->HeadNode.pre;
}
return node;
} tNode* tListPre(tList* list,tNode* node)//返回一个节点的前一个节点
{
if (node->pre == node)
{
return (tNode*);
}
else
{
return node->pre;
}
} tNode* tListNext(tList* list, tNode* node)//返回节点的后一个节点
{
if (node->next == node)
{
return (tNode*);
}
else
{
return node->next;
}
} void RemoveAll(tList* list)//删除所有节点
{
tNode* CurrentNode, *NextNode;
int count; NextNode = list->HeadNode.next;
for (count=list->NodeCount;count > ;count --)
{
CurrentNode = NextNode;
NextNode = CurrentNode->next; CurrentNode->pre = CurrentNode;
CurrentNode->next = CurrentNode;
} list->HeadNode.pre = &(list->HeadNode);
list->HeadNode.next = &(list->HeadNode); list->NodeCount = ;
} void tListHeadAdd(tList *list,tNode *node)//在头部添加节点
{
node->next = list->HeadNode.next;
node->pre = list->HeadNode.next->pre; list->HeadNode.next = node;
list->HeadNode.next->pre = node; list->NodeCount ++; } void tListLastAdd(tList *list,tNode *node)//在最后添加节点
{
node->pre = list->HeadNode.pre;
node->next = list->HeadNode.pre->next; list->HeadNode.pre->next = node;
list->HeadNode.pre = node; list->NodeCount ++;
} tNode* RemoveFirstNode(tList *list)//移除第一个节点
{
tNode *node = (tNode *);
if (list->HeadNode.next != )
{
node = list->HeadNode.next; node->next->pre = &(list->HeadNode);
list->HeadNode.next = node->next; list->NodeCount --; free(node);
}
else
{
return node;
}
} void tListInsertAfter(tList * list, tNode * nodeAfter, tNode * nodeToInsert)//在一个节点后添加一个节点
{
nodeToInsert->next = nodeAfter->next;
nodeToInsert->pre = nodeAfter; nodeAfter->next->pre = nodeToInsert;
nodeAfter->next = nodeToInsert; list->NodeCount ++;
} void tListRemove(tList * list, tNode * node)//移除节点
{
node->pre->next = node->next;
node->next->pre = node->pre; free(node); list->NodeCount --; }

在这个双向链表的实现过程中可以很好地实现队列操作,先进先出概念如这样验证:

int main()
{
tList list;
tNode *node;
int i = ; tListInit(&list); for (i = ; i < ; i++)
{
node = (tNode*)malloc(sizeof(tNode)); printf("Please input the number:");
scanf_s("%d",&node->data); tListLastAdd(&list, node);
} node = FirstNode(&list); printf("List is:");
for (i = ; i < ; i++)
{
printf("%d ",node->data);
node = node->next;
}
printf("\n");
getch();
return ;
}

实现效果为:

  在这个基础上还可以用于多种其他用处!

  PS:今天是自己第一天也是第一次写博客,在实现的过程中遇到很多问题也有很多想法,本来想一一记录但是发现写起来还是很艰辛,也许我现在就是一个小菜鸟,但是希望能够通过自己的努力一点一滴地积累逐渐成长,希望这个博客可以被我一直写下去!

                                          

                                                          写于广东海悟科技有限公司    2017-11-10    22:29:50

RTOS双向链表数据结构的更多相关文章

  1. Linux 内核里的数据结构:双向链表

    原文:https://blog.csdn.net/qq_33487044/article/details/78827260 双向链表 Linux 内核自己实现了双向链表,可以在 include/lin ...

  2. 常用数据结构-线性表及Java 动态数组 深究

    [Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...

  3. 浅谈java类集框架和数据结构(2)

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

  4. Java核心数据结构(List,Map,Set)原理与使用技巧

    JDK提供了一组主要的数据结构实现,如List.Map.Set等常用数据结构.这些数据都继承自 java.util.Collection 接口,并位于 java.util 包内. 1.List接口 最 ...

  5. 【转】Java学习---Java核心数据结构(List,Map,Set)使用技巧与优化

    [原文]https://www.toutiao.com/i6594587397101453827/ Java核心数据结构(List,Map,Set)使用技巧与优化 JDK提供了一组主要的数据结构实现, ...

  6. 双向链表-java完全解析

    原文:https://blog.csdn.net/nzfxx/article/details/51728516 "双向链表"-数据结构算法-之通俗易懂,完全解析 1.概念的引入 相 ...

  7. Java核心数据结构(List、Map、Set)原理与使用技巧

    JDK提供了一组主要的数据结构实现,如List.Set等常用数据结构.这些数据都继承自java.util.Collection接口,并位于java.util包内. 一.List接口 最重要的三种Lis ...

  8. 你真的懂Redis的5种基本数据结构吗?

    摘要: 你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看. 本文分享自华为云社区<你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看>,作者:李子捌. 一 ...

  9. [数据结构]链表相关的实现LinkList.cpp

    目录 LinkList.cpp //链表相关操作的实现 LinkList.h LinkListManager.cpp //链表相关实现函数的调用 LinkListManager.h LinkList. ...

随机推荐

  1. Water Tree(树链剖分+dfs时间戳)

    Water Tree http://codeforces.com/problemset/problem/343/D time limit per test 4 seconds memory limit ...

  2. [udemy]WebDevelopment_History of The Web

    WWW vs Internet For the begining, Internet was there. it was for the academics among universities Th ...

  3. oralce 存储过程、函数和触发器

    一.存储过程和存储函数 指存储在数据库中供所有用户程序调用的子程序叫存储过程.存储函数.   创建存储过程 用CREATE PROCEDURE命令建立存储过程. 语法: create [or repl ...

  4. IIS PHP Warning: Unknown: open(c:\\php\\tmp\\sess_xxx, O_RDWR) failed: Permission denied (13) in Unknown on line 0

    出现这个问题的原因是你修改了php保存session的路径,但没有给用户访问该目录的权限.   右键该目录,给users用户组读.写的权限.

  5. 20172325 2017-2018-2 《Java程序设计》第六周学习总结

    20172325 2017-2018-2 <Java程序设计>第六周学习总结 教材学习内容总结 1.利用[ ]建立一个数组,整列数据可以通过数组名引用,数组中的每个元素则可以通过其在数组中 ...

  6. 最近学习工作流 推荐一个activiti 的教程文档

    全文地址:http://www.mossle.com/docs/activiti/ Activiti 5.15 用户手册 Table of Contents 1. 简介 协议 下载 源码 必要的软件 ...

  7. ubuntu 'yuan' update

    #  tsinghua  university deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiv ...

  8. sklearn中的分词函数countVectorizer()的改动--保留长度为1的字符串

    1简述问题 使用countVectorizer()将文本向量化时发现,文本中长度唯一的字符串会被自动过滤掉,这对于我在做的情感分析来讲,一些表较重要的表达情感倾向的词汇被过滤掉,比如文本'没用的东西, ...

  9. 构造函数constructor 与析构函数destructor(四)

    拷贝构造函数:拷贝构造函数就是在用一个类对象来创建另外一个类对象时被调用的构造函数,如果我们没有显示的提供拷贝构造函数,编译器会隐式的提供一个默认拷贝构造函数. 拷贝构造函数的定义是X(const X ...

  10. 《Delphi XE6 android 编程入门教程》推荐

    近5.6年已经没有看见关于delphi的新技术的书出来了(看来在国内delphi的使用量确实很低了), 高勇同学最近出了一本<Delphi XE6 android 编程入门教程>,上周刚拿 ...