c语言实现链表以及部分函数功能

这篇博客介绍了链表的基础知识,包括链表的概念、分类以及如何使用C语言实现链表的基本操作,如单链表和双向循环链表的创建与管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、链表的概念:链表是一种非连续、非顺序的数据结构。
2、链表的分类:主要分为这三类:单链表、双向链表、循环链表,这三者又可以通过组合形成总共8种链表。
3、链表的基本操作:
首先时头文件部分.h

//不带头节点的单链表 

// 节点结构 
typedef struct SListNode
{
	int _data;
	struct SListNode* _pNext;
}Node;


// 给一个链表结构 
typedef struct SList
{
	Node* _pHead;
}SList;


// 链表的初始化 
void SListInit(SList* pl);

// 在链表中尾插值为data的节点 
void SListPushBack(SList* pl, int data);

// 删除链表最后一个节点 
void SListPopBack(SList* pl);

// 在链表第一个元素前插入值为data的节点 
void SListPushFront(SList* pl, int data);

// 删除链表中第一个节点 
void SListPopFront(SList* pl);

// 在链表pos位置后插入置为data的节点 
void SListInsertAfter(Node* pos, int data);

// 删除链表中值为data的节点 
void SListErase(SList* pl, Node* pos);

// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回空 
Node* SListFind(SList* pl, int data);

// 销毁链表 
void SListDestroy(SList* pl);

// 获取链表中有效节点的个数 
int SListSize(SList* pl);

// 检测链表是否为空 
int SListEmpty(SList* pl);

// 获取链表的第一个节点 
Node* SListFront(SList* pl);

// 获取链表的第二个节点 
Node* SListBack(SList* pl);

// 删除链表中第一个值为data的节点 
void SListRemove(SList* pl, int data);

// 删除链表中所有值为data的节点 
void SListRemoveAll(SList* pl, int data);



typedef struct DListNode
{
	struct DListNode* _pNext;
	struct DListNode* _pPre;
	int _data;
}DNode;

// 初始化双向链表 
void DListInit(DNode** pHead);

// 尾插 
void DListPushBack(DNode* pHead, int data);

// 尾删 
void DListPopBack(DNode* pHead);

// 头插 
void DListPushFront(DNode* pHead, int data);

// 头删 
void DListPopFront(DNode* pHead);

// 在链表中查找值为data的节点,找到返回节点的位置 
DNode* DListFind(DNode* pHead, int data);

// 在pos位置(插入成功后新节点实际在pos前)插入值为data的元素 
void DListInsert(DNode* pos, int data);

// 删除pos位置的节点 
void DListErase(DNode* pos);

// 将链表中的所有节点清空 
void DListClear(DNode* pHead);

// 销毁链表 
void DListDestroy(DNode** pHead);

接下来是各个函数的功能实现部分.c
1、不带头节点的单链表

// 链表的初始化 
void SListInit(SList * pl)
{
	pl->_pHead = NULL;
}

// 在链表中尾插值为data的节点 
void SListPushBack(SList* pl, int data)
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->_data = data;
	node->_pNext = NULL;
	if (pl != NULL)
	{
		Node* cur = pl;
		while (cur->_pNext != NULL)
		{
			cur = cur->_pNext;
		}
		cur->_pNext = node;
	}
	else
	{
		node = pl;
	}
}

// 删除链表最后一个节点 
void SListPopBack(SList* pl)
{
	assert(pl != NULL);
	if (pl->_pHead->_pNext == NULL)
	{
		free(pl);
		pl = NULL;
	}
	else
	{
		Node *cur = pl;
		while (cur->_pNext->_pNext != NULL)
		{
			cur = cur->_pNext;
		}
		free(cur->_pNext);
		cur->_pNext = NULL;
	}
	return pl;
}

// 在链表第一个元素前插入值为data的节点 
void SListPushFront(SList* pl, int data)
{
	Node *node = (Node *)malloc(sizeof(Node));
	node->_data = data;
	node->_pNext = pl;

	return node;
}

// 删除链表中第一个节点 
void SListPopFront(SList* pl)
{
	assert(pl != NULL);
	Node *next = pl->_pHead->_pNext;
	free(pl);
	return next;
}

// 在链表pos位置后插入置为data的节点 
void SListInsertAfter(Node* pos, int data)
{
	Node *node = (Node*)malloc(sizeof(Node));
	node->_data = data;
	node->_pNext = pos->_pNext;//应为node插入pos后,node的下一个就是pos得下一个
	pos->_pNext = node;
}

// 删除链表中值为data的节点 
void SListErase(SList* pl,int data)
{
	//链表为空
	if (pl == NULL)
	{
		return;
	}
	//遍历
	Node *cur = pl->_pHead;
	while (cur->_pNext != NULL)
	{
		if (cur->_data == data)
		{
			Node*next = cur->_pNext;

			free(cur);
			cur = next;
		}
		cur = cur->_pNext;
	}
}

// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回空 
Node* SListFind(SList* pl, int data)
{
	if (pl == NULL)
	{
		return NULL;
	}
	
	Node* cur = pl->_pHead;
	while (cur->_pNext != NULL)
	{
		if (cur->_data == data)
		{
			return cur;
			cur = cur->_pNext;
		}
	}
	return NULL;
}

// 销毁链表 
void SListDestroy(SList* pl)
{
	Node* cur = pl->_pHead;
	while (cur->_pNext != NULL)
	{
		Node* next = cur->_pNext;
		free(cur);
		cur = next;
	}
	pl->_pHead = NULL;
}

// 获取链表中有效节点的个数 
int SListSize(SList* pl)
{
	int count = 0;
	Node* cur = pl->_pHead;
	while (cur!= NULL)
	{
		cur = cur->_pNext;
		count++;
	}
	return count;
}

// 检测链表是否为空 
int SListEmpty(SList* pl)
{
	if (pl->_pHead == NULL)
	{
		return 1;
	}
	return 0;
}

// 获取链表的第一个节点 
Node* SListFront(SList* pl)
{
	return pl->_pHead;
}

// 获取链表的第二个节点 
Node* SListBack(SList* pl)
{
	return pl->_pHead->_pNext;
}

// 删除链表中第一个值为data的节点 
void SListRemove(SList* pl, int data)
{
	assert(pl != NULL);
	Node* cur = pl->_pHead;
	while (cur != NULL)
	{
		if (cur->_data == data)
		{
			Node *next = cur->_pNext;
			free(cur);
			cur = next;
			break;
		}
	}
}

// 删除链表中所有值为data的节点 
void SListRemoveAll(SList* pl, int data)
{
	assert(pl != NULL);
	Node *cur = pl->_pHead;
	while (cur != NULL)
	{
		if (cur->_data == data)
		{
			Node* next = cur->_pNext;
			free(cur);
			cur = next;
		}
	}
}

2、带头结点的双向循环链表

//双向链表

// 初始化双向链表 
void DListInit(DNode* pHead)
{
	DNode* node = (DNode*)malloc(sizeof(DNode));
	node->_data = 0;
	node->_pNext = node;
	node->_pPre = node;

	pHead = node;
}

// 尾插 
void DListPushBack(DNode* pHead, int data)
{
	assert(pHead != NULL);
	DNode *node = (DNode*)malloc(sizeof(DNode));
	node->_data = data;

	node->_pPre = pHead->_pPre;
	node->_pNext = pHead;
	pHead->_pPre->_pNext = node;
	pHead->_pPre = node;
}

// 尾删 
void DListPopBack(DNode* pHead)
{
	assert(pHead != NULL);
	if (pHead->_pNext = pHead)
	{
		return;
	}
	else
	{
		pHead->_pPre = pHead->_pPre->_pPre;
		free(pHead->_pPre->_pNext);
		pHead->_pPre->_pNext = pHead;
	}
}

// 头插 
void DListPushFront(DNode* pHead, int data)
{
	DNode* node = (DNode*)malloc(sizeof(DNode));
	node->_data = data;
	node->_pPre = pHead->_pPre;
	node->_pNext = pHead;
	pHead->_pPre->_pNext = node;
	pHead->_pPre = node;
}

// 头删 
void DListPopFront(DNode* pHead)
{
	assert(pHead != NULL);
	DNode* cur = pHead;
	pHead->_pNext->_pNext->_pPre = pHead;
	pHead->_pNext = pHead->_pNext->_pNext;
	free(cur);
	cur = NULL;
}

// 在链表中查找值为data的节点,找到返回节点的位置 
DNode* DListFind(DNode* pHead, int data)
{
	assert(pHead != NULL);
	DNode* cur = pHead;
	while (cur != NULL)
	{
		if (cur->_data == data)
		{
			return cur;
		}
		cur = cur->_pNext;
	}
	return NULL;
}

// 在pos位置(插入成功后新节点实际在pos前)插入值为data的元素 
void DListInsert(DNode* pos, int data)
{
	assert(pos);
	DNode* node = (DNode*)malloc(sizeof(DNode));
	node->_data = data;

	node->_pNext = pos;
	node->_pPre = pos->_pPre;
	pos->_pPre->_pNext = node;
	pos->_pPre = node;
}

// 删除pos位置的节点 
void DListErase(DNode* pos)
{
	assert(pos);
	pos->_pPre->_pNext = pos->_pNext;
	pos->_pNext->_pPre = pos->_pPre;
	free(pos);
	pos = NULL;
}

// 将链表中的所有节点清空 
void DListClear(DNode* pHead)
{
	assert(pHead != NULL);
	DNode* cur = pHead->_pNext;
	while (cur != pHead)
	{
		DNode* next = cur->_pNext;
		cur->_pNext->_pPre = cur->_pPre;
		cur->_pPre->_pNext = cur->_pNext;
        free(cur);
		cur = next->_pNext;
	}
}

// 销毁链表 
void DListDestroy(DNode** pHead)
{
	assert(pHead != NULL);
	DNode* cur = *pHead;
	cur = cur->_pNext;
	while (cur != *pHead)
	{
		DNode* next = cur->_pNext;
		free(cur);
		cur = next;
	}
	free(*pHead);
	*pHead = NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值