【C语言】双向链表的实现

双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

双链表结构如下:
typedef int DataType;
typedef struct DoubleNode
{
    struct DoubleNode* prev;       //指向前一节点的指针
    struct DoubleNode* next;       //指向后一节点的指针
    DataType data;                 //当前节点的数据
}DoubleNode,*DoubleList;
DoubleList end = NULL;             //记录最后一个节点的位置 

跟单链表相似,只是双链表比单链表多了一个指向前驱的指针。
这样我们在插入和删除一个节点的时候,不必遍历链表找到该节点的前一个节点了。


双链表的一些基本操作实现如下:
void InitDoubleList(DoubleList* pDlist)         //初始化
{
    assert(pDlist);
    *pDlist = NULL;
}
void PrintDoubleList(DoubleList pDlist)         //打印双向链表
{
    if (pDlist == NULL)
    {
        printf("DoubleList Is Empty\n");
        return;
    }
    printf("DoubleList->");
    DoubleList begin = pDlist;
    while (begin)
    {
        printf("%d->", begin->data);
        begin = begin->next;
    }
    printf("NULL\n");
}
DoubleList GreateDoubleNode(DataType data)      //增加节点
{
    DoubleList tmp = (DoubleList)malloc(sizeof(DoubleNode));
    tmp->data = data;
    tmp->next = NULL;
    tmp->prev = NULL;
    return tmp;
}
void PushBack(DoubleList* pDlist,DataType data) //尾插一个节点
{
    assert(pDlist);
    if (*pDlist == NULL)
    {
        *pDlist = GreateDoubleNode(data);
        end = *pDlist;
        return;
    }
    DoubleList tmp = GreateDoubleNode(data);
    end->next = tmp;
    tmp->prev = end;
    end = tmp;
}
void PopBack(DoubleList* pDlist)                //尾删一个节点
{
    assert(pDlist);
    if (*pDlist == NULL)         //空链表
    {
        printf("DoubleList Is Empty\n");
        return;
    }
    if ((*pDlist)->next == NULL) //只有一个节点
    {
        free(*pDlist);
        *pDlist = NULL;
        return;
    }
    DoubleList del = end;
    end = end->prev;
    end->next = NULL;
    free(del);
}
void PushFront(DoubleList* pDlist, DataType data)  //头插一个节点
{
    assert(pDlist);
    if (*pDlist == NULL)
    {
        *pDlist = GreateDoubleNode(data);
        end = *pDlist;
        return;
    }
    DoubleList ret = GreateDoubleNode(data);
    ret->next = *pDlist;
    (*pDlist)->prev = ret;
    *pDlist = ret;
}
void PopFront(DoubleList* pDlist)                  //头删一个节点
{
    assert(pDlist);
    if (*pDlist == NULL)
    {
        printf("DoubleList Is Empty\n");
        return;
    }
    if ((*pDlist)->next == NULL) //只有一个节点
    {
        free(*pDlist);
        *pDlist = NULL;
        return;
    }
    DoubleList del = *pDlist;
    *pDlist = (*pDlist)->next;
    (*pDlist)->prev = NULL;
    free(del);
}
DoubleList Find(DoubleList pDlist, DataType data)    //查找节点
{
    if (pDlist == NULL)
    {
        printf("DoubleList Is Empty\n");
        return NULL;
    }
    DoubleList begin = pDlist;
    while (begin)
    {
        if (begin->data == data)
        {
            return begin;
        }
        begin = begin->next;
    }
    return NULL;
}
void Insert(DoubleList* pDlist, DoubleList n, DataType data)//在节点n后插入一个节点
{
    assert(pDlist);
    if (*pDlist == NULL)
    {
        printf("DoubleList Is Empty\n");
    }
    else if (n == NULL)
    {
        printf("n Not Exist\n");
    }
    else
    {
        if (n == end)
        {
            PushBack(pDlist, data);
        }
        else
        {
            DoubleList ret = GreateDoubleNode(data);
            DoubleList tmp = n->next;
            ret->next = tmp;
            ret->prev = n;
            tmp->prev = ret;
            n->next = ret;
        }
    }
}
void DelDoubleNode(DoubleList* pDlist,DoubleList n)  //删除节点n
{
    assert(pDlist);
    if (*pDlist == NULL)
    {
        printf("DoubleList Is Empty\n");
    }
    else if ((*pDlist)->next == NULL && n == *pDlist)//只有一个节点且查找的正是这个节点
    {
        free(*pDlist);
        *pDlist = NULL;
    }
    else
    {
        if (n == *pDlist)
        {
            PopFront(pDlist);
        }
        else if (n == end)
        {
            PopBack(pDlist);
        }
        else
        {
            DoubleList prev = n->prev;
            DoubleList next = n->next;
            next->prev = prev;
            prev->next = next;
            free(n);
        }
    }
}
void Reverse(DoubleList* pDlist)          //逆置双向链表
{
    assert(pDlist);
    if (*pDlist == NULL || (*pDlist)->next == NULL)
    {
        return;
    }
    DoubleList begin = (*pDlist)->next;
    begin->prev = NULL;
    (*pDlist)->next = NULL;     //摘下头节点作为尾节点
    while (begin)
    {
        DoubleList ret = begin;
        begin = begin->next;
        ret->next = *pDlist;
        ret->prev = NULL;
        (*pDlist)->prev = ret;
        *pDlist = ret;         //更新逆置后的头节点
    }
}

双向链表相比较单向链表,主要有下面几个特点:

**(1)在数据结构中具有双向指针**
**(2)插入数据的时候需要考虑前后的方向的操作**
**(3)同样,删除数据的是有也需要考虑前后方向的操作**
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值