0


实现带头双向循环链表

🌈带头双向循环链表

在这里插入图片描述
描述:一个节点内包含两个指针,一个指向上一个节点,另一个指向下一个节点。哨兵位指向的下一个节点为头节点,哨兵位的上一个指向尾节点。
结构优势:高效率找尾节点;高效率插入与删除;无需判断多种复杂情况,如尾节点、空节点等。

🌈实现带头双向循环链表

☀️list.h

#define_CRT_SECURE_NO_WARNINGS#pragmaonce#include<stdio.h>#include<stdlib.h>#include<assert.h>typedefint DataType;typedefstructListNode{structListNode* prev;structListNode* next;
    DataType data;}ListNode;

ListNode*BuyListNode(DataType x);
ListNode*InitList();voidDestroyList(ListNode* phead);voidPrint(ListNode* phead);intCountSize(ListNode* phead);voidPushBack1(ListNode* phead, DataType x);voidPushBack2(ListNode* phead, DataType x);voidPopBack1(ListNode* phead);voidPopBack2(ListNode* phead);voidPushFront1(ListNode* phead, DataType x);voidPushFront2(ListNode* phead, DataType x);voidPopFront1(ListNode* phead);voidPopFront2(ListNode* phead);voidInsert(ListNode* pos, DataType x);voidErase(ListNode* pos);

☀️list.c

BuyListNode节点创建函数()

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

InitList链表初始化函数()

ListNode*InitList(){
    ListNode* phead =BuyListNode(0);
    phead->next = phead;
    phead->prev = phead;return phead;}

DestroyList链表销毁函数()

voidDestroyList(ListNode* phead){assert(phead);
    ListNode* cur = phead->next;while(cur != phead){
        ListNode* curnext = cur->next;free(cur);
        cur = curnext;}free(phead);}

打印节点信息函数Print()

voidPrint(ListNode* phead){assert(phead);printf("phead<=>");
    ListNode* cur = phead->next;while(cur != phead){printf("%d<=>", cur->data);
        cur = cur->next;}printf("\n");}

统计节点个数函数CountSize()

intCountSize(ListNode* phead){assert(phead);int size =0;
    ListNode* cur = phead->next;while(cur != phead){
        size++;
        cur = cur->next;}return size;}

在pos位置节点前插入函数Insert()

//在pos前插入voidInsert(ListNode* pos, DataType x){assert(pos);
    ListNode* posprev = pos->prev;
    ListNode* newnode =BuyListNode(x);
    posprev->next = newnode;
    newnode->prev = posprev;
    newnode->next = pos;
    pos->prev = newnode;}

删除pos位置节点函数Erase()

voidErase(ListNode* pos){assert(pos);
    ListNode* posprev = pos->prev;
    ListNode* posnext = pos->next;free(pos);
    posprev->next = posnext;
    posnext->prev = posprev;}

尾插(两种方法)PushBack1()&PushBack2()

voidPushBack1(ListNode* phead, DataType x){
    ListNode* tail = phead->prev;
    ListNode* newnode =BuyListNode(x);
    newnode->next = phead;
    phead->prev = newnode;
    tail->next = newnode;
    newnode->prev = tail;}voidPushBack2(ListNode* phead, DataType x){//尾插就相当于在哨兵位head前插入Insert(phead, x);}

尾删(两种方法)PopBack1()&PopBack2()

voidPopBack1(ListNode* phead){assert(phead);assert(phead->next != phead);
    ListNode* tail = phead->prev;
    ListNode* tailprev = tail->prev;free(tail);
    tailprev->next = phead;
    phead->prev = tailprev;}voidPopBack2(ListNode* phead){//尾节点就是phead的prev节点Erase(phead->prev);}

头插(两种方法)PushFront1()&PushFront2()

voidPushFront1(ListNode* phead, DataType x){assert(phead);
    ListNode* newnode =BuyListNode(x);
    ListNode* pheadnext = phead->next;
    newnode->next = pheadnext;
    pheadnext->prev = newnode;
    phead->next = newnode;
    newnode->prev = phead;}voidPushFront2(ListNode* phead, DataType x){//头插就相当于在phead后一个节点的前面插入assert(phead);Insert(phead->next, x);}

头删(两种方法)PopFront1()&PopFront2()

voidPopFront1(ListNode* phead){assert(phead);assert(phead->next != phead);
    ListNode* first = phead->next;
    ListNode* second = first->next;free(first);
    phead->next = second;
    second->prev = phead;}voidPopFront2(ListNode* phead){//头节点时哨兵位phead的下一个节点Erase(phead->next);}

☀️测试

测试尾插:test_PushBack(()

#define_CRT_SECURE_NO_WARNINGS#include"list.h"voidtest_PushBack(){
    ListNode* plist =InitList();PushBack1(plist,1);PushBack1(plist,2);PushBack1(plist,3);PushBack2(plist,1);PushBack2(plist,2);PushBack2(plist,3);Print(plist);DestroyList(plist);}

测试结果:
在这里插入图片描述

测试尾删:test_PopBack()

voidtest_PopBack(){
    ListNode* plist =InitList();PushBack1(plist,1);PushBack1(plist,2);PushBack1(plist,3);PushBack2(plist,1);PushBack2(plist,2);PushBack2(plist,3);Print(plist);PopBack1(plist);Print(plist);PopBack2(plist);Print(plist);DestroyList(plist);}

测试结果:
在这里插入图片描述

测试头插:test_PushFront()

voidtest_PushFront(){
    ListNode* plist =InitList();PushFront1(plist,1);PushFront1(plist,2);PushFront1(plist,3);PushFront2(plist,1);PushFront2(plist,2);PushFront2(plist,3);Print(plist);DestroyList(plist);}

测试结果:
在这里插入图片描述

测试头删:test_PopFront()

voidtest_PopFront(){
    ListNode* plist =InitList();PushFront1(plist,1);PushFront1(plist,2);PushFront1(plist,3);PushFront2(plist,1);PushFront2(plist,2);PushFront2(plist,3);Print(plist);PopFront1(plist);Print(plist);PopFront2(plist);Print(plist);DestroyList(plist);}

测试结果:
在这里插入图片描述

测试用主函数

intmain(){//测试尾插test_PushBack();//测试尾删test_PopBack();//测试头插test_PushFront();//测试头删test_PopFront();}

本文转载自: https://blog.csdn.net/2301_77203593/article/details/132589658
版权归原作者 希子71 所有, 如有侵权,请联系我们删除。

“实现带头双向循环链表”的评论:

还没有评论