链表【数据结构】

本文介绍了单链表的基本概念及其实现方式,包括创建、插入、删除等核心操作,并提供了详细的代码实现。

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

链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点

链表分为

单链表

双链表

双向循环链表

链表与顺序表的比较:

顺序表支持随机访问,单链表不支持随机访问
顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)

顺序表的高速缓存效率更高,单链表CPU高速缓存效率低

这里介绍单链表的基本操作:

结构:

typedef struct SListPNode
{
	DataType _Data;
	struct SListPNode* _pNext;                   //指向下一节点的指针
}Node, *PNode;
创建新节点:

PNode BuySListNode(DataType data)
{
	PNode NewNode = (PNode)malloc(sizeof(Node));
	if (NULL == NewNode)
	{
		return NULL;
	}
	NewNode->_Data = data;
	NewNode->_pNext = NULL;
	return NewNode;
}

初始化:

void SListInit(PNode *ppHead)
{
	assert(ppHead);
	*ppHead = NULL;
}

头插:

void SListPushFront(PNode *ppHead, DataType data)
{
	assert(ppHead);
	PNode NewNode = BuySListNode(data);
	if (NULL == NewNode)
	{
		return;
	}
	NewNode->_pNext = *ppHead;
	*ppHead = NewNode;
}

头删:

void SListPopFront(PNode *ppHead)
{
	PNode pDel = NULL;
	assert(ppHead);
	if (NULL == *ppHead)                       //链表为空
	{
		return;
	}
	else
	{
		PNode pDel = *ppHead;             //移动头结点
		*ppHead = pDel->_pNext;
		free(pDel);                      //删除
	}
}

尾插:

void SListPushBack(PNode *ppHead, DataType data)
{
	PNode pNewNode = NULL;
	assert(ppHead);

	pNewNode = BuySListNode(data);
	if (NULL == pNewNode)		
	{
		return;
	}
	if (NULL == *ppHead)                                 //空链表
	{
		*ppHead = pNewNode;
	}
	else
	{
		PNode  pTailNode = *ppHead;		
		while (pTailNode->_pNext)                   //从头结点开始找到最后一个节点的位置
		{
			pTailNode = pTailNode->_pNext;
		}
		pTailNode->_pNext = pNewNode;
	}
}

尾删:

void SListPopBack(PNode *ppHead)
{
	assert(ppHead);
	if (NULL == *ppHead)                               //空链表
	{
		return;
	}
	else if (NULL ==(*ppHead)->_pNext)                //只有一个节点
	{
		free(*ppHead);
		*ppHead = NULL;
	}
	else				
	{
		PNode pTail = *ppHead;                     //标记最后一个节点
		PNode pPreTail = NULL;                     //标记最后一个节点的前一个节点
		while (pTail->_pNext)
		{
			pPreTail = pTail;
			pTail = pTail->_pNext;
		}
		free(pTail);
		pPreTail->_pNext = NULL;
	}

}

任意插入:

void SListInsert(PNode *ppHead, PNode pos, DataType data)
{
	assert(ppHead);

	PNode pPreNode = NULL;
	if (NULL == pos || NULL == *ppHead)                       //pos不存在或是空表
	{
		return;
	}
	else
	{
		PNode pNewNode = BuySListNode(data);
		if (*ppHead == pos)                               //头插
		{
			pNewNode->_pNext = *ppHead;
			*ppHead = pNewNode;
		}
		else
		{
			pPreNode = *ppHead;					
			while (pPreNode && pPreNode->_pNext != pos)                 //找到pos前一个节点
			{
				pPreNode = pPreNode->_pNext;
			}
			if (pPreNode)
			{
				pNewNode->_pNext = pos;
				pPreNode->_pNext = pNewNode;
			}
			else
			{
				return;
			}
		}
	}
}

任意删除:

void SListErase(PNode *ppHead, PNode pos)
{
	assert(ppHead);
	if (NULL == *ppHead || NULL == pos)
	{
		return;
	}
	else
	{
		if (*ppHead == pos)                        //头删
		{
			*ppHead = pos->_pNext;
			free(pos);
		}
		else
		{
			PNode pPrepos = *ppHead;
			while (pPrepos && pPrepos->_pNext != pos)
			{
				pPrepos = pPrepos->_pNext;
			}
			if (pPrepos)
			{
				pPrepos->_pNext = pos->_pNext;
				free(pos);
			}
			else
			{
				return;
			}
		}
	}
}

查找:

PNode Find(PNode pHead, DataType data)
{
	PNode pCur = pHead;
	while (pCur)
	{
		if (data == pCur->_Data)
		{
			return pCur;
		}
		pCur = pCur->_pNext;
	}
	return NULL;
}

递归查找:

PNode FindBack_D(PNode pHead, DataType data)
{
	if (pHead != NULL)
	{
		if (data == pHead->_Data)
			return pHead;
		return FindBack_D(pHead->_pNext, data);       //此处return返回,不能直接递归调用
	}
	return NULL;
}

打印:

void SListPrint(PNode pHead)
{
	PNode pCur = pHead;
	while (pCur)
	{
		printf(" %d->", pCur->_Data);
		pCur = pCur->_pNext;
	}
	printf("NULL\n");
}

销毁:

void SListDestroy(PNode* ppHead)
{
	PNode pCur = NULL;
	PNode pPreCur = NULL;
	assert(ppHead);
	pCur = *ppHead;
	while (pCur)
	{
		pPreCur = pCur;
		pCur = pCur->_pNext;
		free(pPreCur);
	}
	*ppHead = NULL;

	//while (pCur)
	//{
	//	*ppHead = pCur->_pNext;
	//	free(pCur);
	//	pCur = *ppHead;
	//}

}

SList.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int DataType;

typedef struct SListPNode
{
	DataType _Data;
	struct SListPNode* _pNext;                                      //指向下一节点的指针
}Node, *PNode;


void SListInit(PNode *ppHead);                                          //初始化
void SListPushBack(PNode *ppHead, DataType data);                       //尾插
void SListPopBack(PNode *ppHead);                                       //尾删
void SListPushFront(PNode *ppHead, DataType data);                      //头插
void SListPopFront(PNode *ppHead);					//头删

PNode BuySListNode(DataType data);                                      //创建新节点
PNode Find(PNode pHead, DataType data);                                 //查找

void SListInsert(PNode *ppHead,PNode pos, DataType data);               //任意位置插入(插入pos前)
void SListErase(PNode *ppHead, PNode pos);                              //任意位置删除
unsigned long SListSize(PNode pHead);                                   //链表结点个数
int SListEmpty(PNode pHead);                                            //链表判空
void SListDestroy(PNode* ppHead);                                       //链表销毁
void SListDestroy_D(PNode* ppHead);                                     //链表递归销毁

void SListPrint(PNode pHead);                                           //链表打印
SList.c
#include "SList.h"

PNode BuySListNode(DataType data)
{
	PNode NewNode = (PNode)malloc(sizeof(Node));
	if (NULL == NewNode)
	{
		return NULL;
	}
	NewNode->_Data = data;
	NewNode->_pNext = NULL;
	return NewNode;
}

void SListInit(PNode *ppHead)
{
	assert(ppHead);
	*ppHead = NULL;
}

void SListPushBack(PNode *ppHead, DataType data)
{
	PNode pNewNode = NULL;
	assert(ppHead);

	pNewNode = BuySListNode(data);
	if (NULL == pNewNode)
	{
		return;
	}
	if (NULL == *ppHead)
	{
		*ppHead = pNewNode;
	}
	else
	{
		PNode  pTailNode = *ppHead;
		while (pTailNode->_pNext)
		{
			pTailNode = pTailNode->_pNext;
		}
		pTailNode->_pNext = pNewNode;
	}
}

void SListPopBack(PNode *ppHead)
{
	assert(ppHead);
	if (NULL == *ppHead)
	{
		return;
	}
	else if (NULL ==(*ppHead)->_pNext)
	{
		free(*ppHead);
		*ppHead = NULL;
	}
	else
	{
		PNode pTail = *ppHead;		
		PNode pPreTail = NULL;
		while (pTail->_pNext)
		{
			pPreTail = pTail;
			pTail = pTail->_pNext;
		}
		free(pTail);
		pPreTail->_pNext = NULL;
	}

}

void SListPushFront(PNode *ppHead, DataType data)
{
	assert(ppHead);
	PNode NewNode = BuySListNode(data);
	if (NULL == NewNode)
	{
		return;
	}
	NewNode->_pNext = *ppHead;
	*ppHead = NewNode;
}

void SListPopFront(PNode *ppHead)
{
	PNode pDel = NULL;
	assert(ppHead);
	if (NULL == *ppHead)
	{
		return;
	}
	else
	{
		PNode pDel = *ppHead;
		*ppHead = pDel->_pNext;
		free(pDel);
	}
}

PNode Find(PNode pHead, DataType data)
{
	PNode pCur = pHead;
	while (pCur)
	{
		if (data == pCur->_Data)
		{
			return pCur;
		}
		pCur = pCur->_pNext;
	}
	return NULL;
}

void SListInsert(PNode *ppHead, PNode pos, DataType data)
{
	assert(ppHead);

	PNode pPreNode = NULL;
	if (NULL == pos || NULL == *ppHead)
	{
		return;
	}
	else
	{
		PNode pNewNode = BuySListNode(data);
		if (*ppHead == pos)	//头插
		{
			pNewNode->_pNext = *ppHead;
			*ppHead = pNewNode;
		}
		else
		{
			pPreNode = *ppHead;
			while (pPreNode && pPreNode->_pNext != pos)//找到pos前一个节点
			{
				pPreNode = pPreNode->_pNext;
			}
			if (pPreNode)
			{
				pNewNode->_pNext = pos;
				pPreNode->_pNext = pNewNode;
			}
			else
			{
				return;
			}
		}
	}
}


void SListErase(PNode *ppHead, PNode pos)
{
	assert(ppHead);
	if (NULL == *ppHead || NULL == pos)
	{
		return;
	}
	else
	{
		if (*ppHead == pos)//头删
		{
			*ppHead = pos->_pNext;
			free(pos);
		}
		else
		{
			PNode pPrepos = *ppHead;
			while (pPrepos && pPrepos->_pNext != pos)
			{
				pPrepos = pPrepos->_pNext;
			}
			if (pPrepos)
			{
				pPrepos->_pNext = pos->_pNext;
				free(pos);
			}
			else
			{
				return;
			}
		}
	}
}


int SListEmpty(PNode pHead)
{
	return NULL == pHead;
}

unsigned long SListSize(PNode pHead)
{
	unsigned long count = 0;
	PNode pCur = pHead;
	while (pCur)
	{
		count++;
		pCur = pCur->_pNext;
	}
	return count;
}

//正向销毁
void SListDestroy(PNode* ppHead)
{
	PNode pCur = NULL;
	PNode pPreCur = NULL;
	assert(ppHead);
	pCur = *ppHead;
	while (pCur)
	{
		pPreCur = pCur;
		pCur = pCur->_pNext;
		free(pPreCur);
	}
	*ppHead = NULL;

	//while (pCur)
	//{
	//	*ppHead = pCur->_pNext;
	//	free(pCur);
	//	pCur = *ppHead;
	//}

}

//逆向销毁
void SListDestroy_D(PNode* ppHead)
{
	assert(ppHead);
	if (*ppHead)
	{
		SListDestroy_D(&(*ppHead)->_pNext);
		free(*ppHead);
		*ppHead = NULL;
	}
}



void SListPrint(PNode pHead)
{
	PNode pCur = pHead;
	while (pCur)
	{
		printf(" %d->", pCur->_Data);
		pCur = pCur->_pNext;
	}
	printf("NULL\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值