zoukankan      html  css  js  c++  java
  • 双链表:结构体定义、创建、清除

    双链表:结构体定义、创建、清除

    一、结构体定义

    (1)双链表与单链表的区别在于,多了一个前向指针,结构体声明如下。
    (2)该声明同时利用typedef重定义了结构体类型,将struct DoubleLinkNode类型重定义为DOUBLE_LINKED_NODE类型,后续可以直接用其定义变量;
    (3)由于在结构体内需递归使用结构体定义前驱和后继指针,但是在定义指针时DOUBLE_LINKEND_NODE还未生效,所以此时只能使用struct DoubleLinkNode * 来声明指针。

    // 双链表结构体:链表内的每个节点有两个链域,一个指向前驱,一个指向后继 
    typedef struct DoubleLinkNode {
        void *data;
        // 指向前一个节点的指针
        struct DoubleLinkNode* pre;
        // 指向后一个节点的指针
        struct DoubleLinkNode* next;
    } DOUBLE_LINKED_NODE;
    

    二、创建双链表

    1、说明:输入数组指针,数组长度和数组元素大小;返回创建好的链表头指针
    2、步骤:设置头结点->逐个添加数组其他元素
    3、源码:

    
    // 创建双链表:输入数组指针,数组长度,数组元素大小;返回创建好的链表头指针
    DOUBLE_LINKED_NODE* createDoubleLinkedList(void *array, int len, int size)
    {
        DOUBLE_LINKED_NODE *newNode = NULL;
        DOUBLE_LINKED_NODE *tailNode = NULL;
        // 设置头结点,共四步:申请结构体内存,申请数据区内存,数据区赋值,指针赋值
        DOUBLE_LINKED_NODE *headNode = (DOUBLE_LINKED_NODE*)malloc(sizeof(DOUBLE_LINKED_NODE));
        headNode->data = (void*)malloc(size);
        memcpy(headNode->data, array, size);
        headNode->pre = NULL;
        headNode->next = NULL;
        // 设置尾节点
        tailNode = headNode;
    
        // 逐个加点添加,后移尾节点,
        for (int i = 1; i < len; i++) {
            // 添加新节点:参考头结点的四个步骤
            newNode = (DOUBLE_LINKED_NODE *)malloc(sizeof(DOUBLE_LINKED_NODE));
            newNode->data = (void*)malloc(size);
            memcpy(newNode->data, array + i * size, size);
            // 双链表的精髓在于指针的处理:
            // tailNode->next, 原值为NULL,表示链表结束;现在需要将指正指向nextNode
            tailNode->next = newNode;
            // newNode接在tailNode后面,所以将newNode->pre指向tailNode
            newNode->pre = tailNode;
            // newNode此时实际上是尾节点,需要将其newNode->next指向空
            newNode->next = NULL;
            // 更新尾节点的指针
            tailNode = newNode;
        }
    
        return headNode;
    }
    
    

    三、清除双链表

    // 清理双链表,释放空间(从当前节点开始,释放后续的所有链表空间,当前节点之前的空间不释放)
    int clearDoubleLinkedList(DOUBLE_LINKED_NODE *doubleLinkNode)
    {
        // 清理数据区
        if (doubleLinkNode->data != NULL) {
            free (doubleLinkNode->data);
            // 内存释放后,将指针赋空
            doubleLinkNode->data = NULL;
        }
        // 使用递归方法清理,分离本节点与后续节点,不释放之前的节点
        if (doubleLinkNode->pre != NULL) {
            // 该指针原本指向doubleLinkNode,现将其分离
            doubleLinkNode->pre->next = NULL;
        }
        doubleLinkNode->pre = NULL;
        if (doubleLinkNode->next == NULL) {
            // 链表释放完毕,无后继
            return 0;
        }
        // 还存在后续节点时,递归处理,处理下一个节点,直到无后继
        clearDoubleLinkedList(doubleLinkNode->next);
        // 释放当前节点空间: 上一层的递归处理完成后,需要释放本层的节点空间
        free(doubleLinkNode->next);
        doubleLinkNode->next = NULL;
    
        return 0;
    }
    
    

    四、测试

    测试步骤:先根据数组数据创建一个链表,输出内容后,再删除,测试代码如下:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define LIST_LEN 8
    
    // 结构体定义
    // 创建双链表函数实现
    // 删除双链表函数实现
    
    static int printfDoubleList(char *info, DOUBLE_LINKED_NODE *node)
    {
        DOUBLE_LINKED_NODE *nodeTenp = node;
        printf("%s", info);
        while (nodeTenp != NULL && nodeTenp->data != NULL) {
            printf("%d ", *(int*)(nodeTenp->data));
            nodeTenp = nodeTenp->next;
        }
        printf("
    ");
        return 0;
    }
    
    int main(void)
    {
        int array[LIST_LEN] = {0, 1, 2, 3, 9, 8, 7, 6};
        DOUBLE_LINKED_NODE *temp, *printfTemp;
        // 创建双链表
        temp = createDoubleLinkedList(array, LIST_LEN, sizeof(int));
        printfDoubleList("createDoubleLinkedList:", temp);
        // 清空双链表
        clearDoubleLinkedList(temp->next->next);
        printfDoubleList("clearDoubleLinkedList:", temp);
    
        while(1);
        return 0;
    }
    
    

    运行结果:

  • 相关阅读:
    C# Redis实战(四)
    C# Redis实战(三)
    C# Redis实战(二)
    C# Redis实战(一)
    C#连接内存数据库redis【1、Redis存读取数据】
    C#连接内存数据库redis【1、安装配置】
    c#根据配置文件反射
    内存数据库:Redis与Memcached的区别
    内存数据库:memcached与redis技术的对比试验
    【转】【涨姿势】支付宝怎么做风险控制?
  • 原文地址:https://www.cnblogs.com/HZL2017/p/14295984.html
Copyright © 2011-2022 走看看