c语言实现双向链表

本文详细介绍了双向链表的基本操作,包括初始化、增删查改等,并提供了完整的C语言实现代码。通过双向链表,可以高效地进行节点的插入和删除操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在我们采用链表结构对于数据进行存储的时候,我们往往优先想到的是简单单链表结构。但是在实际使用过程中,双向链表往往具有更好的执行效率,我们以链表的简单增删查改为例:
include <stdio.h>
#include <stdlib.h>
typedef char DLinkType;

typedef struct DLinkNode {
    DLinkType data;
    struct DLinkNode* next;
    struct DLinkNode* prev;
} DLinkNode;

void DLinkListInit(DLinkNode** head){
    if (head == NULL)
        return;
    if (*head == NULL)
        return;
    (*head)->next = NULL;
    (*head)->prev = NULL;
    return;
}

DLinkNode* DLinkListPushBack(DLinkNode* head, DLinkType value){//尾插
    if (head == NULL)
        return NULL;
    DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
    l->data = value;
    l->next = head;
    l->prev = head->prev;
    head->prev->next = l;
    head->prev = l;
    return l;
}

void DLinListPopBack(DLinkNode* head){//尾删
    if (head == NULL)
        return;
    DLinkNode* to_delete = head->prev;
    head->prev->prev->next = head;
    head->prev = head->prev->prev;
    free(to_delete);
    return;
}

void DLinkListPushFront(DLinkNode* head, DLinkType value){
    if (head == NULL)
        return;
    DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
    l->data = value;
    l->prev = head;
    l->next = head->next;
    head->next->prev = l;
    head->next = l;
    return;
}

void DLinkListPopFront(DLinkNode* head){
    if (head == NULL)
        return;
    DLinkNode* to_delete = head->next;
    head->next = head->next->next;
    head->next->prev = head;
    free(to_delete);
    return;
}

DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find){
    if (head == NULL)
        return NULL;
    DLinkNode* p =head->next;
    while (p != head){
        if (p->data = to_find)
            return p;
        p = p->next;
    }
    return NULL;
}


/**
* @brief 往指定位置之前插入一个元素
*/
void DLinkListInsert(DLinkNode* pos, DLinkType value){
    if (pos == NULL)
        return;
    DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
    l->next = pos;
    l->prev = pos->prev;
    pos->prev->next = l;
    pos->prev = l;
    return;
}

/**
* @brief 往指定位置之后插入一个元素
*/
void DLinkListInsertAfter(DLinkNode* pos, DLinkType value){
    if (pos == NULL)
        return;
    DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
    l->next = pos->next;
    l->prev = pos;
    pos->next->prev = l;
    pos->next = l;
    return;
}

void DLinkListErase(DLinkNode* pos){//删除指定节点
    if (pos == NULL)
        return;
    pos->prev->next = pos->next;
    pos->next->prev = pos->prev;
    free(pos);
    return;
}

void DLinkListEraseAll(DLinkNode** head){//删除所有节点
    if (head == NULL)
        return;
    if (*head == NULL)
        return;
    DLinkNode* p =*head;
    (*head)->prev = NULL;
    DLinkNode* to_delete =*head;
    while(p){
        p = p->next;
        free(to_delete);
        to_delete = p;
    }
    return;
}

void DLinkListRemove(DLinkNode* head,DLinkType value){//删除指定值的节点
    if (head == NULL)
        return;
    DLinkNode* p =head->next;
    while(p != head){
        if (p->data == value){
            DLinkListErase(p);
            return;
        }
        p = p->next;
    }
}

void DLinkListRemoveAll(DLinkNode* head,DLinkType value){//删除指定值得所有节点
    if (head == NULL)
        return;
    DLinkNode* p =head->next;
    while(p != head){
        if (p->data == value){
            DLinkListErase(p);
        }
        p = p->next;
    }
    return;
}

size_t DLinkListSize(DLinkNode* head){//判断链表长度
    if (head == NULL)
        return 0;
    DLinkNode* p = head->next;
    size_t count = 1;
    while (p != head){
        ++count;
        p = p->next;
    }
    return count;
}
int main() {
    printf("Hello, World!\n");
    return 0;
}
    对比上文的 单向链表的增删查改,我们可以看到,由于双向链表可以方便的查找到上一个节点,所以省去了很多的遍历过程。这也是一种使用空间来换时间的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值