用C语言简单实现双向链表

在单链表中,通过一个结点找到它的后继结点非常容易,操作的时间复杂程度为O(1),但是要找到它的前驱结点非常麻烦,操作的时间复杂程度为O(n),因为只能从表头指针开始,沿着每个结点遍历,究其原因是单链表的各个结点只指向其后继结点的next域,如果希望查找前驱结点的时间复杂程度也为O(1),则需要为每个结点添加一个前驱指针域prio,使得链表可以双向查找。这就是双向链表。
双向链表结点的类型定义
双向链表的每个结点都有两个指针域:一个指向后继、一个指向前驱。

typedef struct DNode
{
    int data;
    struct DNode *next;
    struct DNode *prio;
}DNode, *DList;

双向链表的初始化

void InitList(DList plist)
{
    assert(plist != NULL);
    if(NULL == plist)
    {
        return;
    }
    plist->next = NULL;
    plist->prio = NULL;
}

双向链表的头插

bool Insert_Head(DList plist, int val)
{
    DNode *p = (DNode*)malloc(sizeof(DNode));
    p->data = val;
    p->next = plist->next;
    plist->next = p;
    if (p->next == NULL)
    {
        return false;
    }
    p->next->prio = p;
    p->prio = plist;
    return true;
}

双向链表的尾插

bool Insert_Tail(DList plist, int val)
{
    DNode *p = (DNode*)malloc(sizeof(DNode));
    p->data = val;
    DNode *q;
    for (q = plist; q->next != NULL; q = q->next);
    p->next = q->next;
    q->next = p;
    p->prio = q;
    return true;
}

双向链表的按值删除

bool Delete(DList plist, int key)
{
    DNode *p,*q;
    for (p = plist; p->next != NULL; p = p->next)
    {
        if (p->next->data == key)
        {
            q = p->next;
            p->next = q->next;
            if (q->next != NULL)
            {
                q->next->prio = p;
            }
        }
    }
    free(q);
    return true;
}

双向链表的销毁

void Destroy(DList plist)
{
    DNode *p;

    while (plist != NULL)
    {
        p = plist->next;
        plist->next = p->next;
        free(p);
    }
}

双向链表的打印

void Show(DList plist)
{
    for (DNode *p = plist->next; p != NULL; p = p->next)
    {
        printf("%d ", p->data);
    }
    printf("\n");
}

双向链表的实例

int main()
{
    DNode head;
    InitList(&head);
    for (int i = 0; i < 20; i++)
    {
        Insert_Tail(&head, i);
    }
    Delete(&head, 5);
    Show(&head);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值