数据结构 之 带头循环双链表

本文详细介绍了带头循环双链表的结构优势,包括可以方便地访问前后结点以及快速访问尾节点。文章还提供了带头循环双链表的基础操作实现,包括创建、初始化、插入、删除、查找和打印等操作,展示了这种链表结构的灵活性和实用性。
在数据结构中我们经常会接触到链表,链表也分好多种,带头结点和不带头结点、循环和不循环、单向链表和双向链表
而在众多不同结构的链表中 带头循环双链表可以说是一种最优的链表结构
相比于单链表只能访问当前结点的后续结点的局限性,双链表既可以访问前面结点也可以访问后面结点
其次循环的情况下相比于非循环的链表在访问尾节点时,非循环的链表余姚遍历整个链表才能访问尾节点,而循环链表由于它的循环特性,不用遍历链表,头结点前一个结点就是尾节点,在访问速度上大大优于非循环链表
带头相对于不带头在对链表头插时候不会改变头结点的地址,不带头的每次头插和头删都会改变头指针,而带头结点可以解决这个问题


定义我们双链表结点的结构体,包括三个部分,_next和_prev指针分别指向下一个和前一个结点,_data用来存放数据
typedef int DataType;
typedef struct DListNode//结点
{
       struct DListNode* _next;
       struct DListNode* _prev;
       DataType _data;
}DListNode;

对于双链表的基础操作包括结点的插入,结点的删除,寻找某个结点,打印链表,销毁链表等
DListNode* BuyDListNode(DataType x);//创建新结点
DListNode* DListInit();//双链表初始化
void DListDestory(DListNode* head);//销毁链表
void DListPrint(DListNode* head);//打印链表
void DListPushBack(DListNode* head, DataType x);//尾插
void DListPushFront(DListNode* head, DataType x);//头插
void DListPopBack(DListNode* head);//尾删
void DListPopFront(DListNode* head);//头删
DListNode* DListFind(DListNode* head, DataType x);//寻找值为x的结点,返回它的地址
void DListInsert(DListNode* pos, DataType x);//在pos位置插入值为x的新结点
void DListErase(DListNode* pos);//删除pos位置结点

创建新的结点时用malloc申请空间,注意要判断是否申请成功,同时对_data赋值,对_prev 和_next指针置空,返回新开辟的结点地址
DListNode* BuyDListNode(DataType x)//创建新的结点
{
       DListNode* NewNode = (DListNode*)malloc(sizeof(DListNode));
       if (NewNode)
       {
              NewNode->_data = x;
              NewNode->_next = NULL;
              NewNode->_prev = NULL;
              return NewNode;
       }
       return NULL;
}

带头循环双链表初始化时是初始化链表的 头Head,同样用malloc申请空间,此时链表里面为空,但是由于是循环链表,所以这块对Head->_nextHead->_prev都指向头,也就是自己本身,返回Head的地址
DListNode* DListInit()//链表初始化
{
       DListNode* Head = (DListNode*)malloc(sizeof(DListNode));
       if (Head)
       {
              Head->_next = Head;
              Head->_prev = Head;
              return Head;
       }
       return NULL;
}

插入操作
void DListPushBack(DListNode* head, DataType x)//尾插
{
       DListNode* NewNode = BuyDListNode(x);
       DListNode* cur = head;
       while (cur->_next != head)
       {
              cur = cur->_next;
       }
       cur->_next = NewNode;
       NewNode->_prev = cur;
       NewNode->_next = head;
       head->_prev = NewNode;
}
void DListPushFront(DListNode* head, DataType x)//头插
{
       DListNode* NewNode = BuyDListNode(x);
       DListNode* cur = head->_next;
       head->_next = NewNode;
       NewNode->_prev = head;
       NewNode->_next = cur;
       cur->_prev = NewNode;
}
void DListInsert(DListNode* pos, DataType x)//在pos位置插入值为x的新的结点
{
       DListNode* tmp = pos->_prev;
       DListNode* NewNode = BuyDListNode(x);
       tmp->_next = NewNode;
       NewNode->_prev = tmp;
       NewNode->_next = pos;
       pos->_prev = NewNode;
}
删除操作
void DListPopBack(DListNode* head)//尾删
{
       DListNode* cur = head->_prev->_prev;
       free(head->_prev);
       head->_prev = cur;
       cur->_next = head;
}
void DListPopFront(DListNode* head)//头删
{
       DListNode* cur = head->_next->_next;
       free(head->_next);
       head->_next = cur;
       cur->_prev = head;
}
void DListErase(DListNode* pos)//删除pos位置结点
{
       DListNode* tmp1 = pos->_prev;
       DListNode* tmp2 = pos->_next;
       tmp1->_next = tmp2;
       tmp2->_prev = tmp1;
        free(pos);
        pos = NULL;
}

寻找值为x的结点
DListNode* DListFind(DListNode* head, DataType x)//寻找值为x的结点,返回它的地址
{
       DListNode* tmp = head->_next;
       while (tmp->_next != head->_next)
       {
              if (tmp->_data == x)
              {
                     return tmp;
              }
              tmp = tmp->_next;
       }
       return NULL;
}
打印链表
void DListPrint(DListNode* head)//打印链表
{
       assert(head);
       DListNode* cur = head;
       printf("Head->");
       while (cur->_next != head)
       {
              cur = cur->_next;
              printf("%d->", cur->_data);
       }
       printf("Head\n");
}
销毁链表
void DListDestory(DListNode* head)
{
       if (head == NULL)
       {
              return;
       }
       DListNode* cur1 = head;
       DListNode* cur2 = head->_next;
       while (cur2)
       {
              free(cur1);
              cur1 = cur2;
              cur2 = cur2->_next;
       }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值