双向循环链表基本实现

实现双向循环链表的创建新节点,初始化,销毁,增加,删除,查找,求长度以及判空等基本操作。

头文件 List.h

#pragma once
#include<stdio.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;
	struct ListNode* _tail;
	int _size;
}List;
void ListInit(List* lt);
void ListDestory(List* lt);
void ListPushBack(List* lt, LTDataType x);
void ListPushFront(List* lt, LTDataType x);
void ListPopBack(List* lt,ListNode* pos,LTDataType x);
void ListPopFront(List* lt, ListNode* pos, LTDataType x);
ListNode* BuyListNode(LTDataType x);
ListNode* ListFind(List* lt, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x);
void ListErase(List* lt,ListNode* pos,LTDataType x);
int ListSize(List* lt);
int ListEmpty(List* lt);
void ListPrint(List* lt);
void testListNode();

 

test.c

1.创建新节点

#include "List.h"
ListNode* BuyListNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode != NULL)
	{
		newnode->_data = x;
		newnode ->_prev = NULL;
		newnode->_next = NULL;
	}
	return newnode;
}

2.链表初始化

void ListInit(List* lt)
{
	assert(lt != NULL);
	lt->_head= BuyListNode(0);
	lt->_head->_next = lt->_head;
	lt->_head->_prev = lt->_head;
}

3.链表销毁

void ListDestory(List* lt)
{
	ListNode* cur = NULL;
	ListNode* tail=NULL;
	assert(lt!= NULL);
		cur = lt;
		while (cur!=tail)
		{
			ListNode* del = cur;
			cur = cur->_next;
			free(del);
			del = NULL;
		}
		free(cur);
}

4.在链表中插入数据 注:因为是双向循环链表在任何地方插入都是一样的实现。

void ListInsert(ListNode* pos, LTDataType x) //pos之前插入  prev newnode pos
{
	assert(pos != NULL);
	ListNode* newnode;
	newnode = BuyListNode(3);
	newnode->_data = x;
	ListNode* prev = pos->_prev;
	prev->_next = newnode;
	newnode->_prev = prev;
	newnode->_next = pos;
	pos->_prev = newnode;
}
void ListPushBack(List* lt, LTDataType x)// tail newnode head
{
	ListInsert(lt->_head, x);
}
void ListPushFront(List* lt, LTDataType x) // tail newnode head
{
	ListInsert(lt->_head, x);
}

5.查找链表中指定位置元素

ListNode* ListFind(List* lt, LTDataType x)
{
	int i = 0;
	while (lt != NULL && lt->_head->_data != x)//寻找值为x的元素**注意这里循环的条件不能写反。原因,当L == NULL 时候 L->data会出错
	{
		i++;
		lt = lt->_head->_next;
	}
	if (lt == NULL)               //如果没找到返回-1
		return -1;
	else
		return x;
}

6.删除指定位置元素

void ListErase(List* lt,ListNode* pos,LTDataType x)
{
	if (lt == NULL && pos < 1)
	{
		return;
	}
	if (pos>ListSize(lt))
	{
		return;
	}
	ListNode *pNode = lt;
	int count = 0;
	while (count < ListSize(lt))
	{
		pNode = pNode->_next;
		count++;
	}
	if (count != pos)
		return;
	x = pNode->_data;
	pNode->_prev->_next = pNode->_next;
	pNode->_next->_prev = pNode->_prev;
	free(pNode);
	pNode = NULL;

}
void ListPopBack(List* lt, ListNode* pos, LTDataType x) // tail head
{
	assert(lt != NULL);
	ListErase(lt->_head, pos, x);
}
void ListPopFront(List* lt, ListNode* pos, LTDataType x)
{
	assert(lt != NULL);
	ListErase(lt->_head, pos, x);
}

7.求链表长度

int ListSize(List* lt)
{
	int size = 0;
	assert(lt != NULL);
	if (lt->_head!=lt->_head->_prev)
	{
		++size;
		lt->_head = lt->_head->_next;
	}
	return size;
}

9.判断链表是否为空

int ListEmpty(List* lt)
{
	if (ListSize(lt) == 0 && lt->_head->_next == lt->_head->_prev)
		return 1;
	else
		return 0;
}

10.打印链表

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

主函数

void testListNode()
{
	ListNode* s;
	ListInit(&s);
	ListPushBack(&s, 1);
	ListPushBack(&s, 2);
	ListPushBack(&s, 3);
	ListPushBack(&s, 4);
	ListPrint(&s);
	int ret = ListFind(&s, 3);
	if (ret != -1)
	{
		printf("%d ", ret);
	}
	else
	{
		printf("找不到");
	}
	printf("\n");
	int size=ListSize(&s);
	printf("%d ", size);
	printf("\n");
	int n = ListEmpty(&s);
	printf("%d ", n);
}
int main()
{
	testListNode();
	system("pause");
	return;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值