数据结构——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;
}