C语言实现标准双向链表

C语言实现标准双向链表

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

说明

本文使用C语言实现了双向链表,可以存储任意类型的数据。指针类型使用了标准库中类型intptr_t,可以兼容32位和64位系统。
本文将链表的结构封装在list.c中,对外提供了一些操作API,并可以传入任意结构的数据到链表中。这样提高了代码的抽象性和复用性,并简化了操作。

注意

链表涉及到指针操作,操作不当易导致内存泄漏。本文虽做了一定程度的封装,但应用到项目中,还是要阅读源码理解后再安全的使用。

源码

list.h

/**
* Copyright (c) 2019-2019 jdh99 All rights reserved.
* @file list.h
* @brief 双向链表头文件
* @verbatim
* Change Logs:
* Date           Author       Notes
* 2019-03-04     jdh          新建
* @endverbatim
*/

#ifndef LIST_H_
#define LIST_H_

#include "stdio.h"
#include "stdbool.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"

/**
* @brief 创建双向链表
* @return 双向链表索引
*/

intptr_t list_create(void);

/**
* @brief 是否为空
* @param index:双向链表索引
* @return true:空.false:非空
*/

bool list_is_empty(intptr_t index);

/**
* @brief 获得节点中的数据
* @note 注意本函数获取的是数据.传入的指针必须要先开辟好足够空间
* @param node_index: 节点索引
* @param data_ptr: 读取的数据指针.读取的数据会复制到其中
* @return 0: 无此节点或者无数据.其他: 数据字节数
*/

uint32_t list_get_data(intptr_t node_index, uint8_t *data_ptr);

/**
* @brief 获得节点中的数据指针
* @note 注意本函数获取的是数据指针
* @param node_index: 节点索引
* @param data_ptr: 二维指针.存储数据指针
* @return 0: 无此节点或者无数据.其他: 数据字节数
*/

uint32_t list_get_data_ptr(intptr_t node_index, uint8_t **data_ptr);

/**
* @brief 删除链表
* @param index:双向链表索引的地址
*/

void list_drop(intptr_t *index_ptr);

/**
* @brief 删除所有节点
* @param index:双向链表索引
*/

void list_clear(intptr_t index);

/**
* @brief 删除节点
* @param index:双向链表索引
* @param node_index: 节点索引
*/

void list_remove(intptr_t index, intptr_t node_index);

/**
* @brief 创建空节点
* @param data_size:数据大小.单位:字节
* @return 节点索引
*/

intptr_t list_create_empty_node(uint32_t data_size);

/**
* @brief 创建节点
* @param data: 数据指针.data可以为NULL
* @param data_size:数据大小.单位:字节
* @return 节点索引
*/

intptr_t list_create_node(uint8_t *data, uint32_t data_size);

/**
* @brief 获取下个节点索引
* @param node_index: 节点索引
* @return NULL: 无下个节点.其他:下个节点索引
*/

intptr_t list_get_next_node(intptr_t node_index);

/**
* @brief 获取上个节点索引
* @param node_index: 节点索引
* @return NULL: 无上个节点.其他:上个节点索引
*/

intptr_t list_get_last_node(intptr_t node_index);

/**
* @brief 在某个节点前插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
* @param node_index: 节点索引
*/

void list_insert_before_node(intptr_t index, intptr_t new_node_index, intptr_t node_index);

/**
* @brief 在某个节点后插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
* @param node_index: 节点索引
*/

void list_insert_after_node(intptr_t index, intptr_t new_node_index, intptr_t node_index);

/**
* @brief 获取首节点
* @param index:双向链表索引
* @return NULL: 获取失败.其他:首节点索引
*/

intptr_t list_get_header(intptr_t index);

/**
* @brief 获取尾节点
* @param index:双向链表索引
* @return NULL: 获取失败.其他:尾节点索引
*/

intptr_t list_get_tail(intptr_t index);

/**
* @brief 断开链接
* @param index:双向链表索引
* @param node_index: 节点索引
*/

void list_break_link(intptr_t index, intptr_t node_index);

/**
* @brief 在列表最前面插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
*/

void list_prepend(intptr_t index, intptr_t new_node_index);

/**
* @brief 在列表最后面插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
*/

void list_append(intptr_t index, intptr_t new_node_index);

#endif

list.c

/**
* Copyright (c) 2019-2019 jdh99 All rights reserved.
* @file list.h
* @brief 双向链表主文件
* @author jdh
* @verbatim
* Change Logs:
* Date           Author       Notes
* 2019-03-04     jdh          新建
* @endverbatim
*/

#include "list.h"

#pragma pack(1)

/**
* @brief 链表结构
*/

typedef struct _Node
{
    
    
    uint8_t *data_ptr;
    uint32_t data_size;

    struct _Node *next;
    struct _Node *last;
} Node, *NodePtr;

/**
* @brief 链表根节点
*/

typedef struct _Root
{
    
    
    NodePtr header;
    NodePtr tail;

    // 占据字节数指的是用户数据占据的字节数
    // 实际占据字节数还包括链表本身大小占据的字节数
    uint32_t occupied_bytes;
    uint32_t real_occupied_bytes;
} Root, *RootPtr;

#pragma pack()

/**
* @brief 删除节点后清除根节点中占据的空间
* @param root_ptr:链表根节点指针
* @param node_ptr: 节点指针
* @return false: 清除异常.true:清除成功
*/

static bool delete_node_occupied(RootPtr root_ptr, NodePtr node_ptr);

static void insert_fisrt_node(RootPtr root_ptr, NodePtr new_node_ptr);

/**
* @brief 创建双向链表
* @return 双向链表索引
*/

intptr_t list_create(void)
{
    
    
    RootPtr root_ptr = (RootPtr)malloc(sizeof(Root));
    root_ptr->header = NULL;
    root_ptr->tail = NULL;
    root_ptr->occupied_bytes = 0;
    root_ptr->real_occupied_bytes = sizeof(Root);
    return (intptr_t)root_ptr;
}

/**
* @brief 是否为空
* @param index:双向链表索引
* @return true:空.false:非空
*/

bool list_is_empty(intptr_t index)
{
    
    
    RootPtr root_ptr = (RootPtr)index;
    if (root_ptr == NULL)
    {
    
    
        return true;
    }

    return (root_ptr->header == NULL);
}

/**
* @brief 获得节点中的数据
* @note 注意本函数获取的是数据.传入的指针必须要先开辟好足够空间
* @param node_index: 节点索引
* @param data_ptr: 读取的数据指针.读取的数据会复制到其中
* @return 0: 无此节点或者无数据.其他: 数据字节数
*/

uint32_t list_get_data(intptr_t node_index, uint8_t *data_ptr)
{
    
    
    if (node_index == (intptr_t)NULL)
    {
    
    
        return 0;
    }

    NodePtr node_ptr = (NodePtr)node_index;
    memcpy(data_ptr, node_ptr->data_ptr, node_ptr->data_size);
    return node_ptr->data_size;
}

/**
* @brief 获得节点中的数据指针
* @note 注意本函数获取的是数据指针
* @param node_index: 节点索引
* @param data_ptr: 二维指针.存储数据指针
* @return 0: 无此节点或者无数据.其他: 数据字节数
*/

uint32_t list_get_data_ptr(intptr_t node_index, uint8_t **data_ptr)
{
    
    
    if (node_index == (intptr_t)NULL)
    {
    
    
        return 0;
    }

    NodePtr node_ptr = (NodePtr)node_index;
    *data_ptr = node_ptr->data_ptr;
    return node_ptr->data_size;
}

/**
* @brief 删除链表
* @param index:双向链表索引的地址
*/

void list_drop(intptr_t *index_ptr)
{
    
    
    if (index_ptr == NULL || *index_ptr == (intptr_t)NULL)
    {
    
    
        return;
    }

    list_clear(*index_ptr);
    free((void *)(*index_ptr));
    *index_ptr = (intptr_t)NULL;
}

/**
* @brief 删除所有节点
* @param index:双向链表索引
*/

void list_clear(intptr_t index)
{
    
    
    if (index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    while (1)
    {
    
    
        if (root_ptr->header == NULL)
        {
    
    
            break;
        }
        list_remove(index, (intptr_t)(root_ptr->header));
    }
}

/**
* @brief 删除节点
* @param index:双向链表索引
* @param node_index: 节点索引
*/

void list_remove(intptr_t index, intptr_t node_index)
{
    
    
    if (index == (intptr_t)NULL || node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    NodePtr node_ptr = (NodePtr)node_index;
    if (node_ptr->last != NULL)
    {
    
    
        node_ptr->last->next = node_ptr->next;
    }
    else
    {
    
    
        // 删除的是首节点
        root_ptr->header = node_ptr->next;
    }
    if (node_ptr->next != NULL)
    {
    
    
        node_ptr->next->last = node_ptr->last;
    }
    else
    {
    
    
        // 删除的是尾节点
        root_ptr->tail = node_ptr->last;
    }
    free(node_ptr->data_ptr);
    node_ptr->data_ptr = NULL;
    if (delete_node_occupied(root_ptr, node_ptr) == false)
    {
    
    
        // todo
    }

    free(node_ptr);
    node_ptr = NULL;
}

/**
* @brief 删除节点后清除根节点中占据的空间
* @param root_ptr:链表根节点指针
* @param node_ptr: 节点指针
* @return false: 清除异常.true:清除成功
*/

static bool delete_node_occupied(RootPtr root_ptr, NodePtr node_ptr)
{
    
    
    if (root_ptr->occupied_bytes < node_ptr->data_size)
    {
    
    
        return false;
    }

    root_ptr->occupied_bytes -= node_ptr->data_size;
    root_ptr->real_occupied_bytes -= node_ptr->data_size + sizeof(Node);
    return true;
}

/**
* @brief 创建空节点
* @param data_size:数据大小.单位:字节
* @return 节点索引
*/

intptr_t list_create_empty_node(uint32_t data_size)
{
    
    
    NodePtr node_ptr = (NodePtr)malloc(sizeof(Node));
    node_ptr->last = NULL;
    node_ptr->next = NULL;
    node_ptr->data_ptr = NULL;
    node_ptr->data_size = 0;

    if (data_size > 0)
    {
    
    
        node_ptr->data_ptr = malloc(data_size);
        node_ptr->data_size = data_size;
        memset(node_ptr->data_ptr, 0, node_ptr->data_size);
    }
    else
    {
    
    
        node_ptr->data_ptr = NULL;
        node_ptr->data_size = 0;
    }

    return (intptr_t)node_ptr;
}

/**
* @brief 创建节点
* @param data: 数据指针.data可以为NULL
* @param data_size:数据大小.单位:字节
* @return 节点索引
*/

intptr_t list_create_node(uint8_t *data, uint32_t data_size)
{
    
    
    NodePtr node_ptr = (NodePtr)(list_create_empty_node(data_size));
    if (data != NULL && data_size > 0)
    {
    
     
        memcpy(node_ptr->data_ptr, data, data_size);
    }
    return (intptr_t)node_ptr;
}

/**
* @brief 获取下个节点索引
* @param node_index: 节点索引
* @return NULL: 无下个节点.其他:下个节点索引
*/

intptr_t list_get_next_node(intptr_t node_index)
{
    
    
    if (node_index == (intptr_t)NULL)
    {
    
    
        return (intptr_t)NULL;
    }

    NodePtr node_ptr = (NodePtr)node_index;
    return (intptr_t)(node_ptr->next);
}

/**
* @brief 获取上个节点索引
* @param node_index: 节点索引
* @return NULL: 无上个节点.其他:上个节点索引
*/

intptr_t list_get_last_node(intptr_t node_index)
{
    
    
    if (node_index == (intptr_t)NULL)
    {
    
    
        return (intptr_t)NULL;
    }

    NodePtr node_ptr = (NodePtr)node_index;
    return (intptr_t)(node_ptr->last);
}

/**
* @brief 在某个节点前插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
* @param node_index: 节点索引
*/

void list_insert_before_node(intptr_t index, intptr_t new_node_index, intptr_t node_index)
{
    
    
    if (index == (intptr_t)NULL || new_node_index == (intptr_t)NULL || node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    NodePtr node_ptr = (NodePtr)node_index;
    NodePtr new_node_ptr = (NodePtr)new_node_index;

    new_node_ptr->last = node_ptr->last;
    new_node_ptr->next = node_ptr;

    if (node_ptr->last != NULL)
    {
    
    
        node_ptr->last->next = new_node_ptr;
    }
    else
    {
    
    
        // 首节点
        root_ptr->header = (NodePtr)new_node_index;
    }
    node_ptr->last = new_node_ptr;

    root_ptr->occupied_bytes += new_node_ptr->data_size;
    root_ptr->real_occupied_bytes += new_node_ptr->data_size + sizeof(Node);
}

/**
* @brief 在某个节点后插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
* @param node_index: 节点索引
*/

void list_insert_after_node(intptr_t index, intptr_t new_node_index, intptr_t node_index)
{
    
    
    if (new_node_index == (intptr_t)NULL || node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    NodePtr node_ptr = (NodePtr)node_index;
    NodePtr new_node_ptr = (NodePtr)new_node_index;

    new_node_ptr->last = node_ptr;
    new_node_ptr->next = node_ptr->next;

    if (node_ptr->next != NULL)
    {
    
    
        node_ptr->next->last = new_node_ptr;
    }
    else
    {
    
    
        // 尾节点
        root_ptr->tail = (NodePtr)new_node_index;
    }
    node_ptr->next = new_node_ptr;

    root_ptr->occupied_bytes += new_node_ptr->data_size;
    root_ptr->real_occupied_bytes += new_node_ptr->data_size + sizeof(Node);
}

/**
* @brief 获取首节点
* @param index:双向链表索引
* @return NULL: 获取失败.其他:首节点索引
*/

intptr_t list_get_header(intptr_t index)
{
    
    
    if (index == (intptr_t)NULL)
    {
    
    
        return (intptr_t)NULL;
    }

    RootPtr root_ptr = (RootPtr)index;
    return (intptr_t)(root_ptr->header);
}

/**
* @brief 获取尾节点
* @param index:双向链表索引
* @return NULL: 获取失败.其他:尾节点索引
*/

intptr_t list_get_tail(intptr_t index)
{
    
    
    if (index == (intptr_t)NULL)
    {
    
    
        return (intptr_t)NULL;
    }

    RootPtr root_ptr = (RootPtr)index;
    return (intptr_t)(root_ptr->tail);
}

/**
* @brief 断开链接
* @param index:双向链表索引
* @param node_index: 节点索引
*/

void list_break_link(intptr_t index, intptr_t node_index)
{
    
    
    if (index == (intptr_t)NULL || node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    NodePtr node_ptr = (NodePtr)node_index;
    if (node_ptr->last != NULL)
    {
    
    
        node_ptr->last->next = node_ptr->next;
    }
    if (node_ptr->next != NULL)
    {
    
    
        node_ptr->next->last = node_ptr->last;
    }
    node_ptr->last = NULL;
    node_ptr->next = NULL;

    if (delete_node_occupied(root_ptr, node_ptr) == false)
    {
    
    
        // todo
    }
}

/**
* @brief 在列表最前面插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
*/

void list_prepend(intptr_t index, intptr_t new_node_index)
{
    
    
    if (index == (intptr_t)NULL || new_node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    if (root_ptr->header == NULL)
    {
    
    
        insert_fisrt_node(root_ptr, (NodePtr)new_node_index);
        return;
    }
    list_insert_before_node(index, new_node_index, (intptr_t)(root_ptr->header));
    root_ptr->header = (NodePtr)new_node_index;
}

static void insert_fisrt_node(RootPtr root_ptr, NodePtr new_node_ptr)
{
    
    
    root_ptr->header = new_node_ptr;
    root_ptr->tail = new_node_ptr;
    root_ptr->occupied_bytes = new_node_ptr->data_size;
    root_ptr->real_occupied_bytes = new_node_ptr->data_size + sizeof(Node);
}

/**
* @brief 在列表最后面插入
* @param index:双向链表索引
* @param new_node_index: 新节点索引
*/

void list_append(intptr_t index, intptr_t new_node_index)
{
    
    
    if (index == (intptr_t)NULL || new_node_index == (intptr_t)NULL)
    {
    
    
        return;
    }

    RootPtr root_ptr = (RootPtr)index;
    if (root_ptr->header == NULL)
    {
    
    
        insert_fisrt_node(root_ptr, (NodePtr)new_node_index);
        return;
    }
    list_insert_after_node(index, new_node_index, (intptr_t)(root_ptr->tail));
    root_ptr->tail = (NodePtr)new_node_index;
}

测试代码:

#include "list.h"

static void test_case0(void);
static void test_case1(void);
static void test_case2(void);
static void test_case3(void);
static void test_case4(void);
static void test_case5(void);

int main()
{
    
    
    test_case0();
    test_case1();
    test_case2();
    test_case3();
    test_case4();
    test_case5();

    getchar();
    return 0;
}

static void test_case0(void)
{
    
    
    printf("-------------------->case0:尾部插入数组测试开始\n");

    uint8_t buffer[10] = {
    
    0};
    intptr_t list = list_create();

    printf("尾部插入数据:\n");
    for (uint8_t i = 0; i < 5; i++)
    {
    
    
        for (uint8_t j = 0; j < 10; j++)
        {
    
    
            buffer[j] = i;
            printf("%d\t", buffer[j]);
        }
        printf("\n");
        intptr_t node = list_create_node(buffer, 10);
        list_append(list, node);
    }

    printf("遍历读取第一个节点并删除:\n");
    while (1)
    {
    
    
        if (list_is_empty(list) == true)
        {
    
    
            break;
        }

        intptr_t node_index = list_get_header(list);
        uint32_t bytes = list_get_data(node_index, buffer);
        list_remove(list, node_index);
        for (uint8_t j = 0; j < bytes; j++)
        {
    
    
            printf("%d\t", buffer[j]);
        }
        printf("\n");
    }

    printf("-------------------->case0:测试结束\n");
}

static void test_case1(void)
{
    
    
    printf("-------------------->case1:首部插入结构体测试开始\n");

    struct Test1
    {
    
    
        int a;
        int b;
    };

    struct Test1 test1;
    intptr_t list = list_create();

    printf("首部插入数据:\n");
    for (uint8_t i = 0; i < 5; i++)
    {
    
    
        test1.a = i;
        test1.b = i;
        printf("a = %d b = %d\n", test1.a, test1.b);

        intptr_t node = list_create_node((uint8_t *)&test1, 10);
        list_prepend(list, node);
    }

    printf("遍历读取第一个节点并删除:\n");
    while (1)
    {
    
    
        if (list_is_empty(list) == true)
        {
    
    
            break;
        }

        intptr_t node_index = list_get_header(list);
        list_get_data(node_index, (uint8_t *)(&test1));
        list_remove(list, node_index);
        printf("a = %d b = %d\n", test1.a, test1.b);
    }

    printf("-------------------->case1:测试结束\n");
}

static void test_case2(void)
{
    
    
    printf("-------------------->case2:遍历队列测试开始\n");

    uint8_t buffer[10] = {
    
    0};
    intptr_t list = list_create();

    printf("插入数据:\n");
    for (uint8_t i = 0; i < 5; i++)
    {
    
    
        for (uint8_t j = 0; j < 10; j++)
        {
    
    
            buffer[j] = i;
            printf("%d\t", buffer[j]);
        }
        printf("\n");
        intptr_t node = list_create_node(buffer, 10);
        list_append(list, node);
    }

    printf("从链表首部开始遍历:\n");
    intptr_t node_index = list_get_header(list);
    while (1)
    {
    
    
        if (node_index == (intptr_t)NULL)
        {
    
    
            break;
        }
        uint32_t bytes = list_get_data(node_index, buffer);
        for (uint8_t j = 0; j < bytes; j++)
        {
    
    
            printf("%d\t", buffer[j]);
        }
        printf("\n");

        node_index = list_get_next_node(node_index);
    }

    printf("从链表尾部开始遍历:\n");
    node_index = list_get_tail(list);
    while (1)
    {
    
    
        if (node_index == (intptr_t)NULL)
        {
    
    
            break;
        }
        uint32_t bytes = list_get_data(node_index, buffer);
        for (uint8_t j = 0; j < bytes; j++)
        {
    
    
            printf("%d\t", buffer[j]);
        }
        printf("\n");

        node_index = list_get_last_node(node_index);
    }


    printf("-------------------->case2:测试结束\n");
}

static void test_case3(void)
{
    
    
    printf("-------------------->case3:1000000次写入然后清除列表测试开始\n");

    uint8_t buffer[10] = {
    
    0};
    intptr_t list = list_create();
    uint32_t num = 1000000;

    while (num--)
    {
    
    
        for (uint8_t i = 0; i < 5; i++)
        {
    
    
            for (uint8_t j = 0; j < 10; j++)
            {
    
    
                buffer[j] = i;
            }
            intptr_t node = list_create_node(buffer, 10);
            list_append(list, node);
        }

        list_clear(list);
        if (list_is_empty(list) == false)
        {
    
    
            printf("测试失败.检测到列表非空!\n");
            break;
        }
    }
    printf("-------------------->case3:测试结束\n");
}

static void test_case4(void)
{
    
    
    printf("-------------------->case4:1000000次创建然后删除列表测试开始\n");

    uint8_t buffer[10] = {
    
    0};
    uint32_t num = 1000000;

    while (num--)
    {
    
    
        intptr_t list = list_create();
        for (uint8_t i = 0; i < 5; i++)
        {
    
    
            for (uint8_t j = 0; j < 10; j++)
            {
    
    
                buffer[j] = i;
            }
            intptr_t node = list_create_node(buffer, 10);
            list_append(list, node);
        }

        list_drop(&list);
        if (list_is_empty(list) == false)
        {
    
    
            printf("测试失败.检测到列表非空!\n");
            break;
        }
    }
    printf("-------------------->case4:测试结束\n");
}

static void test_case5(void)
{
    
    
    printf("-------------------->case5:节点数据指针操作\n");

    intptr_t list = list_create();
    intptr_t node_index = list_create_empty_node(10);
    list_append(list, node_index);

    uint8_t *data_ptr = NULL;
    uint32_t data_size = list_get_data_ptr(node_index, &data_ptr);
    printf("节点大小:data_size = %d\n", data_size);
    printf("写入数据:\n");
    for (uint8_t i = 0; i < data_size; i++)
    {
    
    
        data_ptr[i] = i;
        printf("%d\t", data_ptr[i]);
    }
    printf("\n");

    intptr_t node_index_get = list_get_tail(list);
    uint8_t buffer[10] = {
    
    0};
    uint32_t data_size_get = list_get_data(node_index_get, buffer);
    printf("读取数据:\n");
    for (uint8_t i = 0; i < data_size_get; i++)
    {
    
    
        printf("%d\t", buffer[i]);
    }
    printf("\n");


    printf("-------------------->case5:测试结束\n");
}

测试输出:

-------------------->case0:尾部插入数组测试开始
尾部插入数据:
0       0       0       0       0       0       0       0       0       0
1       1       1       1       1       1       1       1       1       1
2       2       2       2       2       2       2       2       2       2
3       3       3       3       3       3       3       3       3       3
4       4       4       4       4       4       4       4       4       4
遍历读取第一个节点并删除:
0       0       0       0       0       0       0       0       0       0
1       1       1       1       1       1       1       1       1       1
2       2       2       2       2       2       2       2       2       2
3       3       3       3       3       3       3       3       3       3
4       4       4       4       4       4       4       4       4       4
-------------------->case0:测试结束
-------------------->case1:首部插入结构体测试开始
首部插入数据:
a = 0 b = 0
a = 1 b = 1
a = 2 b = 2
a = 3 b = 3
a = 4 b = 4
遍历读取第一个节点并删除:
a = 4 b = 4
a = 3 b = 3
a = 2 b = 2
a = 1 b = 1
a = 0 b = 0
-------------------->case1:测试结束
-------------------->case2:遍历队列测试开始
插入数据:
0       0       0       0       0       0       0       0       0       0
1       1       1       1       1       1       1       1       1       1
2       2       2       2       2       2       2       2       2       2
3       3       3       3       3       3       3       3       3       3
4       4       4       4       4       4       4       4       4       4
从链表首部开始遍历:
0       0       0       0       0       0       0       0       0       0
1       1       1       1       1       1       1       1       1       1
2       2       2       2       2       2       2       2       2       2
3       3       3       3       3       3       3       3       3       3
4       4       4       4       4       4       4       4       4       4
从链表尾部开始遍历:
4       4       4       4       4       4       4       4       4       4
3       3       3       3       3       3       3       3       3       3
2       2       2       2       2       2       2       2       2       2
1       1       1       1       1       1       1       1       1       1
0       0       0       0       0       0       0       0       0       0
-------------------->case2:测试结束
-------------------->case3:1000000次写入然后清除列表测试开始
-------------------->case3:测试结束
-------------------->case4:1000000次创建然后删除列表测试开始
-------------------->case4:测试结束
-------------------->case5:节点数据指针操作
节点大小:data_size = 10
写入数据:
0       1       2       3       4       5       6       7       8       9
读取数据:
0       1       2       3       4       5       6       7       8       9
-------------------->case5:测试结束

猜你喜欢

转载自blog.csdn.net/jdh99/article/details/99276008