双向链表

来源:互联网 发布:js调用另一个js的函数 编辑:程序博客网 时间:2024/06/16 09:38

单链表的局限:
单链表的结点都只有一个指向下一个结点的指针。
单链表的数据元素无法直接访问其前驱元素。

逆序访问单链表中的元素是极其耗时的操作

双向链表的定义

在单链表的结点中增加一个指向其前驱的pre指针。

这里写图片描述

双向链表拥有单链表的所有操作
创建链表
销毁链表
获取链表长度
清空链表
获取第pos个元素操作
插入元素到位置pos
删除位置pos处的元素

插入操作

这里写图片描述

删除操作

这里写图片描述

双向链表的新操作

获取当前游标指向的数据元素
将游标重置指向链表中的第一个数据元素
将游标移动指向到链表中的下一个数据元素
将游标移动指向到链表中的上一个数据元素
直接指定删除链表中的某个数据元素

这里写图片描述

双向链表 的相关代码

//头文件 DLinkList.h#ifndef _DLINKLIST_H_#define _DLINKLIST_H_typedef void DLinkList;typedef struct _tag_DLinkListNode DLinkListNode;struct _tag_DLinkListNode{    DLinkListNode* next;    DLinkListNode* pre;  //新定义的前向指针 };struct Value  //本结构体可以定义在main.c文件中,作为数据部分 {    DLinkListNode header;    int v;};DLinkList* DLinkList_Create();void DLinkList_Destroy(DLinkList* list);void DLinkList_Clear(DLinkList* list);int DLinkList_Length(DLinkList* list);int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);DLinkListNode* DLinkList_Get(DLinkList* list, int pos);DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);DLinkListNode* DLinkList_Reset(DLinkList* list);DLinkListNode* DLinkList_Current(DLinkList* list);DLinkListNode* DLinkList_Next(DLinkList* list);DLinkListNode* DLinkList_Pre(DLinkList* list);#endif
//双向链表 源文件 DLinkList.c#include <stdio.h>#include <malloc.h>#include "DLinkList.h"typedef struct _tag_DLinkList{    DLinkListNode header;    DLinkListNode* slider;    int length;} TDLinkList;DLinkList* DLinkList_Create() // O(1) 创建双向链表 {    TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList));    if( ret != NULL )    {        ret->length = 0;        ret->header.next = NULL;        ret->header.pre = NULL;        ret->slider = NULL;    }    return ret;}void DLinkList_Destroy(DLinkList* list) // O(1) 销毁双向链表 {    free(list);}void DLinkList_Clear(DLinkList* list) // O(1) 清空双向链表 {    TDLinkList* sList = (TDLinkList*)list;    if( sList != NULL )    {        sList->length = 0;        sList->header.next = NULL;        sList->header.pre = NULL;        sList->slider = NULL;    }}int DLinkList_Length(DLinkList* list) // O(1) 获取链表的数据长度 {    TDLinkList* sList = (TDLinkList*)list;    int ret = -1;    if( sList != NULL )    {        ret = sList->length;    }    return ret;}int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) // O(n)//插入某个元素 {     TDLinkList* sList = (TDLinkList*)list;    int ret = (sList != NULL) && (pos >= 0) && (node != NULL);    int i = 0;    if( ret )    {        DLinkListNode* current = (DLinkListNode*)sList;        DLinkListNode* next = NULL;        for(i=0; (i<pos) && (current->next != NULL); i++)        {            current = current->next;        }        next = current->next;        current->next = node;        node->next = next;        if( next != NULL )        {            next->pre = node;        }        node->pre = current;        if( sList->length == 0 )        {            sList->slider = node;        }        if( current == (DLinkListNode*)sList )        {            node->pre = NULL;        }        sList->length++;    }    return ret;}DLinkListNode* DLinkList_Get(DLinkList* list, int pos) // O(n) 获取某个元素 {    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    int i = 0;    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )    {        DLinkListNode* current = (DLinkListNode*)sList;        for(i=0; i<pos; i++)        {            current = current->next;        }        ret = current->next;    }    return ret;}DLinkListNode* DLinkList_Delete(DLinkList* list, int pos) // O(n) 删除某个元素 {    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    int i = 0;    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )    {        DLinkListNode* current = (DLinkListNode*)sList;        DLinkListNode* next = NULL;        for(i=0; i<pos; i++)        {            current = current->next;        }        ret = current->next;        next = ret->next;        current->next = next;        if( next != NULL )        {            next->pre = current;            if( current == (DLinkListNode*)sList )            {                next->pre = NULL;            }        }        if( sList->slider == ret )        {            sList->slider = next;        }        sList->length--;    }    return ret;}DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node){    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    int i = 0;    if( sList != NULL )    {        DLinkListNode* current = (DLinkListNode*)sList;        for(i=0; i<sList->length; i++)        {            if( current->next == node )            {                ret = current->next;                break;            }            current = current->next;        }        if( ret != NULL )        {            DLinkList_Delete(sList, i);        }    }    return ret;}DLinkListNode* DLinkList_Reset(DLinkList* list){    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    if( sList != NULL )    {        sList->slider = sList->header.next;        ret = sList->slider;    }    return ret;}DLinkListNode* DLinkList_Current(DLinkList* list){    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    if( sList != NULL )    {        ret = sList->slider;    }    return ret;}DLinkListNode* DLinkList_Next(DLinkList* list){    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    if( (sList != NULL) && (sList->slider != NULL) )    {        ret = sList->slider;        sList->slider = ret->next;    }    return ret;}DLinkListNode* DLinkList_Pre(DLinkList* list){    TDLinkList* sList = (TDLinkList*)list;    DLinkListNode* ret = NULL;    if( (sList != NULL) && (sList->slider != NULL) )    {        ret = sList->slider;        sList->slider = ret->pre;    }    return ret;}

小结

双向链表在单链表的基础上增加了指向前驱的指针。
功能上双向链表可以完全取代单链表的使用。
循环链表的Next,Pre和Current操作可以高效的遍历链表中的所有元素。

0 0