C语言实现单链表

实现单链表的以下操作:

list.h:

#ifndef __LIST_H__
#define __LIST_H__

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

typedef int DataType;

typedef struct Node
{
	DataType _data;
	struct Node *_pNext;
}Node,*pNode;


// 初始化单链表
void InitList(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);

// 判断结点是否为空
DataType Empty(pNode pHead);

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

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

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

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


//单链表实现约瑟夫环
void JosiphCircle(pNode *pHead,size_t M);


///面试题//
//12.24实现无头单链表的以下操作:
// 逆序打印单链表
void PrintFromTail2Head(pNode pHead);

// 删除单链表的非尾结点(不能遍历单链表)
void DeleteNotTailNode(pNode pos);

// 使用递归实现从未到头打印单链表
void PrintFromTail2Head(pNode pHead);

// 删除单链表的非尾结点
void DeleteNotTailNode(pNode pos);

// 在单链表非头结点前插入结点data
void InsertNotHeadNode(pNode pos, DataType data);

// 查找单链表的中间结点,要求只便利一次链表
pNode FindMidNode(pNode pHead);

// 查找单链表的倒数第K个结点,要求只遍历一次链表
pNode FindLastKNode(pNode pHead, size_t k);

// 使用冒泡排序对单链表进行排序
void BubbleSort(pNode pHead);

// 判断两个单链表是否相交(链表不带环)
int IsListCross(pNode L1, pNode L2);

// 若不带环的单链表相交,求交点
pNode GetCrossNode(pNode PL1, pNode PL2);



//12.25实现链表的以下操作:
// 实现单链表的逆置:使用三个指针
pNode ReverseList(pNode pHead);

// 实现单链表的逆置:使用头插法
void ReverseList_P(pNode* pHead);

// 合并两个已序单链表,合并后依然有序
pNode MergeList(pNode pHead1, pNode pHead2);

// 判断链表是否带环,若带环给出相遇点
pNode HasCircle(pNode pHead);

// 求环的长度
size_t  GetCircleLen(pNode pMeetNode);

// 求环的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode);

// 判断链表是否相交,注意:链表可能带环
int IsCrossWithCircle(pNode pHead1, pNode pHead2);


#endif //__LIST_H__

List.c:

#include "List.h"

void InitList(pNode *pHead)
{
	assert(pHead);
	*pHead = NULL;
}

// 在单链表的尾部插入一个节点
void PushBack(pNode* pHead, DataType data)
{
	assert(pHead);
	if(*pHead == NULL)
	{
		*pHead = BuyNode(data);
	}
	else
	{
		Node *pTailNode = *pHead;
		while(pTailNode->_pNext)
		{
			pTailNode = pTailNode->_pNext;
		}
		pTailNode->_pNext = BuyNode(data);
	}
}

 //构建一个新节点
static Node* BuyNode(DataType data)
{
	Node *pNewNode = (Node *)malloc(sizeof(Node));
	if(pNewNode != NULL)
	{
		pNewNode->_data = data;
		pNewNode->_pNext = NULL;
	}
	return pNewNode;
}

 //删除单链表的最后一个节点
void PopBack(pNode* pHead)
{
	assert(pHead);
	if(pHead == NULL)
	{
		return;
	}
	else if((*pHead)->_pNext == NULL)
	{
		free(*pHead);
		*pHead = NULL;
	}
	else
	{
		Node *pPreNode = *pHead;
		Node *pTailNode = *pHead;
		while(pTailNode->_pNext)
		{
			pPreNode = pTailNode;
			pTailNode = pTailNode->_pNext;
		}
		free(pTailNode);
		pPreNode->_pNext = NULL;
	}
}

// 正向打印单链表
void PrintList(pNode pHead)
{
	Node *pCurNode = pHead;
	while(pCurNode)
	{
		printf("%d->",pCurNode->_data);
		pCurNode = pCurNode->_pNext;
	}
	printf("NULL\n");
}

// 在单链表的头部插入值为data的结点
void PushFront(pNode* pHead, DataType data)
{
	assert(pHead);
	if(*pHead == NULL)
	{
		*pHead = BuyNode(data);
	}
	else
	{
		pNode pNewNode = BuyNode(data);
		pNewNode->_pNext = *pHead;
		*pHead = pNewNode;
	}
}

// 删除单链表的第一个结点
void PopFront(pNode* pHead)
{
	assert(pHead);
	if(*pHead == NULL)
	{
		return;
	}
	else if((*pHead)->_pNext == NULL)
	{
		free(*pHead);
		*pHead = NULL;
	}
	else
	{
		Node *pDelNode = *pHead;
		*pHead = (*pHead)->_pNext;
		free(pDelNode);
	}
}

// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(pNode pHead, DataType data)
{
	Node *pCurNode = pHead;
	while(pCurNode)
	{
		if(pCurNode->_data == data)
		{
		    return pCurNode;
		}
		pCurNode = pCurNode->_pNext;
	}
	return NULL;
}


 //在单链表pos位置后插入值为data的结点
void Insert(pNode pos, DataType data)
{
	Node *pNewNode = NULL;
	if(pos == NULL)
	{
		return;
	}
	pNewNode = BuyNode(data);
	if(pNewNode == NULL)
	{
		return;
	}
	pNewNode->_pNext = pos->_pNext;
	pos->_pNext = pNewNode;
}

// 在单链表非头结点前插入结点data
void InsertNotHeadNode(pNode pos, DataType data)
{
	pNode pNewNode = BuyNode(pos->_data);
	if(pNewNode == NULL)
	{
		return;
	}
	pNewNode->_pNext = pos->_pNext;
	pos->_pNext = pNewNode;
	pos->_data = data;
}

 //在单链表中删除位置为pos的结点
void Erase(pNode* pHead, pNode pos)
{
	assert(pHead);
	if(NULL == *pHead || NULL == pos)
	{
		return;
	}
	else if(*pHead == pos)
	{
		PopFront(pHead);
	}
	else
	{
		Node *pPreNode = *pHead;
		while(pPreNode->_pNext != pos)
		{
			pPreNode = pPreNode->_pNext;
		}
		pPreNode->_pNext = pos->_pNext;
		free(pos);
	}
}

 //移除单链表中第一个值为data的结点(非尾结点)
void Remove(pNode* pHead, DataType data)
{
	pNode pPreNode = Find(*pHead,data);
	if(pPreNode == NULL)
	{
		return;
	}
	else
	{
		pNode pDelNode = pPreNode->_pNext; 
		pPreNode->_data = pPreNode->_pNext->_data;
		pPreNode->_pNext = pPreNode->_pNext->_pNext;
		free(pDelNode);
	}
}

 //移除单链表中第一个值为data的结点
void Remove(pNode* pHead, DataType data)
{
	pNode pPreNode = Find(*pHead,data);
	assert(pHead);
	if(pPreNode == NULL)
	{
		return;
	}
	else
	{
		Erase(pHead,pPreNode);
	}
}


//移除单链表中所有值为data的结点(递归)
void RemoveAll(pNode* pHead, DataType data)
{
	pNode pDelNode = NULL;
	Remove(pHead,data);
	pDelNode = Find(*pHead,data);
	if(pDelNode == NULL)
	{
		return;
	}
	else
	{
		RemoveAll(pHead,data);
	}
}

//移除单链表中所有值为data的结点
void RemoveAll(pNode* pHead, DataType data)
{
	pNode pPre = *pHead;
	pNode pCur = *pHead;
	pCur = pPre->_pNext;
	if(*pHead == NULL)
	{
		return;
	}
	while(pCur)
	{
		if(pCur->_data == data)
		{
			pPre->_pNext = pCur->_pNext;
			free(pCur);
			pCur = pPre->_pNext;
		}
		else
		{
			pPre = pCur;
			pCur = pCur->_pNext;
		}
	}
	if((*pHead)->_data == data)
	{
		pNode pTemp = *pHead;
		*pHead = pTemp->_pNext;
		free(pTemp);
	}
}
		
 //移除单链表中所有值为data的结点(非尾结点)
void RemoveAll(pNode* pHead, DataType data)
{
	pNode pPreNode = *pHead;
	while(pPreNode)
	{
	    pPreNode = Find(pPreNode,data);
		if(pPreNode == NULL)
	    {
		    return;
	    }
	    else
	    {
		    pNode pDelNode = pPreNode->_pNext; 
		    pPreNode->_data = pPreNode->_pNext->_data;
		    pPreNode->_pNext = pPreNode->_pNext->_pNext;
		    free(pDelNode);
		}
	}
}


 //删除单链表的非尾结点(不能遍历单链表)
void DeleteNotTailNode(pNode pos)
{
	assert(pos);
	if(pos->_pNext == NULL)
	{
		return;
	}
	else
	{
		pNode pDelNode = pos->_pNext;
		pos->_data = pDelNode->_data;
		pos->_pNext = pDelNode->_pNext;
		free(pDelNode);
	}
}

 //逆序打印单链表
void PrintFromTail2Head(pNode pHead)
{
	if(pHead == NULL)
	{
		return;
	}
	else
	{
		PrintFromTail2Head(pHead->_pNext);
		printf("%d->",pHead->_data);
	}
}

 //获取单链表总结点的总个数
size_t Size(pNode pHead)
{
	int count = 0;
	pNode pPreNode = pHead;
	while(pPreNode)
	{
		count++;
		pPreNode = pPreNode->_pNext;
	}
	return count;
}

// 判断结点是否为空
DataType Empty(pNode pHead)
{
	if(pHead == NULL)
	{
		return 0;
	}
	else
		return 1;
}

 //返回单链表的最后一个结点的位置
pNode Back(pNode pHead)
{
	pNode pTailNode = pHead;
	while(pTailNode->_pNext)
	{
		pTailNode = pTailNode->_pNext;
	}
	return pTailNode;
}

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

//单链表实现约瑟夫环
void JosiphCircle(pNode *pHead,size_t M)
{
	int m = M;
	pNode pCurNode = NULL;
	assert(pHead);
	if(*pHead == NULL)
	{
		return;
	}
	pCurNode = *pHead;
	while(pCurNode != pCurNode->_pNext)
	{
		pNode pDelNode = NULL;
		m = M;
		while(--m)
		{
			pCurNode = pCurNode->_pNext;
		}
		pDelNode = pCurNode->_pNext;
		pCurNode->_data = pDelNode->_data;
		pCurNode->_pNext = pDelNode->_pNext;
		free(pDelNode);
	}
	*pHead = pCurNode;
	(*pHead)->_pNext = NULL;
}


// 查找单链表的中间结点,要求只遍历一次链表
pNode FindMidNode(pNode pHead)
{
	pNode pFast = NULL;
	pNode pSlow = NULL;
	if(pHead == NULL)
	{
		return NULL;
	}
	pFast = pHead;
	pSlow = pHead;
	while(pFast && pFast->_pNext)
	{
		pSlow = pSlow->_pNext;
		pFast = pFast->_pNext->_pNext;
	}
	return pSlow;
}

// 查找单链表的倒数第K个结点,要求只遍历一次链表
pNode FindLastKNode(pNode pHead, size_t k)
{
	pNode pFast = NULL;
	pNode pSlow = NULL;
	if(pHead == NULL || k == 0)
	{
		return NULL;
	}
	pFast = pHead;
	pSlow = pHead;
	while(k--)
	{
		pFast = pFast->_pNext;
	}
	while(pFast)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}
	return pSlow;
}

// 使用冒泡排序对单链表进行排序
void BubbleSort(pNode pHead)
{
	pNode pTailNode = NULL;
	pNode pPre = NULL;
	pNode pCur = NULL;
	int flag = 0;
	if(pHead == NULL || pHead->_pNext == NULL)
	{
		return;
	}
	pPre = pHead;
	pCur = pHead;
	while(pHead != pTailNode)
	{
		pPre = pHead;
		pCur = pPre->_pNext;
		while(pCur != pTailNode)
		{
			if(pPre->_data > pCur->_data)
			{
				DataType temp = 0;
				flag = 1;
				temp = pPre->_data;
				pPre->_data = pCur->_data;
				pCur->_data = temp;
			}
			pPre = pCur;
			pCur = pCur->_pNext;
		}
		if(flag == 0)
		{
			return;
		}
		pTailNode = pPre;
	}
}

// 判断两个单链表是否相交(链表不带环)
int IsListCross(pNode L1, pNode L2)
{
	pNode pCurNode1 = NULL;
	pNode pCurNode2 = NULL;
	if(L1 == NULL || L2 == NULL)
	{
		return 0;
	}
	pCurNode1 = L1;
	pCurNode2 = L2;
	while(pCurNode1->_pNext)
	{
		pCurNode1 = pCurNode1->_pNext;
	}
	while(pCurNode2->_pNext)
	{
		pCurNode2 = pCurNode2->_pNext;
	}
	if(pCurNode1 == pCurNode2)//两不带环的单链表相交尾节点必相同
	{
		return 1;
	}
	else
		return 0;
}

// 若不带环的单链表相交,求交点
pNode GetCrossNode(pNode pL1, pNode pL2)
{
	size_t s1 = 0;
	size_t s2 = 0;
	int gap = 0;
	if(IsListCross(pL1,pL2) == 0)
	{
		return NULL;
	}
	s1 = Size(pL1);
	s2 = Size(pL2);
	gap = s1 - s2;
	if(gap < 0)
	{
		gap = -gap;
		while(gap--)
		{
			pL2 = pL2->_pNext;
		}
	}
	else
	{
		while(gap--)
		{
			pL1 = pL1->_pNext;
		}
	}
	while(pL1 != pL2)
	{
		pL1 = pL1->_pNext;
		pL2 = pL2->_pNext;
	}
	return pL1;
}
	

// 实现单链表的逆置:使用三个指针
pNode ReverseList(pNode pHead)
{
	pNode pPreNode = NULL;
	pNode pCurNode = NULL;
	pNode pNextNode = NULL;
	if(pHead == NULL || pHead->_pNext == NULL)
	{
		return NULL;
	}
	pPreNode = pHead;
	pCurNode = pPreNode->_pNext;
	pNextNode = pCurNode->_pNext;
	while(pNextNode)
	{
		pCurNode->_pNext = pPreNode;
		pPreNode = pCurNode;
		pCurNode = pNextNode;
		pNextNode = pNextNode->_pNext;
	}
	pCurNode->_pNext = pPreNode;
	pHead->_pNext = NULL;
	pHead = pCurNode;
	return pHead;
}

// 实现单链表的逆置:使用头插法
void ReverseList_P(pNode* pHead)
{
	pNode pNewHead = NULL;
	pNode pPreNode = NULL;
	pNode pCurNode = NULL;
	if(*pHead == NULL || (*pHead)->_pNext == NULL)
	{
		return;
	}
	pPreNode = *pHead;
	pCurNode = (*pHead)->_pNext;
	while(pCurNode)
	{
		pPreNode->_pNext = pNewHead;
		pNewHead = pPreNode;
		pPreNode = pCurNode;
		pCurNode = pCurNode->_pNext;
	}
	pPreNode->_pNext = pNewHead;
	pNewHead = pPreNode;
	*pHead = pNewHead;
}

// 合并两个已序单链表,合并后依然有序
pNode MergeList(pNode pHead1, pNode pHead2)
{
	pNode pL1 = NULL;
	pNode pL2 = NULL;
	pNode pNewHead = NULL;
	pNode pTailNode = NULL;
	if(pHead1 == NULL)
	{
		return pHead2;
	}
	if(pHead2 == NULL)
	{
		return pHead1;
	}
	pL1 = pHead1;
	pL2 = pHead2;
    if(pL1->_data <= pL2->_data)
	{
		pNewHead = pL1;
		pTailNode = pNewHead;
		pL1 = pL1->_pNext;
	}
	else
	{
		pNewHead = pL2;
		pTailNode = pNewHead;
		pL2 = pL2->_pNext;
	}
	while(pL1 && pL2)
	{
		if(pL1->_data <= pL2->_data)
		{
			pTailNode->_pNext = pL1;
			pL1 = pL1->_pNext;
		}
		else
		{
			pTailNode->_pNext = pL2;
			pL2 = pL2->_pNext;
		}
		pTailNode = pTailNode->_pNext;
	}
	if(pL1 != NULL)
	{
		pTailNode->_pNext = pL1;
	}
	if(pL2 != NULL)
	{
		pTailNode->_pNext = pL2;
	}
	return pNewHead;
}

// 判断链表是否带环,若带环给出相遇点
pNode HasCircle(pNode pHead)
{
	pNode pFast = NULL;
	pNode pSlow = NULL;
	if(pHead == NULL)
	{
		return NULL;
	}
	pFast = pHead;
	pSlow = pHead;
	//环内点都是相遇点
	while(pFast && pFast->_pNext)
	{
		pSlow = pSlow->_pNext;
		pFast = pFast->_pNext->_pNext;
		if(pSlow == pFast)
		{
			return pSlow;
		}
	}
	return NULL;
}

// 求环的长度
size_t  GetCircleLen(pNode pMeetNode)
{
	pNode pCurNode = pMeetNode;
	size_t count = 1;
	while(pCurNode->_pNext != pMeetNode)
	{
		pCurNode = pCurNode->_pNext;
		count++;
	}
	return count;
}

// 求环的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode)
{
	pNode pH = NULL;
	pNode pM = NULL;
	if(pHead == NULL || pMeetNode == NULL)
	{
		return NULL;
	}
	pH = pHead;
	pM = pMeetNode;
	while(pH != pM)
	{
		pH = pH->_pNext;
		pM = pM->_pNext;
	}
	return pH;
}

// 判断链表是否相交,注意:链表可能带环
//(两个链表都带环或都不带环)
int IsCrossWithCircle(pNode pHead1, pNode pHead2)
{
	pNode pMeetNode1 = HasCircle(pHead1);
	pNode pMeetNode2 = HasCircle(pHead2);
	if(pMeetNode1 == NULL && pMeetNode2 == NULL)
	{
		pNode pCurNode1 = pHead1;
		pNode pCurNode2 = pHead2;
		if(pHead1 == NULL || pHead2 == NULL)
		{
			return 0;
		}
		while(pCurNode1->_pNext)
		{
			pCurNode1 = pCurNode1->_pNext;
		}
		while(pCurNode2->_pNext)
		{
			pCurNode2 = pCurNode2->_pNext;
		}
		if(pCurNode1 == pCurNode2)
		{
			return 1;  //不带环相交
		}
	}
	else if(pMeetNode1 != NULL && pMeetNode2 != NULL)
	{
		pNode pCurNode = pMeetNode1;
		while(pCurNode->_pNext != pMeetNode1)
		{
			if(pCurNode == pMeetNode2)
			{
				return 2;  //带环环外相交
			}
			pCurNode = pCurNode->_pNext;
		}
		if(pCurNode == pMeetNode2)
		{
			return 2;  //带环环内相交(环的入口点相交)
		}
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值