双向循环链表队列的接口设计

/*************************************************
 *
 *   file name:DoubleLinkQueue.c
 *   author   :momolyl@126.com
 *   date     :2024/04/28
 *   brief    :构建双向循环链队的接口
 *   note     :None
 *
 *   CopyRight (c) 2024    momolyl@126.com    All Right Reseverd
 *
 **************************************************/
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
/*************************************************
 *
 *   func name     :
 *   brief         :
 *   func parameter:
 *
 *
 *   return        :None
 *   note          :None
 *   func author   :momolyl@126.com
 *   date          :2024/04/28
 *   version       :V1.0
 **************************************************/
// 构建链队的结点(队数据域+指针域1+指针域2)
typedef int DataType_t;
typedef struct LinkQueue
{
    DataType_t Data;
    struct LinkQueue *Prev;
    struct LinkQueue *Next;

} LinkQueue_t;

// 创建一个空的顺序循环队列,并对其进行初始化
LinkQueue_t *LinkQueue_Creat(void)
{
    // 为循环队列的头结点申请内存空间
    LinkQueue_t *Head = (LinkQueue_t *)calloc(1, sizeof(LinkQueue_t));
    if (NULL == Head)
    {
        perror("calloc memory for Head is failed!\n");
        exit(-1);
    }
    Head->Next = Head;
    Head->Prev = Head;
    return Head;
}
// 创建新结点,并对其进行初始化
LinkQueue_t *LinkQueue_NewNode(DataType_t data)
{
    // 为循环队列的头结点申请内存空间
    LinkQueue_t *NewNode = (LinkQueue_t *)calloc(1, sizeof(DataType_t));
    if (NULL == NewNode)
    {
        perror("calloc memory for NewNode is failed!\n");
        return NewNode;
    }
    NewNode->Data = data;    // 初始化数据域
    NewNode->Prev = NewNode; // 初始化指针域1
    NewNode->Next = NewNode; // 初始化指针域2
    return NewNode;
}

// 判断队列是否为空
bool LinkQueue_IsEmpty(LinkQueue_t *Head)
{
    return (Head->Next == Head) ? true : false;
}

// 入队操作(尾插)
bool LinkQueue_Enqueue(LinkQueue_t *Head, DataType_t data)
{
    LinkQueue_t *Phead = Head->Next;
    LinkQueue_t *NewNode = LinkQueue_NewNode(data);
    if (LinkQueue_IsEmpty(Head)) // 判断链表是否为空
    {
        // 链表为空
        Head->Next = NewNode;    // 让头结点的Next指针指向新结点
        NewNode->Next = NewNode; // 让新结点的Next指针指向新结点
        NewNode->Prev = NewNode; // 让新结点的Prev指针指向新结点
        return true;
    }

    // 2.2链表非空

    NewNode->Prev = Phead->Prev; // 新节点的Prev指针指向尾结点
    NewNode->Next = Phead;       // 新结点的Next指针指向首结点
    Phead->Prev->Next = NewNode; // 尾结点的Next指针指向新结点
    Phead->Prev = NewNode;       // 首结点的Prev指针指向新结点
    return true;
}

// 出队操作(头删)
DataType_t LinkQueue_Dequeue(LinkQueue_t *Head)
{
    // 判断链表是否为空
    if (LinkQueue_IsEmpty(Head))
    {
        printf("Link queue is empty!\n");
        return false; // 为空则删除失败
    }
    DataType_t temp = Head->Next->Data;
    LinkQueue_t *Phead = Head->Next; // 备份首节点地址,用于最后释放首结点地址
    Phead->Prev->Next = Phead->Next; // 让尾结点的Next指针指向首节点的直接后继结点
    Phead->Next->Prev = Phead->Prev; // 让首结点的直接后继结点的Prev指针指向尾结点
    Head->Next = Phead->Next;        // 让头结点的Next指针指向首结点的直接后继结点
    Phead->Next = NULL;              // 让首结点的Next指针指向NULL
    Phead->Prev = NULL;              // 让首结点的Prev指针指向NULL
    free(Phead);
    return temp;
}

bool LinkQueue_Print(LinkQueue_t *Head)

{
    LinkQueue_t *Front = Head->Next; // 备份头结点

    while (Front->Next != Head->Next)
    {
        printf("%d ", Front->Data); // 打印链表

        Front = Front->Next; // 遍历链表
    }

    printf("%d ", Front->Data);
    printf("\n");
    return true;
}
int main(void)
{
    LinkQueue_t *Head = LinkQueue_Creat();
    LinkQueue_Enqueue(Head, 1);
    LinkQueue_Enqueue(Head, 2);
    LinkQueue_Enqueue(Head, 3);

    LinkQueue_Print(Head);
    printf("The dequeue element is %d\n", LinkQueue_Dequeue(Head));
    LinkQueue_Print(Head);
    return 0;
}
posted @   铃是铃铛的铃  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示