实现单链表及其基本操作

单链表的定义:

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针

(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

单链表分为:1,有头单链表 2,无头单链表

本次主要针对无头单链表


链表的声明

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

typedef int DataType;
//带头单链表
typedef struct Node
{
	DataType _data;
	struct Node* _pNext;
}Node, *PNode;


链表的基本操作

注意:

在传入参数时,当需要修改pHead的指向时,需要传入二级指针PNode *pHead

当不需要改变pHead的指向时,只需传入一级指针PNode pHead即可。

// 初始化单链表
void InitList(PNode* pHead);
//销毁链表
void DestroyList(PNode *pHead);

// 在单链表的尾部插入一个节点
void PushBack(PNode* pHead, DataType data);

// 删除单链表的最后一个节点
void PopBack(PNode* pHead);

// 在单链表的头部插入值为data的结点
void PushFront(PNode* pHead, DataType data);

// 删除单链表的第一个结点
void PopFront(PNode* pHead);

// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(PNode pHead, DataType data);

// 在单链表pos位置后插入值为data的结点
void Insert(PNode pos, DataType data);

// 在单链表中删除位置为pos的结点
void Erase(PNode* pHead, PNode pos);

// 移除单链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data);

// 移除单链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data);

// 获取单链表总结点的总个数
size_t Size(PNode pHead);

// 判断结点是否为空
int Empty(PNode pHead);

// 返回单链表的最后一个结点的位置
PNode Back(PNode pHead);

// 返回单链表的第一个结点的位置
PNode Front(PNode pHead);

// 构建一个新节点
Node* BuyNode(DataType data);

// 正向打印单链表
void PrintList(PNode pHead);


链表基本功能实现

///只要改变了单链表的内容(指针指向内容),应使用PNode*二级指针。
///不然的话,在函数中改变了pHead的内容,函数外pHead还是指向原来的地址//
// 构建一个新节点
Node* BuyNode(DataType data)
{
	PNode pTemp = (PNode)malloc(sizeof(Node));

	if (NULL != pTemp)
	{
		pTemp->_data = data;
		pTemp->_pNext = NULL;
	}

	return pTemp;
}


// 初始化单链表
void InitList(PNode* pHead)
{	
	assert(NULL != pHead);
	*pHead = NULL;   //初始化为空
}

// 在单链表的尾部插入一个节点
void PushBack(PNode* pHead, DataType data)
{	
	PNode pNewNode = NULL;
	
	assert(NULL != pHead);

	if (!(pNewNode = BuyNode(data)))  //创建节点失败
		return ;
	
	if (NULL == *pHead)     //链表为空时
		*pHead = pNewNode;
	else		//链表不为空
	{
		PNode pTailNode = Back(*pHead);
		pTailNode->_pNext = pNewNode;
	}
}

// 在单链表的头部插入值为data的结点
void PushFront(PNode* pHead, DataType data)
{
	PNode pNewNode = NULL;

	assert(NULL != pHead);

	if (!(pNewNode = BuyNode(data)))//创建节点失败
		return ;

	if (NULL == *pHead)		//链表为空时
		*pHead = pNewNode;
	else				//链表不为空
	{
		pNewNode->_pNext = *pHead;
		*pHead = pNewNode;
	}
}
// 删除单链表的最后一个节点
void PopBack(PNode* pHead)
{
	assert(NULL != pHead);

	if (NULL == *pHead) //链表为空
		return ;

	if (NULL == (*pHead)->_pNext) //链表只有一个节点
	{
		free(*pHead); //删除节点
		*pHead = NULL; //链表为空
	}
	else		//链表节点大于等于2
	{
		PNode pDelNode = *pHead;  //倒数第二个节点指针
	
		while (NULL != pDelNode->_pNext->_pNext) //指向倒数第二个节点
			pDelNode = pDelNode->_pNext;

		free(pDelNode->_pNext);	//删除最后一个节点
		pDelNode->_pNext = NULL;  //倒数第二个节点指向空。
	}
}
// 删除单链表的第一个结点
void PopFront(PNode* pHead)
{
	assert(NULL != pHead);

	if (NULL == *pHead)
		return ;
	else
	{
		PNode pFirstNode = *pHead;

		*pHead = (*pHead)->_pNext;
		free(pFirstNode);
		pFirstNode = NULL;
	}
}

// 在单链表pos位置后插入值为data的结点
void Insert(PNode pos, DataType data)
{
	PNode pNewNode = NULL;

	assert(NULL != pos);
	
	if (!(pNewNode = BuyNode(data)))
		return ;

	pNewNode->_pNext = pos->_pNext;
	pos->_pNext = pNewNode;
}

// 在单链表中删除位置为pos的结点
void Erase(PNode* pHead, PNode pos)
{
	PNode pPreNode = NULL;
	assert(NULL != pHead);  //看看是该用if(pos == NULL)好,还是assert好。
	assert(NULL != pos);

	pPreNode = *pHead;	//pPreNode指向pos前一节点

	if (NULL == *pHead)		//当是空链表时
		return ;

	if (pos == *pHead)	//pos为第一个节点时
		PopFront(pHead);
	else	//pos为别的位置,并且链表不为空
	{	//考虑pos不为链表内容情况
		while (pPreNode && pPreNode->_pNext != pos)	//pCurNode指向不为空且pCurNode->_pNext不等于pos
			pPreNode = pPreNode->_pNext;	//pCurNode指向下一节点

		if (NULL != pPreNode)	//pCurNode下一节点是pos
		{
			pPreNode->_pNext = pos->_pNext;
			free(pos);
			pos = NULL;
		}
	}
}

// 移除单链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data)
{
	PNode pDelNode = NULL;

	assert(NULL != pHead);

	if (pDelNode = Find(*pHead, data))
		Erase(pHead, pDelNode);
}

// 移除单链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data)
{
	PNode pDelNode = NULL;

	assert(NULL != pHead);

	pDelNode = *pHead;

	if (NULL == *pHead)		//链表为空
		return ;

	if (NULL == (*pHead)->_pNext) //链表只有一个节点
	{
		if ((*pHead)->_data == data)
			PopFront(pHead);
	}
	else
	{	//思路:将本该删除的节点pDelNode替换为它的下一节点pTemp,然后释放pTemp。
		while (pDelNode->_pNext)
			if (pDelNode->_data == data)
			{
				PNode pTemp = pDelNode->_pNext;

				pDelNode->_data = pTemp->_data;
				pDelNode->_pNext = pTemp->_pNext;

				free(pTemp);
				pTemp = NULL;
			}
			else
				pDelNode = pDelNode->_pNext;
	}
}

//销毁链表
void DestroyList(PNode *pHead)
{
	PNode pCurNode = NULL;

	assert(NULL == pHead);

	while (NULL != *pHead)
	{
		PNode pTemp = *pHead;
		*pHead = (*pHead)->_pNext;
		free(pTemp);
		pTemp = NULL;
	}
}

///
// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(PNode pHead, DataType data)
{
	assert(NULL != pHead);

	while (pHead)
		if (pHead->_data == data)
			break;
		else
			pHead = pHead->_pNext;

	return pHead;
}


// 获取单链表总结点的总个数
size_t Size(PNode pHead)
{
	size_t n = 0;
	
	while (pHead) //当pHead不为空时
	{
		++n;
		pHead = pHead->_pNext;
	}

	return n;
}

// 判断结点是否为空
int Empty(PNode pHead)
{
	if (pHead)	//pHead不是空链表
		return 1;
	return 0;
}

// 返回单链表的最后一个结点的位置
PNode Back(PNode pHead)
{
	if (NULL != pHead)  //pHead不是空链表
		while (pHead->_pNext)
			pHead = pHead->_pNext;

	return pHead;
}

// 返回单链表的第一个结点的位置
PNode Front(PNode pHead)
{
	return pHead;
}

// 正向打印单链表
void PrintList(PNode pHead)
{
	PNode pCurNode = NULL;

	assert(NULL != pHead);
		
	pCurNode = pHead;

	while (pCurNode)
	{
		printf("%d->", pCurNode->_data);
		pCurNode = pCurNode->_pNext;
	}

	printf("<null>\n");
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值