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:測試結束
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章