欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构--带头双向循环链表的基本功能实现

程序员文章站 2022-03-15 19:41:08
...

带头双向循环链表 : 是一种无死角链表, 是链表的一种,带有头结点, 其次它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点 , 且它的头指向尾 , 尾指向头 , 是循环的 , 是双向的 , 是带头结点的 ,

基本结构如下图所示 :          

 

                     数据结构--带头双向循环链表的基本功能实现

 

List.h

#pragma once
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <assert.h>
typedef int LTDataType;

//链表结构体
typedef struct ListNode
{
	struct ListNode* _next;
	struct ListNode* _prev;
	LTDataType _data;
}ListNode;

typedef struct List
{
	struct ListNode* _head;
}List;

//初始化链表
void ListInit(List* lt);
//销毁链表
void ListDestory(List* lt);
//头插
void ListPushFront(List* lt, LTDataType x);
//尾插
void ListPushBack(List* lt, LTDataType x);
//头删
void ListPopFront(List* lt);
//尾删
void ListPopBack(List* lt);
//申请节点
ListNode* BuyListNode();
//查找节点
ListNode* ListFind(List* lt, LTDataType x);
//指定位置插入
void ListInsert(ListNode* pos, LTDataType x);
//指定位置删除
void ListErase(ListNode* pos);
//链表大小
int ListSize(List* lt);
//判断链表是否为空
int ListEmpty(List* lt);
//打印链表
void ListPrint(List* lt);

 List.c

#include "List.h"
//初始化链表
void ListInit(List* lt)
{
	//创建头结点
	lt->_head = BuyListNode();
	lt->_head->_next = lt->_head;
	lt->_head->_prev = lt->_head;
}
//销毁链表
void ListDestory(List* lt)
{
	ListNode *del,*ret;
	assert(lt);
	del = lt->_head->_next;
	while (del == lt->_head)
	{
		ret = del;
		free(ret);
		ret = NULL;
		del = del->_next;
	}
	free(del);
	del = NULL;
}
//头插
void ListPushFront(List* lt, LTDataType x)
{
	assert(lt);
	//相当于在头结点后面插入
	ListInsert(lt->_head->_next, x);
}
//尾插
void ListPushBack(List* lt, LTDataType x)
{
	assert(lt);
	//相当于在头结点前面插入
	ListInsert(lt->_head->_prev, x);
}
//头删
void ListPopFront(List* lt)
{
	assert(lt);
	//相当于删除头结点后面的元素
	ListErase(lt->_head->_prev);
}
//尾删
void ListPopBack(List* lt)
{
	assert(lt);
	//相当于删除头结点前面的元素
	ListErase(lt->_head->_next);
}
//申请节点
ListNode* BuyListNode()
{
	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	//断言,空间是否开辟成功
	assert(newNode);
	newNode->_next = NULL;
	newNode->_prev = NULL;
	return newNode;
}
//查找节点
ListNode* ListFind(List* lt, LTDataType x)
{
	ListNode * newNode;
	assert(lt);
	newNode = lt->_head;
	while (newNode->_next != lt->_head)
	{
		newNode=newNode->_next;
		if (newNode->_data == x)
			return newNode;
	}
	printf("要查找的数据 %d 不存在!\n",x);
	return NULL;
}
//指点位置插入
void ListInsert(ListNode* pos, LTDataType x)
{
	ListNode *prev;
	ListNode *newNode;
	if (!pos)
	{
		printf("数据 %d 插入失败!\n", x);
		return;
	}
	newNode = BuyListNode();
	newNode->_data = x;
	prev = pos->_prev;
	prev->_next = newNode;
	newNode->_prev = prev;
	newNode->_next = pos;
	pos->_prev = newNode;
}
//指点位置删除
void ListErase(ListNode* pos)
{
	ListNode *prev;
	prev = pos->_prev;
	prev->_next = pos->_next;
	pos->_next->_prev = prev;
	free(pos);
	pos = NULL;
}
//链表大小
int ListSize(List* lt)
{
	ListNode *cur;
	int size = 0;
	assert(lt);
	assert(lt);
	cur = lt->_head;
	while (cur->_next != lt->_head)
	{
		cur = cur->_next;
		size++;
	}
	return size;
}
//判断链表是否为空
int ListEmpty(List* lt)
{
	assert(lt);
	//为空返回0,非空返回1
	return lt->_head->_next == lt->_head->_prev ? 0 : 1;
}
//打印链表
void ListPrint(List* lt)
{
	ListNode *cur;
	assert(lt);
	cur = lt->_head;
	printf("链表中的数据为: ");
	while (cur->_next != lt->_head)
	{
		printf("%d ", cur->_next->_data);
		cur = cur->_next;
	}
	printf("\n");
}

test.c

#include "List.h"
int main()
{
	List lt;
	ListNode *cur;
	ListInit(&lt);
	ListPushBack(&lt, 1);
	ListPushBack(&lt, 2);
	ListPushBack(&lt, 3);
	ListPushBack(&lt, 4);
	cur = ListFind(&lt, 3);
	ListErase(cur);
	cur = ListFind(&lt, 4);
	ListInsert(cur, 5);
	printf("链表的长度为: %d\n", ListSize(&lt));
	ListPrint(&lt);
	ListDestory(&lt);
	system("pause");
	return 0;
}