devbox
编程先知
这个屌丝很懒,什么也没留下!
热门标签
热门文章
  • 1Android之Adapter用法总结_android setadapter
  • 2报错" href="/blog/article/detail/82574" target="_blank">vue使用scss方法(报错解决方案),及变换主题色_
    当前位置:   article > 正文

    C语言 实现一个双链表_实现一个函数,完成双链表排序功能 typedef struct dll_node

    实现一个函数,完成双链表排序功能 typedef struct dll_node

    一、 概述

    链表是一种常见的数据结构了,我们希望实现类似如下的双向链表(图片来源网络):
    这里写图片描述

    如下定义:

    typedef struct DoubleLinkList
    {
        DLNode* head;   // 链表头
        DLNode* back;  // 链表尾
        size_t size;    //链表包含的元素的个数 typedef unsigned int   size_t;  
    }DLlist;  // 双链表 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    每个元素或节点如下(图片来源网络):
    这里写图片描述

    如下定义:

    typedef struct DoubleLinkListNode
    {
        struct DoubleLinkListNode* pPre;  // 前一个节点指针
        struct DoubleLinkListNode* pNext; // 后一个节点指针
        _TYPE value;
    }DLNode;  // 节点
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结构体不熟悉的可以参考:C语言 结构体与共用体


    二、实现

    1 头文件

    编写如下doublelinklist.h头文件

    #pragma once 
    
    #define _ASC 1  // 升序排序
    #define _DESC 0  // 降序排序
    typedef int _TYPE;  // 数据类型
    
    typedef struct DoubleLinkListNode
    {
        struct DoubleLinkListNode* pPre;  // 前一个节点指针
        struct DoubleLinkListNode* pNext; // 后一个节点指针
        _TYPE value;
    }DLNode;  // 节点
    
    typedef struct DoubleLinkList
    {
        DLNode* head;   // 链表头
        DLNode* back;  // 链表尾
        size_t size;    //链表包含的元素的个数 typedef unsigned int   size_t;  
    }DLlist;  // 双链表 
    
    // 对一个新链表进行初始化
    void init(DLlist* pList);
    
    // 快速创建一个空的双链表
    DLlist* _createList(); 
    
    // 使用可变参数来创建一个链表
    DLlist* _createListWithValues(int length, ...);
    
    // 使用数组来创建一个链表
    DLlist* _createListWithArrayValues(_TYPE array[], int length);
    
    // 插入到头部,返回1插入成功
    int addToHead(DLlist* pList, _TYPE value);
    
    // 插入到尾部,返回1插入成功
    int addToBack(DLlist* pList, _TYPE value);
    
    // 将一维数组的值添加到链表头部,返回1插入成功
    int addToHeadWithArrayValues(DLlist* pList, _TYPE array[], int length);
    
    // 将一维数组的值添加到链表尾部,返回1插入成功
    int addToBackWithArrayValues(DLlist* pList,_TYPE array[], int length);
    
    // 插入到指定元素的后面,返回1插入成功
    int insertAfter(DLlist* pList, _TYPE curValue, _TYPE newValue);
    
    // 插入到指定元素的后面,返回1插入成功,改进版
    int insertAfter2(DLlist* pList, _TYPE curValue, _TYPE newValue);
    
    // 插入到指定元素的前面,返回1插入成功
    int insertBefore(DLlist* pList, _TYPE curValue, _TYPE newValue);
    
    // 插入到指定元素的前面,返回1插入成功,改进版
    int insertBefore2(DLlist* pList, _TYPE curValue, _TYPE newValue);
    
    // 删除第一个节点,并返回它
    DLNode* removeFirst(DLlist* pList);
    
    // 删除最后一个节点,并返回它
    DLNode* removeLast(DLlist* pList);
    
    // 正向显示所有
    void showAll(DLlist* pList);
    
    // 使用递归正向显示所有
    void showAllWithRecursion(DLNode* head);
    
    // 反向显示所有
    void showAllReverse(DLlist* pList); 
    
    // 使用递归反向显示所有
    void showAllReverseWithRecursion(DLNode* back);
    
    // 删除指定元素,返回1删除成功
    int deleteNode(DLlist* pList, _TYPE value);
    
    // 删除指定元素,返回1删除成功,deleteNode改进版
    int deleteNode2(DLlist* pList, _TYPE value);
    
    // 删除一个范围的元素,从fromValue的节点开始删除,删除count个
    int deleteRange(DLlist* pList, _TYPE fromValue,int count);
    
    // 检查是否为空
    int checkNull(void* p);
    
    // 修改指定的值,返回1修改成功
    int modify(DLlist* pList, _TYPE oldValue, _TYPE newValue);
    
    // 释放所有元素,清空链表,返回1则成功
    int freeAll(DLlist* pList);
    
    // 从第一个匹配元素开始释放,返回1删除成功
    int freeFrom(DLlist* pList, _TYPE value);
    
    // 通过值找到指定匹配的第一个节点
    DLNode* findByValue(DLlist* pList, _TYPE value);
    
    // 将一个链表插入当前链表的尾部
    int addListToBack(DLlist* pList, DLlist* addingList);
    
    // 获取指定值的节点在链表中的深度
    int getDepth(DLlist* pList, _TYPE value);
    
    // 是否为空,返回1则为空
    int isEmpty(DLlist* pList);  
    
    // 对链表值进行排序,asc为0则降序序排,否则升序。可以使用_ASC(升序) , _DESC(降序)
    void sort(DLlist* pList,int asc);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109

    2 函数实现

    在DoubleLinkList.c中实现。下面将函数分个显示

    void init (DLlist* pList);

    用于给通过DoubleLinkList创建的新链表进行初始化

    void init(DLlist* pList)
    {
        pList->head = pList->back = NULL;
        pList->size = 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    DLlist* _createList();

    快速创建一个双链表

    DLlist* _createList()
    {
        DLlist* pList = (DLlist*)malloc(sizeof(DLlist));
        pList->head = pList->back = NULL;
        pList->size = 0;
        return pList;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    DLlist* _createListWithValues (int length, …)

    使用可变参数来创建一个链表,需要声明头文件#include<stdarg.h>
    
    • 1
    DLlist* _createListWithValues(int length, ...)
    {
        DLlist* pList = _createList();
    
        va_list ap; // 参数指针
        va_start(ap, length); // 第一个元素
        for (int i = 0; i < length; i++)
        {
            addToBack(pList,va_arg(ap, _TYPE)); // 返回对应类型的数据,并添加到链表
        }
        va_end(ap);
    
        return pList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    DLlist* _createListWithArrayValues (_TYPE array[], int length)

    使用数组的元素来创建一个链表,length表示要添加到链表的个数

    
    DLlist* _createListWithArrayValues(_TYPE array[], int length)
    {
        if (checkNull(array)|| 0==length)
        {
            return NULL;
        }
    
        DLlist* pList =  _createList();
        if (checkNull(pList))
        {
            return NULL;
        }
    
        if (addToBackWithArrayValues(pList, array, length))
        {
            return pList;
        }
    
        return NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    int addToHead (DLlist* pList, _TYPE value);

    插入双链表的头部,返回1则表示插入成功

    int addToHead(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            return 0;
        }
    
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;   // 创建新节点失败,则返回
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = value;
    
        if (pList->head==NULL)  // 若头节点为空,则新节点置为头节点
        {
            pList->head = newNode;
            pList->back = newNode;
            pList->size++;
        }
        else    // 添加到头部
        {
            newNode->pNext = pList->head;
            pList->head->pPre = newNode;
            pList->head = newNode;  // 将链表的头部设为新节点  
            pList->size++;
        }
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    int addToBack (DLlist* pList, _TYPE value);

    插入到双链表的尾部,返回1插入成功

    int addToBack(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;   // 创建新节点失败,则返回
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = value;
        if (NULL == pList->head)  // 若头节点为空,则新节点置为头节点
        {
            pList->head = newNode;
            pList->back = newNode;
            pList->head->pNext = pList->back->pNext = NULL;
            pList->size++;
        }
        else if (pList->size == 1)  // 只有一个元素,头尾都指向它,链接好头部与下一个节点
        {
            newNode->pPre = pList->head;
            pList->head->pNext = newNode;
            pList->back = newNode;
            pList->size++;
        }
        else  // 添加到尾部
        {
            newNode->pPre = pList->back;
            pList->back->pNext = newNode;
            pList->back = newNode;
            pList->size++;
        }
    
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    int addToHeadWithArrayValues (DLlist* pList, _TYPE array[], int length)

    将一维数组的值添加到链表头部,返回1插入成功

    int addToHeadWithArrayValues (DLlist* pList, _TYPE array[], int length)
        {
            if (checkNull(pList) || checkNull(array) || length == 0)
            {
                return 0;
            }
    
            for (int i = 0; i < length; i++)
            {
                if (!addToHead(pList, array[i]))
                {
                    return 0;
                }
            }
    
            return 1;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    int addToBackWithArrayValues (DLlist* pList, _TYPE array[], int length)

    将一维数组的值添加到链表尾部,返回1插入成功

    int addToBackWithArrayValues(DLlist* pList, _TYPE array[], int length)
        {
            if (checkNull(pList) || checkNull(array) || length == 0)
            {
                return 0;
            }
    
            for (int i = 0; i < length; i++)
            {
                if (!addToBack(pList, array[i]))
                {
                    return 0;
                }
            }
    
            return 1;
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    int insertAfter (DLlist* pList, _TYPE curValue, _TYPE newValue);

    插入到指定值curValue的节点元素的后面,返回1则插入成功

    int insertAfter(DLlist* pList, _TYPE curValue, _TYPE newValue)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:插入指定节点后面失败,空链表\n");
            return 0;
        }
    
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;   // 创建新节点失败,则返回
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = newValue;
    
        if (pList->head->value==curValue)  // 头节点满足
        {
            DLNode* next = pList->head->pNext;
            next->pPre = newNode;
            newNode->pNext = next;
            newNode->pPre = pList->head;
            pList->head->pNext = newNode;
            pList->size++;
            return 1;
        }
        else if (pList->back->value == curValue)  // 尾节点满足,防止要遍历一遍,浪费时间
        {
            pList->back->pNext = newNode;
            newNode->pPre = pList->back->pNext;
            pList->back;
            pList->size++;
            return 1;
        }
        else  // 其他
        {
            DLNode* p = pList->head->pNext;
            while (p)
            {
                if (p->value==curValue)
                {
                    DLNode* next = p->pNext;
                    next->pPre = newNode;
                    newNode->pNext = next;
                    newNode->pPre = p;
                    p->pNext = newNode;
                    pList->size++;
                    return 1;
                }
                p = p->pNext;
            }
        }
    
        return 0;
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    int insertAfter2 (DLlist* pList, _TYPE curValue, _TYPE newValue);

    插入到指定值curValue的节点元素的后面,返回1插入成功,insertAfter改进版

    int insertAfter2(DLlist* pList, _TYPE curValue, _TYPE newValue)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:插入指定节点后面失败,空链表\n");
            return 0;
        }
        DLNode* curNode = findByValue(pList, curValue); // 查找指定节点
        if (checkNull(pList))
        {
            printf("\n插入失败,目标节点value=%d不存在\n", curNode);
            return 0;
        }
    
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = newValue;
        if (curNode==pList->back)
        {
            pList->back->pNext = newNode;
            newNode->pPre = pList->back;
            pList->back = newNode;
            pList->size++;
        }
        else
        {
            DLNode* nextNode = curNode->pNext;
            newNode->pPre = curNode;
            newNode->pNext = nextNode;
            curNode->pNext = newNode;
            nextNode->pPre = newNode;
            pList->size++;
        }
    
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    int insertBefore (DLlist* pList, _TYPE curValue, _TYPE newValue);

    插入到指定值curValue的节点元素的前面,返回1则插入成功

    int insertBefore(DLlist* pList, _TYPE curValue, _TYPE newValue)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:插入指定节点前面失败,空链表\n");
            return 0;
        }
    
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = newValue;
        if (curValue == pList->head->value)  // 头节点满足
        {
            newNode->pNext = pList->head;
            pList->head->pPre = newNode;
            pList->head = newNode;
            pList->size++;
            return 1;
        }
        else if(pList->back->value == curValue) // 尾节点满足
        {
            newNode->pNext = pList->back;
            newNode->pPre = pList->back->pPre;
            pList->back->pPre->pNext = newNode; // 改变尾节点前面一个节点的指向,到newNode  
            pList->back->pPre = newNode;// 添加到尾节点前面
            pList->size++;
            return 1;
        }
        else
        {
            DLNode* curNode = pList->head->pNext;
            while (curNode)
            {
                if (curNode->value == curValue)
                {
                    DLNode* preNode =  curNode->pPre;
                    newNode->pNext = curNode;
                    newNode->pPre = preNode;
                    curNode->pPre = newNode;   // 添加到当前结点前面
                    preNode->pNext = newNode;
                    pList->size++;
                    return 1;
                }
                curNode = curNode->pNext;
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    int insertBefore2 (DLlist* pList, _TYPE curValue, _TYPE newValue);

    插入到指定值curValue的节点元素的前面,返回1则插入成功,insertBefore改进版

    int insertBefore2(DLlist* pList, _TYPE curValue, _TYPE newValue)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:插入指定节点后面失败,空链表\n");
            return 0;
        }
    
        DLNode* curNode = findByValue(pList, curValue); // 查找指定节点
        if (checkNull(pList))
        {
            printf("\n插入失败,目标节点value=%d不存在\n", curNode);
            return 0;
        }
    
        DLNode* newNode = (DLNode*)malloc(sizeof(DLNode));
        if (checkNull(newNode))
        {
            return 0;
        }
        newNode->pNext = newNode->pPre = NULL;
        newNode->value = newValue;
    
        if (curNode==pList->head)
        {
            newNode->pNext = pList->head;
            pList->head->pPre = newNode;
            pList->head = newNode;
            pList->size++;
        }
        else
        {
    
            DLNode* preNode = curNode->pPre;
            newNode->pNext = curNode;
            newNode->pPre = preNode;
            curNode->pPre = newNode;
            preNode->pNext = newNode;
            pList->size++;
        }
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    DLNode* removeFirst (DLlist* pList);

    删除第一个节点,并返回它

    DLNode* removeFirst(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return NULL;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return NULL;
        }
        if (pList->head->pNext==NULL)   // 只有head
        {
            DLNode* head = pList->head;
            pList->head = NULL;
            pList->size--;
            return head;
        }
        else
        {
            DLNode* head = pList->head;
            DLNode* next = head->pNext;
            head->pNext = NULL;
            next->pPre = NULL;
            pList->head = next;
            pList->size--;
            return head;
        }
    
        return NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    DLNode* removeLast (DLlist* pList);

    删除最后一个节点,并返回它

    DLNode* removeLast(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return NULL;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return NULL;
        }
        if (pList->back==pList->head)
        {
            return removeFirst(pList);
        }
        else
        {
            DLNode* back = pList->back;
            DLNode* preNode = back->pPre;
            back->pPre = NULL;
            preNode->pNext = NULL;
            pList->back = preNode;
            pList->size--;
            return back;
        }
        return NULL;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    void showAll (DLlist* pList);

    正向显示所有节点值

    void showAll(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return;
    
        }
        else
        {
            if (isEmpty(pList))
            {
                printf("\nlog:showAll 空链表\n");
                return;
            }
            printf("\n[  ");
            DLNode* p = pList->head;
            while (p!=NULL)
            {
                printf("%d  ", p->value);
                p = p->pNext;  // 往后遍历
            }
            printf("]\n");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    void showAllWithRecursion (DLNode* head);

    使用递归正向显示所有节点的值

    void showAllWithRecursion(DLNode* head)
    {
        static count = 0;
    
        if (NULL==head)
        {
            printf("]\n"); // 打印结束 ]
            count = 0;
            return;
        }
        else
        {
            if (count == 0)   // 打印起始 [
            {
                printf("\n[  ");
            }
            count++;
            printf("%d  ", head->value);
            showAllWithRecursion(head->pNext); // 递归调用,打印后面一个
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    void showAllReverse (DLlist* pList);

    反向显示所有节点的值

    void showAllReverse(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
        printf("\n[  ");
        DLNode* p = pList->back;
        while (p!=NULL) 
        {
            printf("%d  ", p->value);
            p = p->pPre;  // 往前遍历
        }
        printf("]\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    void showAllReverseWithRecursion (DLNode* back);

    使用递归反向显示所有节点的值

    void showAllReverseWithRecursion(DLNode* back)
    {
        if (NULL ==back)
        {
            printf("\n");
            return;
        }
        else
        {
            printf("%d\t", back->value);
            showAllReverseWithRecursion(back->pPre); // 递归调用,打印前一个
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    int deleteNode (DLlist* pList, _TYPE value);

    删除第一个指定元素的节点,返回1则删除成功

    int deleteNode(DLlist* pList, _TYPE value)
    {
    
        if (checkNull(pList))
        {
            printf("\nlog:删除节点失败\n");
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:删除节点失败,空链表\n");
            return 0;
        }
        DLNode* findNode = findByValue(pList, value);
        if (checkNull(findNode))
        {
            printf("\nlog:要删除的节点不存在,value=%d\n", value);
            return 0;
        }
        if (value == pList->head->value)  // 头节点满足
        {
            if (pList->head->pNext==NULL)  // 只有head时
            {
                DLNode* curNode = pList->head;
                pList->head = pList->back = NULL;  // 删除所有节点后将head与back都赋值NULL
                free(curNode);
            }
            else
            {
                DLNode* curNode = pList->head;
                pList->head = curNode->pNext;   // 头节点后移
                free(curNode);
    
            }
            pList->size--;
            return 1;
        }
        else if (value == pList->back->value)   // 尾节点满足
        {
            DLNode* curNode = pList->back;
            pList->back = curNode->pPre;
            pList->back->pNext = NULL;
            free(curNode);
            pList->size--;
            return 1;
        }
        else
        {
            DLNode* curNode = pList->head->pNext;
            while (curNode!=NULL)       // 下面可以调用findByValue来查找指定节点
            {
                if (curNode->value==value)  // 删除满足条件的节点
                {
                    DLNode* preNode = curNode->pPre;
                    DLNode* nextNode = curNode->pNext;
                    preNode->pNext = nextNode;
                    nextNode->pPre = preNode;
                    free(curNode);  // 释放内存
                    pList->size--;
                    return 1;
                }
                curNode = curNode->pNext;
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    int deleteNode2 (DLlist* pList, _TYPE value)

    删除指定元素,返回1删除成功,deleteNode改进版

    int deleteNode2(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            printf("\nlog:删除节点失败\n");
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:删除节点失败,空链表\n");
            return 0;
        }
        DLNode* findNode = findByValue(pList, value);
        if (checkNull(findNode))
        {
            printf("\nlog:要删除的节点不存在,value=%d\n", value);
            return 0;
        }
        if (findNode==pList->head)
        {
            DLNode* curNode = pList->head;
            pList->head = curNode->pNext;
            pList->head->pPre = NULL;
            free(curNode);
            pList->size--;
        }
        else
        {
            DLNode* preNode = findNode->pPre;
            DLNode* next = findNode->pNext;
            preNode->pNext = next;
            next->pPre = preNode;  // 上一个节点与下一个节点连接起来
            free(findNode);
            pList->size--;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    int deleteRange (DLlist* pList, _TYPE fromValue,int count);

    删除一个范围的元素节点,从fromValue值的节点开始删除,删除count个。返回1表示删除成功

    int deleteRange(DLlist* pList, _TYPE fromValue, int count)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
    
        DLNode* curNode = findByValue(pList,fromValue);
        if (checkNull(curNode))
        {
            return 0;
        }
    
        int num = 0;
        if (curNode==pList->head)   // 如果是头节点
        {
            while (num < count && deleteNode(pList, pList->head->value))    // 从头部开始删除count个
            {
                ++num;
            }
            return 1;
        }
        else
        {
            DLNode* preNode = curNode->pPre;
            while (curNode)
            {
                if (num<count)
                {
                    preNode->pNext = curNode->pNext;
                    curNode->pPre = preNode;
                    free(curNode);
                    ++num;
                }
                else
                {
                    break;
                }
                curNode = preNode->pNext;
            }
        }
    
        if (num == count || NULL == curNode) // 如果删除了指定数量或已经是尾节点下一个了
        {
            pList->size -= (num==count)?  count:  num;
            return 1;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    int checkNull (void* p);

    检查指针是否为空

    int checkNull(void* p)
    {
        if (NULL == p)
        {
            printf("\nlog: null pointer\n");
            return 1;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    int modify (DLlist* pList, _TYPE oldValue, _TYPE newValue);

    修改指定的值的节点,返回1表示修改成功

    int modify(DLlist* pList, _TYPE oldValue, _TYPE newValue)
    {
        if (checkNull(pList) )
        {
            return 0;
        }
    
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
        DLNode* curNode = pList->head;
        while (curNode)
        {
            if (curNode->value==oldValue)
            {
                curNode->value = newValue;
                return 1;
            }
            curNode = curNode->pNext;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    int freeAll (DLlist* pList);

    释放所有元素,清空链表,返回1则成功

    int freeAll(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
        DLNode* curNode = pList->head->pNext;
        while (curNode)     // 循环删除头节点的下一个节点
        {
            pList->head->pNext = curNode->pNext;
            free(curNode);
            curNode = pList->head->pNext;
        }
    
        free(pList->head);  // 删除头节点
        pList->head = pList->back = NULL;
        pList->size = 0;
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    int freeFrom (DLlist* pList, _TYPE value);

    从第一个匹配值的节点开始释放,截断并丢弃从指定值节点开始到结尾的链。返回1删除成功

    int freeFrom(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
    
        DLNode* curNode = findByValue(pList, value);
        if (curNode==NULL)
        {
            printf("\nlog: 要删除value=%d的起始节点不存在\n",value);
            return 0;
        }
        if (curNode==pList->head)
        {
            return freeAll(pList);
        }
        else
        {
            DLNode* preNode = curNode->pPre;
            int depth = getDepth(pList, preNode->value);
            DLlist* dyingList = (DLlist*)malloc(sizeof(DLlist)); // 将要被删除的链表
            if (checkNull(dyingList))
            {
                return 0;
            }
            dyingList->head = curNode;
            freeAll(dyingList);  // 调用freeAll来删除
            free(dyingList);
            preNode->pNext = NULL;  // 将curNode的上一个节点的pNext置NULL
            pList->back = preNode;  // 重新设置尾节点
            pList->size = depth;
        }
    
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    DLNode* findByValue (DLlist* pList, _TYPE value);

    通过值找到指定匹配的第一个节点

    DLNode* findByValue(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            return 0;
        }
        if (isEmpty(pList))
        {
            printf("\nlog:空链表\n");
            return 0;
        }
    
        DLNode* curNode = pList->head;
        while (curNode)
        {
            if (curNode->value==value)
            {
                return curNode;
            }
            curNode = curNode->pNext;
        }
        return NULL;  // 没有找到还回空
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    int addListToBack (DLlist* pList, DLlist* addingList);

    将一个链表插入当前链表的尾部

    int addListToBack(DLlist* pList, DLlist* addingList)
    {
        if (checkNull(pList)|| checkNull(addingList)||isEmpty(addingList))
        {
            return 0;
        }
    
        DLNode* curNode = addingList->head;
        while (curNode)
        {
            addToBack(pList, curNode->value);   // 添加到尾部
            curNode = curNode->pNext;
        }
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    int getDepth (DLlist* pList, _TYPE value);

    获取指定值的节点在链表中的深度

    int getDepth(DLlist* pList, _TYPE value)
    {
        if (checkNull(pList))
        {
            return -1;
        }
        if (isEmpty(pList))
        {
            return 0;
        }
        DLNode* curNode = pList->head;
        int depth = 0;
        while (curNode)
        {
            depth++;
            if (curNode->value==value)
            {
                return depth;
            }
            curNode = curNode->pNext;
        }
    
        return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    int isEmpty (DLlist* pList);

    判断链表是否为空,返回1则为空

    int isEmpty(DLlist* pList)
    {
        if (checkNull(pList))
        {
            return 1;
        }
        return pList->size == 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    void sort (DLlist* pList, int asc)

    使用选择排序法对链表值进行排序,asc为0则降序序排,否则升序。可以使用_ASC(升序) , _DESC(降序)

    void sort(DLlist* pList, int asc)
    {
        if (checkNull(pList) || isEmpty(pList))
        {
            return;
        }
        for (DLNode *pi = pList->head; pi->pNext!=NULL; pi = pi->pNext)
        {
            DLNode *pk = pi;
            for (DLNode *pj = pi->pNext; pj!= NULL; pj = pj->pNext)
            {
                if (asc && pk->value > pj->value)       // 排升序
                {
                    pk = pj;
                }
                if (!asc && pk->value < pj->value)      // 排降序
                {
                    pk = pj;
                }
            }
    
            if (pk!=pi)
            {
                _TYPE value = pk->value;
                pk->value = pi->value;
                pi->value = value;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3 使用示例

    测试1:创建、添加到头尾、修改、删除节点、显示所有

    void main()
    {
        DLlist* pList =  _createList();  // 创建一个双链表
        addToHead(pList, 1);    // 插入数据到头
        addToHead(pList, 2);
        addToHead(pList, 3);
        addToHead(pList, 4);
        addToHead(pList, 5);
    
        addToBack(pList, 11); // 插入数据到尾
        addToBack(pList, 22);
        addToBack(pList, 33);
        addToBack(pList, 44);
        addToBack(pList, 55);
    
        showAll(pList); // 正向显示所有
        showAllReverse(pList); // 反向显示所有
    
        modify(pList, 11, 66);  // 将11修改为66
        showAll(pList); // 正向显示所有
        printf("size=%d\n", pList->size);
    
        deleteNode(pList, 33);
        showAll(pList); // 正向显示所有
        printf("size=%d\n", pList->size); // 双链表的大小
    
        system("pause");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    输出:

    
    [  5  4  3  2  1  11  22  33  44  55  ]
    
    [  55  44  33  22  11  1  2  3  4  5  ]
    
    [  5  4  3  2  1  66  22  33  44  55  ]
    size=10
    
    [  5  4  3  2  1  66  22  44  55  ]
    size=9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试2:删除一个范围、清空所有、截取前部分

    void main()
    {
        DLlist* pList = (DLlist*)malloc(sizeof(DLlist));
        init(pList);
    
        addToHead(pList, 1);
        addToHead(pList, 2);
        addToHead(pList, 3);
        addToHead(pList, 4);
        addToHead(pList, 5);
        addToHead(pList, 6);
        addToHead(pList, 7);
        addToHead(pList, 8);
        addToHead(pList, 9);
        addToHead(pList, 10);
    
        showAll(pList);
        printf("size=%d\n", pList->size);  // 大小
    
        freeFrom(pList, 3);  // 从3开始,删除后面所有
        showAll(pList);
        printf("size=%d\n", pList->size);
    
        deleteRange(pList, 9, 3);  // 从9开始删除3个元素
        showAll(pList);
        printf("size=%d\n", pList->size);
    
        freeAll(pList); // 清空链表
        showAll(pList);
        printf("size=%d\n", pList->size);
    
        system("pause");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    输出:

    
    [  10  9  8  7  6  5  4  3  2  1  ]
    size=10
    
    [  10  9  8  7  6  5  4  ]
    size=7
    
    [  10  6  5  4  ]
    size=4
    
    log:showAll 空链表
    size=0
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试3:删除头尾、查找、插入

    void main()
    {
        DLlist* pList = (DLlist*)malloc(sizeof(DLlist));
        init(pList);
    
        addToHead(pList, 1);
        addToHead(pList, 2);
        addToHead(pList, 3);
        addToHead(pList, 4);
        addToHead(pList, 5);
        addToHead(pList, 6);
        showAll(pList);
        printf("size=%d\n", pList->size);
    
        //int ib = insertBefore(pList, 5, 66);
        int ib = insertBefore2(pList, 5, 66);   //5前面插入66
        if (ib)
        {
            printf("\n前插成功\n");
            showAll(pList);
            printf("size=%d\n", pList->size);
        }
    
        int ia = insertAfter(pList, 3, 26); //3后面插入26
        if (ia)
        {
            printf("\n后插成功\n");
            showAll(pList);
            printf("size=%d\n", pList->size);
        }
    
        DLNode* find = findByValue(pList, 6);  // 查找6
        if (find)
        {
            printf("\nfind ,value=%d,depth=%d\n", find->value, getDepth(pList, find->value));
        }
    
        DLNode* first = removeFirst(pList);  // 删除第一个节点并返回它
        if (first)
        {
            printf("\nfirst value=%d\n", first->value);
            showAll(pList);
            printf("size=%d\n", pList->size);
        }
    
        DLNode* last = removeLast(pList); // 删除最后一个节点并返回它
        if (last)
        {
            printf("\nlast value=%d\n", last->value);
            showAll(pList);
            printf("size=%d\n", pList->size);
        }
    
        system("pause");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    输出:

    
    [  6  5  4  3  2  1  ]
    size=6
    
    前插成功
    
    [  6  66  5  4  3  2  1  ]
    size=7
    
    后插成功
    
    [  6  66  5  4  3  26  2  1  ]
    size=8
    
    find ,value=6,depth=1
    
    first value=6
    
    [  66  5  4  3  26  2  1  ]
    size=7
    
    last value=1
    
    [  66  5  4  3  26  2  ]
    size=6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    测试4:使用可变参数创建链表,并向链表中添加一个链表

    void main()
    {
        DLlist* pList = _createListWithValues(5, 2, 3, 4, 5, 6);
        DLlist* pnewList = _createListWithValues(5,11,22,33,44,55); 
        showAll(pList);
        showAll(pnewList);
    
        if (!checkNull(pList)&& !checkNull(pnewList))
        {
            addListToBack(pList, pnewList); // 将pnewList添加到pList尾部
        }
    
        showAll(pList);
        printf("size=%d\n", pList->size);
    
    
        system("pause");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出:

    [  2  3  4  5  6  ]
    
    [  11  22  33  44  55  ]
    
    [  2  3  4  5  6  11  22  33  44  55  ]
    size=10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试5:对链表元素进行排序

    void main()
    {
    //  DLlist* pList = _createListWithValues(5, 2 ,8 , 4, 9, 7); // 创建一个包还5个元素(2 ,8 , 4, 9, 7)的链表
    
        int arr[5] = { 2 ,8 , 4, 9, 7 };
        DLlist* pList = _createListWithArrayValues(arr, 5);
    
        //showAllReverse(pList);
        sort(pList, _DESC);  // 降序
        showAll(pList);
    
        sort(pList, _ASC);  // 升序
        showAll(pList);
    
        // addToBackWithArrayValues(pList, arr, 3);  // 将一个数组的值添加到链表尾部
        //showAll(pList);
    
        system("pause");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    输出:

    [  9  8  7  4  2  ]
    
    [  2  4  7  8  9  ]
    • 1
    • 2
    • 3

    三、实现像Java那样优雅的调用

    在上面的例子中,使用链表的相关函数进行操作时,会感覚很凌乱,有时可能会令人困惑,这到底是对谁进行的操作。在Java中,使用集合类时,都是通过对象来调用方法,比如如下代码:

        List<String> mylist = new ArrayList<>();
        mylist.add("hello");
        mylist.add("world");
        mylist.add("haha");
        mylist.add("hi");
        mylist.remove(1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们可以很清楚的知道,是对list进行的操作,而且使用list进行调用会很方便,编译器会显示出所有可以被调用的方法。

    为了实现类似这样的功能,我们需要对双链表的结构体定义进行改造,给其添加相关的函数指针成员,当创建双链表时,对这些函数指针进行初始化,指向之前调用的相应函数,这样当我们使用双链表时,就可以方便的进行调用了。函数指针相关知识可以参考 C语言 指针的细枝末节相关部分。

    改造双链表结构体

    对双链表结构体添加相关函数指针成员,如下所示:

    注意:在函数指针的形参为链表结构体时,需要使用struct DoubleLinkList,而不能使用DLlist,因为这时候DLlist还未定义。

    typedef struct DoubleLinkList
    {
        DLNode* head;   // 链表头
        DLNode* back;  // 链表尾
        size_t size;    //链表包含的元素的个数 typedef unsigned int   size_t;  
    
        // pointers
        void (*init)(struct DoubleLinkList* pList);
    
        int (*addToHead)(struct DoubleLinkList* pList, _TYPE value);
    
        int (*addToBack)(struct DoubleLinkList* pList, _TYPE value);
    
        int (*addToHeadWithArrayValues)(struct DoubleLinkList* pList, _TYPE array[], int length);
    
        int (*addToBackWithArrayValues)(struct DoubleLinkList* pList, _TYPE array[], int length);
    
        int (*insertAfter)(struct DoubleLinkList* pList, _TYPE curValue, _TYPE newValue);
    
        int (*insertAfter2)(struct DoubleLinkList* pList, _TYPE curValue, _TYPE newValue);
    
        int (*insertBefore)(struct DoubleLinkList* pList, _TYPE curValue, _TYPE newValue);
    
        int (*insertBefore2)(struct DoubleLinkList* pList, _TYPE curValue, _TYPE newValue);
    
        DLNode* (*removeFirst)(struct DoubleLinkList* pList);
    
        DLNode* (*removeLast)(struct DoubleLinkList* pList);
    
        void(*showAll)(struct DoubleLinkList* pList);
    
        void(*showAllWithRecursion)(DLNode* head);
    
        void(*showAllReverse)(struct DoubleLinkList* pList);
    
        void(*showAllReverseWithRecursion)(DLNode* back);
    
        int(*deleteNode)(struct DoubleLinkList* pList, _TYPE value);
    
        int(*deleteNode2)(struct DoubleLinkList* pList, _TYPE value);
    
        int(*deleteRange)(struct DoubleLinkList* pList, _TYPE fromValue, int count);
    
        int(*checkNull)(void* p);
    
        int(*modify)(struct DoubleLinkList* pList, _TYPE oldValue, _TYPE newValue);
    
        int(*freeAll)(struct DoubleLinkList* pList);
    
        int(*freeFrom)(struct DoubleLinkList* pList, _TYPE value);
    
        DLNode* (*findByValue)(struct DoubleLinkList* pList, _TYPE value);
    
        int(*addListToBack)(struct DoubleLinkList* pList, struct DoubleLinkList* addingList);
    
        int(*getDepth)(struct DoubleLinkList* pList, _TYPE value);
    
        int(*isEmpty)(struct DoubleLinkList* pList);
    
        void(*sort)(struct DoubleLinkList* pList, int asc);
    
    }DLlist;  // 双链表 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    改造创建链表的函数实现

    在创建链表的函数,需要对相关的函数指针成员进行初始化,赋值对应的函数地址。如下代码:

    // 给函数指针赋值
    void initRefs(DLlist* pList){
        pList->init = init;
        pList->addToHead = addToHead;
        pList->addToBack = addToBack;
        pList->addToHeadWithArrayValues = addToHeadWithArrayValues;
        pList->addToBackWithArrayValues = addToBackWithArrayValues;
        pList->insertAfter = insertAfter;
        pList->insertAfter2 = insertAfter2;
        pList->insertBefore = insertBefore;
        pList->insertBefore2 = insertBefore2;
        pList->removeFirst = removeFirst;
        pList->removeLast = removeLast;
        pList->showAll = showAll;
        pList->showAllWithRecursion = showAllWithRecursion;
        pList->showAllReverse = showAllReverse;
        pList->showAllReverseWithRecursion = showAllReverseWithRecursion;
        pList->deleteNode = deleteNode;
        pList->deleteNode2 = deleteNode2;
        pList->deleteRange = deleteRange;
        pList->checkNull = checkNull;
        pList->modify = modify;
        pList->freeAll = freeAll;
        pList->freeFrom = freeFrom;
        pList->findByValue = findByValue;
        pList->addListToBack = addListToBack;
        pList->getDepth = getDepth;
        pList->isEmpty = isEmpty;
        pList->sort = sort; 
    }
    
    //用于给通过DoubleLinkList创建的新链表进行初始化
    void init(DLlist* pList)
    {
        pList->head = pList->back = NULL;
        pList->size = 0;
        initRefs(pList);  // 初始化
    }
    
    //快速创建一个双链表
    DLlist* _createList()
    {
        DLlist* pList = (DLlist*)malloc(sizeof(DLlist));
        init(pList);
    
        return pList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    这样就完成了改造,其他代码不需要进行修改。下面我们进行一下测试。

    测试使用

    #include"doublelinklist2.h"
    
    void main(){
    
        DLlist* pList = _createList();
        pList->addToHead(pList, 1);    // 插入数据到头
        pList->addToHead(pList, 2);
        pList->addToHead(pList, 3);
        pList->addToHead(pList, 4);
        pList->addToHead(pList, 5);
    
        pList->addToBack(pList, 11); // 插入数据到尾
        pList->addToBack(pList, 22);
        pList->addToBack(pList, 33);
        pList->addToBack(pList, 44);
        pList->addToBack(pList, 55);
    
        pList->showAll(pList); // 正向显示所有
        pList->showAllReverse(pList); // 反向显示所有
    
        pList->modify(pList, 11, 66);  // 将11修改为66
        pList->showAll(pList); // 正向显示所有
        printf("size=%d\n", pList->size);
    
        pList->deleteNode(pList, 33);
        pList->showAll(pList); // 正向显示所有
        printf("size=%d\n", pList->size); // 双链表的大小
    
    
    
        system("pause");
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    现在,我们就可以轻松的通过链表来进行相关函数的调用,感覚还是很不错的。


    源码

    声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
    推荐阅读
    相关标签