欢迎访问宙启技术站
智能推送

C语言实现带头双向循环链表的接口

发布时间:2023-05-15 22:50:11

C语言实现带头双向循环链表的接口

链表是一种常见的数据结构,是用于存储数据元素的一种线性结构。链表的特点是可以动态地添加和删除元素,相比于数组,链表的优势在于插入和删除元素的时间复杂度是O(1),而数组的时间复杂度是O(n)。其中,循环链表是一种特殊的链表形式,其特点是链表的最后一个节点连接了 个节点,形成了一个环。而带头双向循环链表则是在链表头部增加了一个哨兵节点,同时每个节点都存储了前驱和后继节点的地址,因此可以很方便地实现双向遍历的功能。

下面是C语言实现带头双向循环链表的接口:

1.链表节点定义

typedef struct ListNode

{

    int data; //节点数据

    struct ListNode* prev; //前驱节点指针

    struct ListNode* next; //后继节点指针

}ListNode, * PListNode;

2.初始化链表

void InitList(PListNode* pHead)

{

    *pHead = (PListNode)malloc(sizeof(ListNode)); //创建头节点

    (*pHead)->prev = (*pHead)->next = *pHead; //初始化头节点的前驱和后继节点

}

3.判断链表是否为空

int ListEmpty(PListNode pHead)

{

    return pHead->next == pHead;

}

4.获取链表长度

int ListLength(PListNode pHead)

{

    int len = 0;

    PListNode pNode = pHead->next;

    while (pNode != pHead)

    {

        len++;

        pNode = pNode->next;

    }

    return len;

}

5.获取链表指定位置的节点

PListNode GetNode(PListNode pHead, int index)

{

    PListNode pNode = pHead->next;

    int i = 0;

    while (pNode != pHead && i < index)

    {

        pNode = pNode->next;

        i++;

    }

    return pNode;

}

6.获取链表指定节点的数据

int GetData(PListNode pNode)

{

    return pNode->data;

}

7.在链表指定位置插入节点

void InsertNode(PListNode pHead, int index, int data)

{

    PListNode pNode = GetNode(pHead, index - 1);

    PListNode pNewNode = (PListNode)malloc(sizeof(ListNode));

    pNewNode->data = data;

    pNewNode->prev = pNode;

    pNewNode->next = pNode->next;

    pNode->next->prev = pNewNode;

    pNode->next = pNewNode;

}

8.删除链表指定位置的节点

void DeleteNode(PListNode pHead, int index)

{

    PListNode pNode = GetNode(pHead, index - 1);

    PListNode pDeleteNode = pNode->next;

    pNode->next = pDeleteNode->next;

    pDeleteNode->next->prev = pNode;

    free(pDeleteNode);

}

9.清空链表

void ClearList(PListNode pHead)

{

    PListNode pNode = pHead->next;

    PListNode pNext = NULL;

    while (pNode != pHead)

    {

        pNext = pNode->next;

        free(pNode);

        pNode = pNext;

    }

    pHead->prev = pHead->next = pHead;

}

10.销毁链表

void DestroyList(PListNode* pHead)

{

    ClearList(*pHead);

    free(*pHead);

    *pHead = NULL;

}

总结

带头双向循环链表在实际开发中应用广泛,尤其是在需要频繁进行前后节点遍历的情况下会有很好的性能表现。但是需要注意的是,在编写代码时尽量简洁明了,减少节点指针的引用次数和内存的申请和释放,避免内存泄漏和指针无法释放的问题。