双向链表总结

Posted 菜鸟沃土

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向链表总结相关的知识,希望对你有一定的参考价值。

基本数据结构之-双向链表

双向链表和单向链表明显的区别就是,双向链表可以向前查找,也就是能直接找到它自己的前驱结点,但是双向链表不是循环链表!

分析基本的数据结构,每个结点都有自己的数据域和两个指针域,一个指向前驱,一个指向后继,但是为了通用性,我们只考虑一个前驱和一个后继的关系

 

typedef struct _DOUBLE_LIST_NODE

{

    // 定义双向链表的前驱和后继

    struct _DOUBLE_LIST_NODE *Pre;

    struct _DOUBLE_LIST_NODE  *Next;

}DoubleListNode, *DoubleSidedList;

 

 

 

// 初始化

int Init_DoubleSidedList(DoubleSidedList *doublesidedlist)

{

    if (doublesidedlist == NULL)

    {

        exit(-1);

    }

    if (*doublesidedlist == NULL)

    {

        *doublesidedlist = (DoubleSidedList)malloc(sizeof(DoubleListNode));

    }

    (*doublesidedlist)->Next = NULL;

    (*doublesidedlist)->Pre = NULL;

 

    return 0;

}

// 销毁,不要释放其他位置的空间,不知道是栈内存还是堆内存,并且不知道是什么数据类型

void Destroy_DoubleSidedList(DoubleSidedList doublesidedlist)

{

    if (doublesidedlist == NULL)

    {

        return;

    }

    free(doublesidedlist);

}

 

// 仅仅是把指针置空

void Clear_DoubleSidedList(DoubleSidedList doublesidedlist)

{

    if (doublesidedlist == NULL)

    {

        return;

    }

    doublesidedlist->Next = NULL;

    doublesidedlist->Pre = NULL;

}

 

int Empty_DoubleSidedList(DoubleSidedList doublesidedlist)

{

    if (doublesidedlist==NULL)

    {

        return -1;

    }

    // 如果next为空,肯定链表也是空的

    return doublesidedlist->Next == NULL;

    //

}

 

// 返回当前双向链表的长度

int Length_DoubleSidedList(DoubleSidedList doublesidedlist)

{

    if (doublesidedlist == NULL)

    {

        return 0;

    }

    int length = 0;

    // 第一个元素的开始的位置在 定义Next开始

    DoubleListNode *pCurrent =doublesidedlist->Next;

 

    while (pCurrent!= NULL)

    {

        ++length;

        pCurrent = pCurrent->Next;

    }

    return length;

}

 

void * GetElem_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos)

{

    if (doublesidedlist == NULL)

    {

        return NULL;

    }

    if (Pos<0 || Pos>Length_DoubleSidedList(doublesidedlist)-1)

    {

        return NULL;

    }

    DoubleListNode *pCurrent = doublesidedlist->Next;

    int i = 0;

    while (i<Pos)

    {

        pCurrent = pCurrent->Next;

        ++i;

    }

    // 返回所在的位置 从 0 开始

    return pCurrent;

}

// 查看链表中是否存在某个值,返回所在的位置

int  LocateElem_DoubleSidedList(DoubleSidedList doublesidedlist, void* data, int(*compare)(void *data1, void *data2))

{

    if (doublesidedlist==NULL)

    {

        return -1;

    }

    if (data == NULL)

    {

        return -2;

    }

    if (compare == NULL)

    {

        return -4;

    }

    DoubleListNode *Node = (DoubleListNode *)data;

    int i = 0;

    DoubleListNode *pCurrent = doublesidedlist->Next;

 

    while (pCurrent!= NULL)

    {

        // 必须要传入比较函数

        if (compare(pCurrent, Node))

        {

            return i;

        }

        pCurrent = pCurrent->Next;

        ++i;

    }

    return -3;

}

// 返回前驱,这儿就可以体现出双向链表的优势

void *PriorElem_DoubleSidedList(DoubleSidedList doublesidedlist, void *data)

{

    if (doublesidedlist == NULL)

    {

        return NULL;

    }

    if (data == NULL)

    {

        return NULL;

    }

 

    DoubleListNode *pCurrent = doublesidedlist->Next;

 

    while (pCurrent != NULL)

    {

#if 0

 

        if (pCurrent->Next==data)

        {

            return pCurrent;

        }

 

#else

 

        if (pCurrent == data)

        {

            //这就是双向链表的好处

            return pCurrent->Pre;

        }

       

#endif

        pCurrent = pCurrent->Next;

    }

    return NULL;

}

// 返回后继

void* NextElem_DoubleSidedList(DoubleSidedList doublesidedlist, void *data)

{

    if (doublesidedlist == NULL)

    {

        return NULL;

    }

    if (data == NULL)

    {

        return NULL;

    }

 

    DoubleListNode *pCurrent = doublesidedlist;

 

    while (pCurrent->Next != NULL)

    {

        if (pCurrent == data)

        {

            return pCurrent->Next;

        }

        pCurrent = pCurrent->Next;

    }

    return NULL;

}

 

// 插入操作,一定要考虑特殊的情况

int Insert_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos, void * data)

{

    if (doublesidedlist == NULL)

    {

        return -1;

    }

    if (data == NULL)

    {

        return -2;

    }

    if (Pos < 0)

    {

        Pos = 0;

    }

    if (Pos > Length_DoubleSidedList(doublesidedlist))

    {

        Pos = Length_DoubleSidedList(doublesidedlist);

    }

 

    DoubleListNode *pCurrent = doublesidedlist;

 

    for (int i = 0; i < Pos; ++i)

    {

        pCurrent = pCurrent->Next;

    }

    DoubleListNode *Node = (DoubleListNode *)data;

   

    //

    if (Pos==0 && Length_DoubleSidedList(doublesidedlist) == 0)

    {

        // 最前面一个位置插入 && 当前长度为0 插入的结点不存在后继结点

            Node->Next = pCurrent->Next;

            Node->Pre = pCurrent;

            pCurrent->Next = Node;

    }

    else if (Length_DoubleSidedList(doublesidedlist) == Pos)

    {

        // 最后一个结点不存在后继结点

        Node->Next = pCurrent->Next;

        Node->Pre = pCurrent;

        pCurrent->Next = Node;

    }

    else

    {

        Node->Next = pCurrent->Next;

        pCurrent->Next->Pre = Node;

        pCurrent->Next = Node;

        Node->Pre = pCurrent;

    }

   

 

    return 0;

}

 

// 删除操作 一定要考虑特殊的情况

int  DeleteByPos_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos)

{

    if (doublesidedlist == NULL)

    {

        return -1;

    }

    if (Pos<0 || Pos>Length_DoubleSidedList(doublesidedlist) - 1)

    {

        return -2;

    }

    DoubleListNode *pCurrent = doublesidedlist->Next;

    // 找到前驱

 

    for (int i = 0; i < Pos; ++i)

    {

        pCurrent = pCurrent->Next;

    }

    // 如果删除的是最后一个结点,那么找不到最后一个结点的下一个结点

    if (Pos == Length_DoubleSidedList(doublesidedlist))

    {

        pCurrent->Pre->Next = NULL;

    }

    else

    {

        pCurrent->Next->Pre = pCurrent;

        pCurrent->Next = pCurrent->Next->Next;

    }

   

    return 0;

 

}

 

int  DeleteByVal_DoubleSidedList(DoubleSidedList doublesidedlist, void* data)

{

    if (doublesidedlist == NULL)

    {

        return -1;

    }

    DoubleListNode *pCurrent = doublesidedlist->Next;

 

    while (pCurrent->Next != NULL )

    {

        if (pCurrent == data)

        {

            break;

        }

        pCurrent = pCurrent->Next;

    }

    // 如果是最后一个结点,

    if (pCurrent->Next == NULL)

    {

        pCurrent->Pre->Next = NULL;

    }

    else

    {

        pCurrent->Next->Pre = pCurrent;

        pCurrent->Next = pCurrent->Next->Next;

    }

   

    return 0;

}

// 遍历操作

void Traverse_DoubleSidedList(DoubleSidedList doublesidedlist, void(*Traverse)(void *data))

{

    if (doublesidedlist == NULL)

    {

        return;

    }

    if (Traverse == NULL)

    {

        return;

    }

    DoubleListNode *pCurrent = doublesidedlist->Next;

    while (pCurrent != NULL)

    {

        Traverse(pCurrent);

        pCurrent = pCurrent->Next;

    }

}

 

以上是关于双向链表总结的主要内容,如果未能解决你的问题,请参考以下文章

算法总结之 反转单向和双向链表

c++ 双向链表操作总结

双向循环链表增删查改C语言实现

双向链表的实现(双向链表与单向链表的简单区别联系和实现)

双向链表的实现(双向链表与单向链表的简单区别联系和实现)

数据结构带头双向循环链表