有头节点的双向循环链表源代码

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <malloc.h>
//带头节点双向循环 
//带头节点优点容易写删除操作 双向优点可以找到节点前一个,循环优点容易找到尾节点
typedef  int LTDateType;

typedef struct ListNode//节点的属性有单和双向之分但是无法区别带头还是不带头 
{
	LTDateType _data;
	struct ListNode *_next;
	struct ListNode *_prev;
}ListNode;

typedef struct List
{
	ListNode *_head;
}List;
//函数的声明
void ListInit(List *list);//建立 
void ListDestory(List *plist);//销毁 
void ListPrint(List *plist);//显示,可以传List型参数但效率低,因为要构造新的List变量

ListNode *BuyListNode();
void ListPushBack(List *plist,LTDateType x);
void ListPopBack(List *plist);
void ListPushFront(List *plist,LTDateType x);
void ListPopFront(List *plist);

ListNode* ListFind(List* plist,LTDateType x);

void ListInsert(ListNode* pos,LTDateType x);//在pos节点前链接值为x的节点 
void ListErase(ListNode* pos);
void ListRemove(List* plist,LTDateType x);//找到x的节点删除 

int ListSize(List* plist);
int ListEmpty(List* plist);
//函数的实现
ListNode *BuyListNode(LTDateType x)
{
	ListNode *node= (ListNode*)malloc(sizeof(ListNode));
	node->_data = x;
	node->_next = NULL;//初始化要有头尾节点 
	node->_prev = NULL;
	return node;
}

void ListInit(List *plist)
{
	assert(plist);
	plist->_head = BuyListNode(-1);
	plist->_head->_next = plist->_head;
	plist->_head->_prev = plist->_head;
}

void ListDestory(List *plist)
{
	assert(plist);
	ListNode* cur = plist->_head->_next;
	ListNode* next ;
	while(cur!=plist->_head)
	{
	    next = cur->_next;
		free(cur);
		cur = next;
	}
	free(plist->_head);
	plist->_head = NULL;
	
}

void ListPushBack(List *plist,LTDateType x)
{
	assert(plist); 
	ListNode* head = plist->_head;
	ListNode* tail = head->_prev;
	ListNode* newnode =   BuyListNode(x);
	tail->_next = newnode;
	newnode->_prev = tail;
	head->_prev = newnode; 
	newnode->_next = head; 
	
}

void ListPopBack(List *plist)
{
	ListNode *cur = plist->_head;
	while(cur->_next!=plist->_head)
	{
		cur = cur->_next;
	}
	if(cur!=plist->_head)
	{
	cur->_prev->_next = cur->_next;
	cur->_next->_prev = cur->_prev;
	free(cur);
	cur = NULL;	
	}
}

void ListPushFront(List *plist,LTDateType x)
{
	assert(plist);
	
	ListNode* newnode =   BuyListNode(x);
	ListNode* next = plist->_head->_next;
	plist->_head->_next = newnode;
	newnode->_prev = plist->_head;
	next->_prev = newnode;
	newnode->_next = next;
}

void ListPopFront(List *plist)
{
	assert(plist&& plist->_head->_next!=plist->_head);
	ListNode *cur = plist->_head->_next;
	plist->_head->_next = cur->_next;
	cur->_next->_prev = plist->_head; 
	free(cur);
	
}

void ListPrint(List *plist)
{
	assert(plist&&plist->_head);
	ListNode *cur = plist->_head->_next;
	if(cur!=plist->_head)
	{
	printf("%d->",cur->_data);
		cur = cur->_next;	
	}
	
	while(cur!=plist->_head)
	{
		printf("<-%d->",cur->_data);
		cur = cur->_next;
	}
	printf("\n"); 
}

ListNode* ListFind(List* plist,LTDateType x)
{
	ListNode *cur = plist->_head;
	while(cur->_next!=plist->_head)
	{
		if(cur->_data == x)
		return cur;
		cur = cur->_next;
	}
	return nullptr;
}

void ListInsert(ListNode* pos,LTDateType x)
{
	ListNode* prev = pos->_prev;
	ListNode* cur =BuyListNode(x);
	prev->_next = cur;
	cur->_prev  = prev;
	cur->_next = pos;
	pos->_prev = cur;
	
}
 
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* next = pos->_next;
	ListNode* prev = pos->_prev;
	next->_prev = pos->_prev;
	prev->_next = pos->_next;
	free(pos);
}

void ListRemove(List* plist,LTDateType x)
{
	ListNode *cur = ListFind(plist,x);
	if(cur!=nullptr)
	{
		ListErase(cur);
	}
}

int ListSize(List* plist)
{
	assert(plist);
ListNode *cur = plist->_head;
int size = 0;

		while(cur->_next!=plist->_head)	
	{
		size++;
		cur = cur->_next;
	}
	return size;
}

int ListEmpty(List* plist)
{
	assert(plist);
	ListNode *cur = plist->_head;
	if(cur->_next!=cur)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
//测试函数
void test()
{
	List plist;
	ListInit(&plist);
	ListPushBack(&plist,1);
	ListPushBack(&plist,2);
	ListPushBack(&plist,3);
	ListPushBack(&plist,4);
	ListPushBack(&plist,5);
	ListPrint(&plist);
	ListRemove(&plist,4);
	ListPrint(&plist);
	printf("%d   ",ListSize( &plist));
	ListDestory(&plist);
	ListInit(&plist);
	printf("%d   ",ListEmpty(&plist));
}


//主函数
int main()
{
	test();
}

双向循环有头链表,是一种结构复杂,但是操作简单的数据结构,是一种对于单向无循环无头链表的优化后的数据结构,需要注意以下几点

(1)双向链表有三个成员分别为数据域以及前后指针,在双向链表的初始化(Insert)中要让前后指针指向自己,方便之后的函数实现,

(2)通过链表的尾的后面指向头可以实现很多操作

(3)对于节点的增删要注意增加删除的指针要修改指向方向如下图

 

在加入一个新节点需要

删除节点则为

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值