数据结构——C语言实现带头双向循环链表

2023年6月10日13:08:17

数据结构——C语言实现带头双向循环链表
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了,比单链表实用的多。
图示:
在这里插入图片描述
ListNode.h文件:

#include<stdio.h>
typedef struct ListNode
{
 DataType _data;
 struct ListNode* _next;
 struct ListNode* _prev;
}ListNode;
typedef struct List
{
 struct ListNode* _head;
}List;
void ListInit(List* plist);//初始化带头双向循环链表
void ListDestory(List* plist);//销毁
ListNode* CreatListNode(DataType x);//
void ListPushBack(List* plist, DataType x);//尾插
void ListPopBack(List* plist);//尾删
void ListPushFront(List* plist, DataType x);//头插
void ListPopFront(List* plist);//头删
void ListInsert(List* plist,ListNode* pos, DataType x);//在pos前面插入
void ListErase(List* plist,ListNode* pos); // 删除pos位置的结点
void ListPrint(List* plist);
void testList();

ListNode.c文件:

#include"ListNode.h"
#include<assert.h>
#include<malloc.h>
//初始化链表
void ListInit(List* plist)
{
 assert(plist);
 plist->_head = CreatListNode(0);
 //仅有头结点时前驱结点和后继结点均指向自身
 plist->_head->_next = plist->_head;
 plist->_head->_prev = plist->_head;
}
//销毁链表
void ListDestory(List* plist)
{
 assert(plist);
 ListNode* cur=plist->_head->_next;
 while (cur != plist->_head)
 {
  ListNode* next = cur->_next;
  //遍历释放空间
  free(cur);
  //释放空间后将其置为空
  cur = next;
 }
 //最后释放头结点
 free(plist->_head);
 plist->_head = NULL;
}
//生成新结点
ListNode* CreatListNode(DataType x)
{
//分配空间
 ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
 //为新结点赋值
 newNode->_data = x;
 newNode->_next = newNode->_prev = NULL;
 return newNode;
}
//尾插
void ListPushBack(List* plist, DataType x)
{
 assert(plist);
 ListNode* newNode = CreatListNode(x);
 ListNode* tail = plist->_head->_prev;
 tail->_next = newNode;
 newNode->_next = plist->_head;
 newNode->_prev = tail;
 plist->_head->_prev = newNode;
}
//尾删
void ListPopBack(List* plist)
{
 assert(plist);
 ListNode* prev, * tail;
 //判断是否为头结点
 if (plist->_head == plist->_head->_next)
 {
  return;
 }
 tail = plist->_head->_prev;
 prev = tail->_prev;
 prev->_next = plist->_head;
 plist->_head->_prev = prev;
 free(tail);
 tail = NULL;
}
//头插
void ListPushFront(List* plist, DataType x)
{
 assert(plist);
 ListNode* newNode = CreatListNode(x);
 ListNode* next = plist->_head->_next;
 plist->_head->_next = newNode;
  newNode->_prev = plist->_head;
 newNode->_next = next;
 next->_prev = newNode;
}
//头删
void ListPopFront(List* plist)
{
 assert(plist);
 ListNode* next = plist->_head->_next;
 ListNode* nextnext=next->_next;
 //判断是否为头结点
 if (plist->_head == plist->_head->_next)
 {
  return;
 }
 plist->_head->_next = nextnext;
 nextnext->_prev = plist->_head;
 free(next);
 next = NULL;
}
//在pos位置前面插入
void ListInsert(List* plist, ListNode* pos, DataType x)
{
 assert(plist && pos);
 ListNode* prev = pos->_prev;
 ListNode* newNode = CreatListNode(x);
 prev->_next = newNode;
 newNode->_prev = prev;
 newNode->_next = pos;
 pos->_prev = newNode;
}
//删除pos位置的结点
void ListErase(List* plist,ListNode* pos)
{
 assert(plist && pos);
 ListNode* prev, * next;
 //判断是否为头结点
 if (plist->_head == pos)
 {
  return;
 }
 prev = pos->_prev;
 next = pos->_next;
 prev->_next = next;
 next->_prev = prev;
 free(pos);
 pos = NULL;
}
//打印链表
void ListPrint(List* plist)
{
 assert(plist);
 ListNode* cur = plist->_head->_next;
 while (cur != plist->_head)
 {
    printf("%d->", cur->_data);
    cur = cur->_next;
 }
 printf("\n");
}
//测试
void testList()
{
 List list;
 ListInit(&list);
 ListPushBack(&list, 1);
 ListPushBack(&list, 2);
 ListPushBack(&list, 3);
 ListPushBack(&list, 4);
 ListPushFront(&list, 1);
 ListPushFront(&list, 2);
 ListPushFront(&list, 3);
 ListPushFront(&list, 4);
 ListPrint(&list);
 ListPopBack(&list);
 ListPopFront(&list);
 ListPrint(&list);
 ListDestory(&list);
 ListPrint(&list);

main.c文件

int main()
{
 testList();
 return 0;
}

  • 作者:我爱吃香锅
  • 原文链接:https://blog.csdn.net/weixin_41028343/article/details/101173623
    更新时间:2023年6月10日13:08:17 ,共 3233 字。