您的位置:首页 > 教育 > 培训 > 美国 韩国 日本_广州番禺人才网官网_百度快照投诉中心官网_网络推广外包哪个公司做的比较好

美国 韩国 日本_广州番禺人才网官网_百度快照投诉中心官网_网络推广外包哪个公司做的比较好

2025/2/24 9:31:09 来源:https://blog.csdn.net/qq_70199082/article/details/143961410  浏览:    关键词:美国 韩国 日本_广州番禺人才网官网_百度快照投诉中心官网_网络推广外包哪个公司做的比较好
美国 韩国 日本_广州番禺人才网官网_百度快照投诉中心官网_网络推广外包哪个公司做的比较好

        链表的结构分为8中,其实搞懂了单链表和双向哨兵位循环链表,这部分的知识也就掌握的差不多了。双向哨兵位循环链表的结构如下:        

        下面我从0构建一个双向哨兵位循环链表。

1、准备工作 

        构建节点结构体,双向循环链表的每一个节点内需要有两个指针变量,一个指针变量指向前一个节点,另一个指针变量指向后一个节点。这里将指向前一个节点的指针变量命名为prev,指向后一个节点的指针变量命名为next,那么节点的结构可以定义为:

typedef int LDataType;typedef struct LNode
{LDataType data;struct LNode* prev;struct LNode* next;}LNode;

       存储的数据类型为LDataType类型。

2、链表的初始化与销毁

        在链表的初始化部分,我们需要创建一个哨兵位节点用于后面链表的搭建。它的结构可以定义为下面的形式:

        哨兵位节点的prev和next指针均指向自己本身从而形成循环,代码可以写成如下的形式:

LNode* LNodeCreat()
{LNode* pHead = (LNode*)malloc(sizeof(LNode));if (pHead == NULL){perror("malloc fail");return NULL;}pHead->next = pHead->prev = pHead;return pHead;
}

         链表的销毁部分应该考虑到后续插入来的节点,应该遍历整个链表将每一个节点进行释放并置空,最后再销毁哨兵位的头节点。

void LNodeDestroy(LNode* pHead)
{assert(pHead);LNode* cur = pHead->next;while (cur != pHead){LNode* next = cur->next;free(cur);cur = next;}free(pHead);
}

3、链表的末尾插入

        这里将创建一个新的节点封装成一个函数,为了方便后面继续使用。创建的新节点的prev和next均指向NULL,新节点内包含的数据为用户需要插入的数据val.下面是创建节点的函数实现:

LNode* BuyNewNode(LDataType val)
{LNode* newNode = (LNode*)malloc(sizeof(LNode));if (newNode == NULL){perror("BuyNewNode malloc fail");return NULL;}newNode->prev = newNode->next = NULL;newNode->data = val;
}

        创建的新节点的逻辑结构可以想象成下面的形式:

       我们知道,链表的尾插是需要找到尾节点的,在这里可以很方便的找到链表的尾节点tail,因为哨兵位的头节点指向的就是链表的尾节点,所以说不管原链表中是否存在节点在这里均可视为一种情况,插入的逻辑图为:

 

        代码的实现如下:

void LNodePushBack(LNode* pHead, LDataType val)
{assert(pHead);LNode* newNode = BuyNewNode(val);LNode* tail = pHead->prev;tail->next = newNode;newNode->prev = tail;pHead->prev = newNode;newNode->next = pHead;
}

4、链表的打印

        上面实现了链表的尾插,为了验证上述代码的正确性,这里先来写链表的打印,以便及时发现存在的问题。这里的思想就是遍历整个链表打印节点中的数据。

void LNodePrint(LNode* pHead)
{assert(pHead);LNode* cur = pHead->next;while (cur != pHead){printf("%d <=>", cur->data);LNode* next = cur->next;cur = next;}printf("\n");}

        这里先来测试一下上述代码能否正常实现双向带头链表的功能。

//测试代码
void test()
{LNode* pList = LNodeCreat();LNodePushBack(pList, 1);LNodePushBack(pList, 2);LNodePushBack(pList, 3);LNodePushBack(pList, 4);LNodePrint(pList);LNodeDestroy(pList);
}int main()
{test();return 0;
}

        输出结果:

5、链表的头部插入

        头插的操作是十分简单的,在插入之前记录一下第一个节点的位置用于和新创建的节点链接。逻辑结构可以化成如下的形式:

        代码实现如下:

void LNodePushFront(LNode* pHead, LDataType val)
{assert(pHead);LNode* newNode = BuyNewNode(val);LNode* first = pHead->next;newNode->prev = pHead;pHead->next = newNode;newNode->next = first;first->prev = newNode;
}

 6、链表的尾删

        逻辑结构如下图所示:

        代码实现如下:

void LNodePopBack(LNode* pHead)
{assert(pHead);assert(pHead->prev != pHead);LNode* tail = pHead->prev;LNode* last = tail->prev;pHead->prev = last;last->next = pHead;free(tail);tail = NULL;
}

7、链表的头删

        逻辑结构如下:

        代码实现:

void LNodePopFront(LNode* pHead)
{assert(pHead);assert(pHead->prev != pHead);LNode* del = pHead->next;LNode* first = del->next;pHead->next = first;first->prev = pHead;free(del);del = NULL;
}

 8、链表节点的查找

        查找到目标节点,返回目标节点的地址,用于后续的操作。代码实现:

LNode* FindNode(LNode* pHead, LDataType val)
{assert(pHead);LNode* cur = pHead->next;while (cur != pHead){if (cur->data == val)return cur;cur = cur->next;}return NULL;
}

9、链表在pos前插入

        配合上面的查找函数进行使用,先查找到pos的位置,再进行插入操作。

        代码实现:

//在pos的前面插入
void LNodeInsert(LNode* pos, LDataType val)
{assert(pos);LNode* posPrev = pos->prev;LNode* newNode = BuyNewNode(val);posPrev->next = newNode;newNode->prev = posPrev;newNode->next = pos;pos->prev = newNode;}

10、删除pos位置的节点

        这个函数还是要配合查找函数进行使用,逻辑图如下:

        代码实现:

void LNodeErase(LNode* pos)
{assert(pos);LNode* posPrev = pos->prev;LNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);pos = NULL;}

         至此,哨兵位头节点的双向循环链表已全部实现。希望能帮到读者。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com