双向不循环链表

双向不循环链表

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

typedef int DataType_t;

// 构造双向不循环链表的节点
typedef struct DoublyNonCirLinkedList
{
    DataType_t data;        // 节点的数据域
    struct DoublyNonCirLinkedList *prev; // 节点的前向指针域
    struct DoublyNonCirLinkedList *next; // 节点的后向指针域
} DoublyNonCirLiList_t;

// 创建一个空双向不循环链表,空链表应该有一个头节点,对链表进行初始化
DoublyNonCirLiList_t *DoublyNonCirLiList_Creat(void)
{
    // 1. 创建一个头结点,为头节点申请内存
    DoublyNonCirLiList_t *Head = (DoublyNonCirLiList_t *)calloc(1, sizeof(DoublyNonCirLiList_t));
    if (NULL == Head)
    {
        perror("Calloc memory for Head is failed");
        return NULL;
    }
    // 2. 对头节点进行初始化,头节点不存储有效内容,指针域初始化为 NULL
    Head->prev = NULL;
    Head->next = NULL;
    // 3. 把头结点的地址返回即可
    return Head;
}

// 创建链表的新的节点并对链表进行初始化
DoublyNonCirLiList_t *DoublyNonCirLiList_NewNode(DataType_t data)
{
    // 1. 创建一个新结点,为新节点申请内存
    DoublyNonCirLiList_t *New = (DoublyNonCirLiList_t *)calloc(1, sizeof(DoublyNonCirLiList_t));
    if (NULL == New)
    {
        perror("Calloc memory for NewNode is failed");
        return NULL;
    }
    // 2. 对新节点进行初始化
    New->data = data;
    New->prev = NULL;
    New->next = NULL;
    return New;
}

// 将新的节点插入到链表首节点//头插
bool DoublyNonCirLiList_HeadInsert(DoublyNonCirLiList_t *Head, DataType_t data)
{
    // 1. 创建新节点并对新节点进行初始化
    DoublyNonCirLiList_t *New = DoublyNonCirLiList_NewNode(data);
    if (NULL == New)
    {
        perror("can not insert new node\n");
        return false;
    }
    // 2. 将新节点插入到链表头部
    New->next = Head->next;
    if (Head->next != NULL)
    {
        Head->next->prev = New;
    }
    New->prev = Head;
    Head->next = New;
    return true;
}

// 将新的节点插入到链表尾节点//尾插
bool DoublyNonCirLiList_TailInsert(DoublyNonCirLiList_t *Head, DataType_t data)
{
    // 1. 创建新节点并对新节点进行初始化
    DoublyNonCirLiList_t *New = DoublyNonCirLiList_NewNode(data);
    if (NULL == New)
    {
        perror("can not insert new node\n");
        return false;
    }
    // 2. 找到链表的尾节点
    DoublyNonCirLiList_t *Phead = Head;
    while (Phead->next != NULL)
    {
        Phead = Phead->next;
    }
    // 3. 将新节点插入到链表尾部
    Phead->next = New;
    New->prev = Phead;
    return true;
}

// 将新的节点插入到链表指定节点之后//指定插
bool DoublyNonCirLiList_DestInsert(DoublyNonCirLiList_t *Head, DataType_t dest, DataType_t data)
{
    // 1. 创建新节点并对新节点进行初始化
    DoublyNonCirLiList_t *New = DoublyNonCirLiList_NewNode(data);
    if (NULL == New)
    {
        perror("can not insert new node\n");
        return false;
    }
    // 2. 找到指定节点
    DoublyNonCirLiList_t *Phead = Head->next;
    while (Phead != NULL && Phead->data != dest)
    {
        Phead = Phead->next;
    }
    if (Phead == NULL)
    {
        printf("data is not found\n");
        return false;
    }
    // 3. 将新节点插入到指定节点之后
    New->next = Phead->next;
    if (Phead->next != NULL)
    {
        Phead->next->prev = New;
    }
    New->prev = Phead;
    Phead->next = New;
    return true;
}

// 遍历
void DoublyNonCirLiList_Print(DoublyNonCirLiList_t *Head)
{
    // 对链表的头节点的下一个节点的地址进行备份
    DoublyNonCirLiList_t *Phead = Head->next;
    while (Phead != NULL)
    {
        // 输出当前节点的数据域
        printf("data = %d\n", Phead->data);
        // 输出当前节点的前一个节点和后一个节点的地址
        printf("prev = %p, next = %p\n", (void *)Phead->prev, (void *)Phead->next);
        // 移动到下一个节点
        Phead = Phead->next;
    }
}

// 删除首节点
bool DoublyNonCirLiList_HeadDel(DoublyNonCirLiList_t *Head)
{
    if (Head == NULL || Head->next == NULL)
    {
        perror("The LiList is empty");
        return false;
    }
    DoublyNonCirLiList_t *DelNode = Head->next;
    Head->next = DelNode->next;
    if (DelNode->next != NULL)
    {
        DelNode->next->prev = Head;
    }
    free(DelNode);
    return true;
}

// 删除尾节点
bool DoublyNonCirLiList_TailDel(DoublyNonCirLiList_t *Head)
{
    if (Head == NULL || Head->next == NULL)
    {
        perror("The LiList is empty");
        return false;
    }
    DoublyNonCirLiList_t *Phead = Head;
    while (Phead->next->next != NULL)
    {
        Phead = Phead->next;
    }
    DoublyNonCirLiList_t *DelNode = Phead->next;
    Phead->next = NULL;
    free(DelNode);
    return true;
}

// 删除指定节点
bool DoublyNonCirLiList_DestDel(DoublyNonCirLiList_t *Head, DataType_t dest)
{
    if (Head == NULL || Head->next == NULL)
    {
        perror("The LiList is empty");
        return false;
    }
    DoublyNonCirLiList_t *Phead = Head->next;
    while (Phead != NULL && Phead->data != dest)
    {
        Phead = Phead->next;
    }
    if (Phead == NULL)
    {
        printf("data is not found\n");
        return false;
    }
    Phead->prev->next = Phead->next;
    if (Phead->next != NULL)
    {
        Phead->next->prev = Phead->prev;
    }
    free(Phead);
    return true;
}

// 主函数,程序的入口
int main(int argc, char const *argv[])
{
    // 创建一个空的双向不循环链表
    DoublyNonCirLiList_t *Head = DoublyNonCirLiList_Creat();
    // 向链表尾部插入数据1
    DoublyNonCirLiList_TailInsert(Head, 1);
    // 向链表尾部插入数据2
    DoublyNonCirLiList_TailInsert(Head, 2);
    // 向链表尾部插入数据3
    DoublyNonCirLiList_TailInsert(Head, 3);
    // 向链表尾部插入数据4
    DoublyNonCirLiList_TailInsert(Head, 4);
    // 打印链表中的数据
    DoublyNonCirLiList_Print(Head);
    // 换行,用于分隔不同操作的输出结果
    printf("\n");
    // 向链表头部插入数据6
    DoublyNonCirLiList_HeadInsert(Head, 6);
    // 可以在此处调用其他操作函数进行测试
    // 再次打印链表中的数据
    DoublyNonCirLiList_Print(Head);
    // 换行,用于分隔不同操作的输出结果
    printf("\n");
    // 删除链表的首节点
    DoublyNonCirLiList_HeadDel(Head);
    // 打印链表中的数据
    DoublyNonCirLiList_Print(Head);
    // 换行,用于分隔不同操作的输出结果
    printf("\n");
    // 删除链表的尾节点
    DoublyNonCirLiList_TailDel(Head);
    // 打印链表中的数据
    DoublyNonCirLiList_Print(Head);
    // 输出头节点的地址
    printf("Head = %p\n", (void *)Head);
    // 程序正常结束,返回0
    return 0;
}    

运行结果

posted @ 2025-04-17 21:52  ice_cui  阅读(26)  评论(0)    收藏  举报