线性表(List)---链式存储结构(双向链表)

来源:互联网 发布:淘宝运营计划方案 编辑:程序博客网 时间:2024/04/29 01:59

双向链表设计与实现


双向链表的介绍

双向链表定义: 在单链表的结点中增加一个指向其前驱的pre指针。
双向链表定义
双向链表设计意义: 方便逆序访问链表中的元素(O(n))。
单链表中的逆序访问:

len = LinkList_Length(list);for (i = len - 1; len >= 0; i++) //O(n){   LinkListNode *p = LinkList_Get(list, i); //O(n)//访问数据元素p中的元素}

双向链表的设计

定义一个结构体指针用来存储指针与指针之间的关系:

typedef struct DLinkListNode{    struct DLinkListNode *next;    struct DLinkListNode *pre;}DLinkListNode;

定义一个头结点用来存储链表:

typedef struct _tag_DLinkList{    DLinkListNode header;    DLinkListNode *slider;//游标    int length;}TDLinkList;

数据元素定义实例:

typedef struct Value{    DLinkListNode node;    int v;}Value;

双向链表新增操作

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

双向链表重要算法

  • 双向链表插入算法
    双向链表插入算法
  • 双向链表删除算法
    双向链表删除算法

双向链表的优缺点

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

双向链表的实现

DLinkList.h

#ifndef  _DLINKLIST_H_#define  _DLINKLIST_H_typedef void DLinkList;typedef struct DLinkListNode{    struct DLinkListNode *next;    struct DLinkListNode *pre;}DLinkListNode;//创建双向链表DLinkList *DLinkList_Create();//销毁双向链表void DLinkList_Destroy(DLinkList *list);//清空双向链表void DLinkList_Clear(DLinkList *list);//获取双向链表长度int DLinkList_Length(DLinkList *list);//向第pos位置char如元素nodeint DLinkList_Insert(DLinkList *list, DLinkListNode *node, int pos);//获取第pos位置的元素DLinkListNode *DLinkList_Get(DLinkList *list, int pos);//删除第pos位置的元素DLinkListNode *DLinkList_Delete(DLinkList *list, int pos);//获取当前游标的元素DLinkListNode *DLinkList_Current(DLinkList *list);//将游标重置指向链表的第一个位置元素DLinkListNode *DLinkList_Rset(DLinkList *list);//将游标移动指向到链表下一个位置元素DLinkListNode *DLinkList_Next(DLinkList *list);//将游标移动指向到链表上一个位置元素DLinkListNode *DLinkList_Pre(DLinkList *list);//直接删除指定链表中的某个元素DLinkListNode *DLinkList_DeleteNode(DLinkList *list, DLinkListNode *node);#endif//DLinkList.h

DLinkList.c

#include "DLinkList.h"#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct _tag_DLinkList{    DLinkListNode header;    DLinkListNode *slider;//游标    int length;}TDLinkList;//创建双向链表DLinkList *DLinkList_Create(){    TDLinkList *ret = (TDLinkList *)malloc(sizeof(TDLinkList));    if(ret==NULL)    {        printf("func DLinkList_Create()(ret==NULL) err\n");        return ret;    }//  memset(ret, 0, sizeof(ret));    ret->header.next = NULL;    ret->header.pre = NULL;    ret->slider = NULL;    ret->length = 0;    return ret;}//销毁双向链表void DLinkList_Destroy(DLinkList *list){    if (list == NULL)    {        return;    }    free(list);    return ;}//清空双向链表void DLinkList_Clear(DLinkList *list){    TDLinkList *tlist=(TDLinkList *)list;    if (list == NULL)    {        printf("func DLinkList_Clear() (list == NULL) err\n");        return;    }    tlist->header.next = NULL;    tlist->header.pre = NULL;    tlist->slider = NULL;    tlist->length = 0;    return ;}//获取双向链表长度int DLinkList_Length(DLinkList *list){    int ret = 0;    TDLinkList *tlist = (TDLinkList *)list;    if (list == NULL)    {        ret = -1;        printf("func DLinkList_Length()(list == NULL) err:%d\n",ret);        return ret;    }    ret = tlist->length;    return ret;}//向第pos位置插入元素nodeint DLinkList_Insert(DLinkList *list, DLinkListNode *node, int pos){    int ret = 0, i = 0;    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *Current = NULL;    DLinkListNode *Next = NULL;    if (list == NULL || node == NULL || pos < 0)    {        ret = -1;        printf("func DLinkList_Insert() (list == NULL || node == NULL || pos < 0) err:%d", ret);        return ret;    }    if (pos > tlist->length)    {        ret = -2;        printf("func DLinkList_Insert() (pos > tlist->length) err:%d\n", ret);        return ret;    }    Current = (DLinkListNode *)tlist;    for (i = 0; (i < pos) && (Current->next != NULL); i++)    {        Current = Current->next;    }    Next = Current->next;    Current->next = node;  //1    node->next = Next;     //2    if (Next != NULL)    {        Next->pre = node;  //3    }    node->pre = Current;   //4    if(tlist->length==0)    {         tlist->slider = node;//当链表插入第一个元素处理游标    }    //若在0位置插入,需要特殊处理新节点next前pre指向NULL    if (Current == (DLinkListNode *)tlist)    {        node->pre = NULL;    }    tlist->length++;    return ret;}//获取第pos位置的元素DLinkListNode *DLinkList_Get(DLinkList *list, int pos){    int i = 0;    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *Current = NULL;    DLinkListNode *ret = NULL;    if (list == NULL || pos < 0)    {        printf("func DLinkList_Get() (list == NULL || pos < 0) err\n");        return NULL;    }    if (pos > tlist->length)    {        printf("func DLinkList_Get() (pos > tlist->length) err\n");        return  NULL;    }    Current = (DLinkListNode *)tlist;    for (i = 0; (i < pos) && (Current->next != NULL); i++)    {        Current = Current->next;    }    ret = Current->next;    return ret;}//删除第pos位置的元素DLinkListNode *DLinkList_Delete(DLinkList *list, int pos){    int i = 0;    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *Current = NULL;    DLinkListNode *Next = NULL;    DLinkListNode *ret = NULL;    if (list == NULL || pos < 0)    {        printf("func DLinkList_Delete() (list == NULL || pos < 0) err\n");        return NULL;    }    if (pos > tlist->length)    {        printf("func DLinkList_Deletee() (pos > tlist->length) err\n");        return NULL;    }    Current = (DLinkListNode *)tlist;    for (i = 0; (i < pos) && (Current->next != NULL); i++)    {        Current = Current->next;    }    ret = Current->next;    Next = ret->next;                   Current->next = Next;           //1    if (Next != NULL)    {        Next->pre = Current;        if (Current == (DLinkListNode *)tlist)        {            Next->pre = NULL;        }    }    if (tlist->slider == ret)    {        tlist->slider = Next;    }    tlist->length--;    return ret;}//获取当前游标的元素DLinkListNode *DLinkList_Current(DLinkList *list){    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *ret = NULL;    if (list == NULL)    {        printf("func DLinkList_Current() (list == NULL) err\n");        return NULL;    }    ret = tlist->slider;    return ret;}//将游标重置指向链表的第一个位置元素DLinkListNode *DLinkList_Rset(DLinkList *list){    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *ret = NULL;    if (list == NULL)    {        printf("func DLinkList_Rset() (list == NULL) err\n");        return NULL;    }    tlist->slider = tlist->header.next;    ret = tlist->slider;    return ret;}//将游标移动指向到链表下一个位置元素DLinkListNode *DLinkList_Next(DLinkList *list){    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *ret = NULL;    if (list == NULL)    {        printf("func DLinkList_Next() (list == NULL) err\n");        return NULL;    }    ret = tlist->slider;    tlist->slider = ret->next;    return ret;}//将游标移动指向到链表上一个位置元素DLinkListNode *DLinkList_Pre(DLinkList *list){    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *ret = NULL;    if (list == NULL)    {        printf("func DLinkList_Pre() (list == NULL) err\n");        return NULL;    }    ret = tlist->slider;    tlist->slider = ret->pre;    return ret;}//直接删除指定链表中的某个元素DLinkListNode *DLinkList_DeleteNode(DLinkList *list, DLinkListNode *node){    int i = 0;    TDLinkList *tlist = (TDLinkList *)list;    DLinkListNode *ret = NULL;    DLinkListNode *Current = NULL;    if (list == NULL || node)    {        printf("func DLinkList_DeleteNode() (list == NULL || node) err\n");        return NULL;    }    Current = (DLinkListNode *)tlist;    for (i = 0; i < tlist->length; i++)    {        if (Current->next == node)        {            ret = Current->next;            break;        }    }    if (ret != NULL)    {        DLinkList_Delete(tlist, i);    }    if (ret == tlist->slider)    {        tlist->slider = ret->next;    }    return ret;}

双向链表集成测试框架

#include <stdio.h>#include <string.h>#include <stdlib.h>#include "DLinkList.h"typedef struct Value{    DLinkListNode node;    int v;}Value;void main(){    int i = 0, ret = 0;    Value v1, v2, v3, v4, v5;    Value *tmp = NULL;    DLinkList *list = DLinkList_Create();    if (list == NULL)    {        printf("func DLinkList_Create()(list == NULL) err\n");        return;    }    v1.v = 1;    v2.v = 2;    v3.v = 3;    v4.v = 4;    v5.v = 5;    ret = DLinkList_Insert(list, (DLinkListNode *)&v1, DLinkList_Length(list));    if (ret != 0)    {        printf("func DLinkList_Insert() (ret != 0) err:%d\n", ret);        return;    }    ret = DLinkList_Insert(list, (DLinkListNode *)&v2, DLinkList_Length(list));    if (ret != 0)    {        printf("func DLinkList_Insert() (ret != 0) err:%d\n", ret);        return;    }    ret = DLinkList_Insert(list, (DLinkListNode *)&v3, DLinkList_Length(list));    if (ret != 0)    {        printf("func DLinkList_Insert() (ret != 0) err:%d\n", ret);        return;    }    ret = DLinkList_Insert(list, (DLinkListNode *)&v4, DLinkList_Length(list));    if (ret != 0)    {        printf("func DLinkList_Insert() (ret != 0) err:%d\n", ret);        return;    }    ret = DLinkList_Insert(list, (DLinkListNode *)&v5, DLinkList_Length(list));    if (ret != 0)    {        printf("func DLinkList_Insert() (ret != 0) err:%d\n", ret);        return;    }    printf("Get Elements:\n");    for (i = 0; i < DLinkList_Length(list); i++)    {        tmp = (Value *)DLinkList_Get(list, i);        printf("tmp->v:%d\n", tmp->v);    }    printf("\n");    printf("\n");    DLinkList_Delete(list, DLinkList_Length(list) - 1); //删除最后一个元素    DLinkList_Delete(list, 0);                           //删除第一个元素    printf("Delete first element and last element:\n");    for (i = 0; i < DLinkList_Length(list); i++)    {        tmp = (Value *)DLinkList_Next(list);        printf("tmp->v:%d\n", tmp->v);    }    printf("\n");    DLinkList_Rset(list);   //游标重置    DLinkList_Next(list);   //游标后移一个  3    printf("reset slider,and move slider to next: \n");    tmp = (Value *)DLinkList_Current(list);    printf("tmp->v:%d\n", tmp->v);    DLinkList_Pre(list);     //游标前移一个 2    printf("mov slider to pre:\n");    tmp = (Value *)DLinkList_Current(list);    printf("tmp->v:%d\n", tmp->v);    printf("Length:%d\n", DLinkList_Length(list));      DLinkList_Destroy(list);    system("pause");    return;}

结果截图
双向链表集成测试框架截图

阅读全文
1 0