双向链表的实现(c语言数据结构)

目录

需要实现的功能

具体功能的实现

1.创建新的结点

2.双向链表的初始化

3.双向链表的尾插

4.双向链表的打印

5.双向链表的头删

6.双向链表的摧毁

7.双向链表的结点查找

8.双向链表在pos位置之前插入

9.删除目标位置的结点

10.头删

11.尾删

汇总

以下是测试文件


需要实现的功能

以下是定义在我们的List.h的文件中,来声明我们双向链表需要实现的功能。

双向链表携带了该结点的前置结点和后置结点,可以比单链表更加方便地访问结点的前置元素。

同时在此我们采用了带哨兵位的双向链表,我们的尾结点的next指针指向我们的哨兵位,我们的哨兵位的前置结点指向我们的尾结点。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
typedef int LTDataType;
typedef struct ListNode
{
    struct ListNode*next;
    struct ListNode*prev;
    LTDataType data;
}LTNode;
LTNode* BuyListNode(LTDataType x);


// 创建返回链表的头结点.
LTNode *ListInit();
// 双向链表销毁
void ListDestory(LTNode* pHead);
// 双向链表打印
void ListPrint(LTNode*phead);
// 双向链表尾插
void ListPushBack(LTNode*phead,LTDataType x);
// 双向链表尾删
void ListPopBack(LTNode* pHead);
// 双向链表头插
void ListPushFront(LTNode*phead,LTDataType x);
// 双向链表头删
void ListPopFront(LTNode* pHead);
// 双向链表查找
LTNode * ListFind(LTNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(LTNode* pos);

具体功能的实现

1.创建新的结点

我们开辟一块新的元素,并将结点中的数据修改为我们传入的数据,并且将我们的前置结点和后置结点置空。

LTNode* BuyListNode(LTDataType x)
{
    LTNode *node=(LTNode*)malloc(sizeof(LTNode));
    if(node==NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    node->data=x;
    node->next=NULL;
    node->prev=NULL;
    return node;
}

2.双向链表的初始化

LTNode *ListInit()
{
    LTNode *phead= BuyListNode(-1);
    phead->next=phead;
    phead->prev=phead;
    return phead;
}

3.双向链表的尾插

void ListPushBack(LTNode*phead,LTDataType x)
{
    assert(phead);
    LTNode* newnode= BuyListNode(x);
    LTNode*tail=phead->prev;
    tail->next=newnode;
    newnode->prev=tail;
    newnode->next=phead;
    phead->prev=newnode;
}

4.双向链表的打印

void ListPrint(LTNode*phead)
{
    assert(phead);
    LTNode *temp=phead->next;
    while(temp!=phead)
    {
        printf("%d->",temp->data);
        temp=temp->next;
    }
    printf("\n");
    printf("已经成功打印完链表中的所有内容\n");
}

5.双向链表的头删

void ListPushFront(LTNode*phead,LTDataType x)
{
    assert(phead);

    LTNode*newnode= BuyListNode(x);
    LTNode *next=phead->next;

    phead->next=newnode;
    newnode->prev=phead;
    newnode->next=next;
    next->prev=newnode;
}

6.双向链表的摧毁

void ListDestory(LTNode* pHead)
{
    LTNode *p=pHead->next;
    while(p!=pHead)
    {
        LTNode *pp=p;
        p=p->next;
        free(pp);
    }
    pHead->next=pHead;
    pHead->prev=pHead;
    printf("已经成功摧毁整张链表\n");
}

7.双向链表的结点查找

LTNode * ListFind(LTNode* pHead, LTDataType x)
{
    assert(pHead);
    LTNode *p=pHead->next;
    while(p!=pHead&&p->data!=x)
    {
        p=p->next;
    }
    if(p->data==x)
    {
        return p;
    }
    else
    {
        printf("查找不到\n");
        return NULL;
    }
}

8.双向链表在pos位置之前插入

void ListInsert(LTNode* pos, LTDataType x)
{
    assert(pos);
    LTNode *p=pos->prev;
    LTNode *newnode= BuyListNode(x);
    newnode->next=pos;
    pos->prev=newnode;
    p->next=newnode;
    newnode->prev=p;
    printf("已成功实现插入%d\n",x);
}

9.删除目标位置的结点

void ListErase(LTNode* pos)
{
    assert(pos);
    LTNode *p=pos->prev;
    p->next=pos->next;
    pos->prev=p;
    printf("已经成功删除%d\n",pos->data);
    free(pos);
}

10.头删

我们只需要调用我们之前的删除函数就能够将我们的链表的第一个结点删除,也就是我们哨兵位结点的下一个结点

void ListPopFront(LTNode* pHead)
{
    ListErase(pHead->next);
}

11.尾删

由于我们的双向链表的哨兵位的前置指针指向我们双向链表的尾结点,所以我们只要通过我们双向链表的哨兵位结点的前置结点就可以找到我们的尾结点,然后调用我们的删除指定位置的函数删除我们的尾结点。

void ListPopFront(LTNode* pHead)
{
    ListErase(pHead->next);
}

汇总

以下代码全部写在List.c文件中

#include "List.h"
LTNode* BuyListNode(LTDataType x)
{
    LTNode *node=(LTNode*)malloc(sizeof(LTNode));
    if(node==NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    node->data=x;
    node->next=NULL;
    node->prev=NULL;
    return node;
}
LTNode *ListInit()
{
    LTNode *phead= BuyListNode(-1);
    phead->next=phead;
    phead->prev=phead;
    return phead;
}
void ListPushBack(LTNode*phead,LTDataType x)
{
    assert(phead);
    LTNode* newnode= BuyListNode(x);
    LTNode*tail=phead->prev;
    tail->next=newnode;
    newnode->prev=tail;
    newnode->next=phead;
    phead->prev=newnode;
}
void ListPrint(LTNode*phead)
{
    assert(phead);
    LTNode *temp=phead->next;
    while(temp!=phead)
    {
        printf("%d->",temp->data);
        temp=temp->next;
    }
    printf("\n");
    printf("已经成功打印完链表中的所有内容\n");
}

void ListPushFront(LTNode*phead,LTDataType x)
{
    assert(phead);

    LTNode*newnode= BuyListNode(x);
    LTNode *next=phead->next;

    phead->next=newnode;
    newnode->prev=phead;
    newnode->next=next;
    next->prev=newnode;
}
void ListDestory(LTNode* pHead)
{
    LTNode *p=pHead->next;
    while(p!=pHead)
    {
        LTNode *pp=p;
        p=p->next;
        free(pp);
    }
    pHead->next=pHead;
    pHead->prev=pHead;
    printf("已经成功摧毁整张链表\n");
}
LTNode * ListFind(LTNode* pHead, LTDataType x)
{
    assert(pHead);
    LTNode *p=pHead->next;
    while(p!=pHead&&p->data!=x)
    {
        p=p->next;
    }
    if(p->data==x)
    {
        return p;
    }
    else
    {
        printf("查找不到\n");
        return NULL;
    }
}
void ListInsert(LTNode* pos, LTDataType x)
{
    assert(pos);
    LTNode *p=pos->prev;
    LTNode *newnode= BuyListNode(x);
    newnode->next=pos;
    pos->prev=newnode;
    p->next=newnode;
    newnode->prev=p;
    printf("已成功实现插入%d\n",x);
}
void ListErase(LTNode* pos)
{
    assert(pos);
    LTNode *p=pos->prev;
    p->next=pos->next;
    pos->prev=p;
    printf("已经成功删除%d\n",pos->data);
    free(pos);
}
void ListPopFront(LTNode* pHead)
{
    ListErase(pHead->next);
}
void ListPopBack(LTNode* pHead)
{
    ListErase(pHead->prev);
}

以下是测试文件

#include"List.h"
int main() {
    LTNode* plist=ListInit();
    ListPushBack(plist,5);
    ListPushBack(plist,10);
    ListPushBack(plist,53);
    ListPushBack(plist,9);
    ListPushBack(plist,3);
    ListPushBack(plist,34);
    ListPushBack(plist,5);
    ListPushFront(plist,9);
    ListPrint(plist);
    ListInsert(ListFind(plist,9),8);
    ListPrint(plist);

//    ListErase(ListFind(plist,53));
    ListPopFront(plist);
    ListPrint(plist);
    ListPopBack(plist);
    ListPrint(plist);
    ListDestory(plist);
    return 0;
}

 

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桜キャンドル淵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值