15.[RT-Thread]双向链表

双向链表是操作系统中常用的数据结构,属于链表的一类。
它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱,其头指针head是唯一确定的。
因此,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。
由于双向链表具 有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。

/**************      包含的头文件        **************************/
#include "board.h"
#include "rtthread.h"

/*****************       变量       *******************************/
/* 定义线程控制块 */
static  rt_thread_t test1_thread = RT_NULL;
static  rt_thread_t test2_thread = RT_NULL;

/************************* 全局变量声明 ****************************/
/* 当我们在写应用程序的时候,可能需要用到一些全局变量。*/

/*********************    函数声明    ********************************/
static void test1_thread_entry(void* parameter);
static void test2_thread_entry(void* parameter);


/********************    链表的基本操作    ********************************/
/*双向链表结构体*/
struct rt_list_node{
    
    
    struct rt_list_node *next; /**< 指向下一个节点的指针. */
    struct rt_list_node *prev; /**< 指向上一个节点的指针. */
};

typedef struct rt_list_node rt_list_t;


/*初始化一个链表*/
rt_inline void rt_list_init(rt_list_t *l)
{
    
    
    1->next = l->prev = l;
}

/*向链表中插入结点*/
/*向链表指定节点后面插入节点rt_list_insert_after()*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
    
    
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

/*向链表指定节点前面插入节点rt_list_insert_before()*/
rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
    
    
    l->prev->next = n;
    n->prev = l->prev;

    l->prev = n;
    n->next = 1;
}

/*从链表删除节点函数rt_list_remove()源码*/
rt_inline void rt_list_remove(rt_list_t *n)
{
    
    
    n->next->prev = n->prev;
    n->prev->next = n->next;

    n->next = n->prev = n;
}

/*****************      main 函数    ************************/
int main(void)
{
    
    
    /*
    * 开发板硬件初始化,RTT系统初始化已经在main函数之前完成,
    * 即在component.c文件中的rtthread_startup()函数中完成了。
    * 所以在main函数中,只需要创建线程和启动线程即可。
    */

    rt_kprintf("这是一个[野火]- STM32全系列开发板-RTT双向链表操作实验!\n");
    test1_thread =                          /* 线程控制块指针 */
        rt_thread_create( "test1",              /* 线程名字 */
                        test1_thread_entry,   /* 线程入口函数 */
                        RT_NULL,             /* 线程入口函数参数 */
                        512,                 /* 线程栈大小 */
                        2,                   /* 线程的优先级 */
                        20);                 /* 线程时间片 */

    /* 启动线程,开启调度 */
    if (test1_thread != RT_NULL)
        rt_thread_startup(test1_thread);
    else
        return -1;

    test2_thread =                          /* 线程控制块指针 */
        rt_thread_create( "test2",              /* 线程名字 */
                        test2_thread_entry,   /* 线程入口函数 */
                        RT_NULL,             /* 线程入口函数参数 */
                        512,                 /* 线程栈大小 */
                        3,                   /* 线程的优先级 */
                        20);                 /* 线程时间片 */

    /* 启动线程,开启调度 */
    if (test2_thread != RT_NULL)
        rt_thread_startup(test2_thread);
    else
        return -1;
}

/*****************        线程定义       **************************/
static void test1_thread_entry(void* parameter)
{
    
    
    rt_list_t *head;  /* 定义一个双向链表的头节点 */
    rt_list_t *node1; /* 定义一个双向链表的头节点 */
    rt_list_t *node2; /* 定义一个双向链表的头节点 */

    /*链表初始化函数*/
    head = rt_malloc(sizeof(rt_list_t)); /*申请动态内存*/
    if(RT_NULL == head) /*没有申请成功*/
        rt_kprintf("动态内存申请失败!\n");
    else 
        rt_kprintf("动态内存申请成功,头结点地址为%的!\n",head);

    rt_kprintf("\n双向链表初始化中......\n");
    rt_list_init(head);
    if(rt_list_isempty(head))
        rt_kprintf("双向链表初始化成功!\n\n");
    
   /* 插入节点:顺序插入与从末尾插入 */
    rt_kprintf("添加节点和尾节点添加......\n");
    /* 动态申请第一个结点的内存 */
    node1 = rt_malloc(sizeof(rt_list_t));
    /* 动态申请第二个结点的内存 */
    node2 = rt_malloc(sizeof(rt_list_t));
    rt_kprintf("添加第一个节点与第二个节点......\n");

    /* 因为这是在某个节点后面添加一个节点函数
    为后面的rt_list_insert_before(某个节点之前)
    添加节点做铺垫,两个函数添加完之后的顺序是
    head -> node1 -> node2 */
    rt_list_insert_after(head, node2);
    rt_list_insert_before(head2, node1);

    if((node1->prev == head)) && (node2->prev == node1))
        rt_kprintf("添加节点成功!\n\n");
    else
        rt_kprintf("添加节点失败!\n\n");
    
    /*从链表删除节点函数rt_list_remove()实例*/
    rt_printf("删除节点......\n");
    rt_list_remove(node1);
    rt_free(node1);/* 释放第一个节点的内存 */
    if(node2->prev == head)
        rt_kprintf("删除节点成功\n\n");

}                                                                                                                                   

static void test2_thread_entry(void* parameter)
{
    
    
    /* 线程都是一个无限循环,不能返回 */
    while(1){
    
    
        rt_kprintf("线程运行中!\n");
        LED2_TOGGLE;
        rt_thread_delay(1000); //每1000ms扫描一次
    }
    
}   

猜你喜欢

转载自blog.csdn.net/shouchen1/article/details/130121312