单链表面试题

1、List.h

#define _CRT_SECURE_NO_WARNINGS 1
#define __CONTACT_H__
#ifdef __CONTACT_H__

typedef int DataType;

typedef struct  Node
{
	DataType data;
	struct Node* pNext;
	int Length;
}Node, *pNode;

void InitSeqList(pNode *pHead);//初始化
void Pushback(pNode *pHead, DataType data);//尾插法
pNode BuyBode(DataType data);//创建第一个新节点
void popback(pNode *pHead);//尾删法
void pushfront(pNode *pHead, DataType data);//头插法
void popfront(pNode *pHead);//头删法
void insert(pNode pos, DataType data);//随机位置插入元素
void Erase(pNode *pHead, pNode pos);//删除任意位置的元素
pNode Find(pNode pHead, DataType data);//查找
void Remove(pNode *pHead, DataType data);//删除某个元素
void RemoveAll(pNode *pHead, DataType data);//删除所有相同的元素
int Empty(pNode pHead);//判空
void Clear(pNode *pHead);//清除
void Destroy(pNode *pHead);//销毁
int size(pNode pHead);//大小
void Bubblesort(PNode *pHead);//冒泡排序
void Selectsort(PNode *pHead);//选择排序
int BinarySearch(PNode *pHead,DataType data);//折半查找
void PrintSelectsort(pNode *pHead);//打印
///
void ReversePrintList(pNode pHead);
void DeleteNotailNode(pNode pos);
//void DeleteNotHeadNode(PNode pos);
void InsertNotHeadNode(pNode pos, DataType data);// 在无头单链表的一个非头节点前插入一个节点
//
pNode UniteList(pNode *pHead1, pNode *pHead2);  //合并两个有序链表。
//PNode FindMidNode(PNode pHead);  //寻找链表中间那个节点。
pNode FindLastKNode(pNode pHead, int k);  //寻找倒数第k个节点。
//PNode ShowTailNode(PNode pHead);  //露出尾部指针。
void JosephCircle(pNode pHead, int M);  //单链表实现约瑟夫环(JosephCircle) 
int IsCross(pNode pHead1, pNode pHead2); //判断两个链表是否相交,若相交,求交点。(假设链表不带环) 
pNode GetCrossNode(pNode pHead1, pNode pHead2);//判断两个链表是否相交,若相交,求交点。(假设链表不带环) 
pNode HasCircle(pNode pHead);// 判断单链表是否带环?返回快慢指针相遇的节点。为啥返回相遇的节点。
int GetCircleLen(pNode pMeetNode); //求环的长度。 参数是快慢指针相遇的节点。
pNode GetEnterNode(pNode pHead, pNode pMeetNode);//进环节点位置, 参数是快慢指针相遇的节点。

#endif

2、List.cpp

#include"List.hpp"
#include<iostream>
#include<assert.h>
using namespace std;

void InitSeqList(pNode *pHead)//链表初始化
{
	assert(pHead);
	*pHead = NULL;
}

int Empty(pNode pHead)//判段是否为空表
{
	assert(pHead);
	if (pHead)
		return 1;
	else
		return 0;
}
int Size(pNode pHead)//链表有多少个节点
{
	assert(pHead);
	pNode pCurNode = pHead;
	int count = 0;
	while (pCurNode)
	{
		count++;
		pCurNode = pCurNode->pNext;
	}
	return count;
}
pNode BuyBode(DataType data)//创建一个新节点
{
	pNode pTemp = (pNode) malloc(sizeof(Node));
	if (pTemp)
	{
		pTemp->data = data;
		pTemp->pNext = NULL;
		return pTemp;
	}
	else
	{
		cout << "开辟内存失败!" << endl;
		return NULL;
	}
}

void Pushback(pNode *pHead, DataType data)//尾插法
{
	assert(pHead);
	pNode pTailNode = *pHead;
	if (*pHead == NULL)
	{
		*pHead = BuyBode(data);
	}
	else
	{
		while (pTailNode->pNext)
		{
			pTailNode = pTailNode->pNext;
		}
		pTailNode->pNext = BuyBode(data);
	}
}
void popback(pNode *pHead)//尾删法
{
	assert(pHead);
	pNode pCurNode = *pHead;
	pNode pReNode = NULL;
	if (*pHead == NULL)//链表为空表
	{
		cout << "链表为空表!" << endl;
		return;
	}
	else if (pCurNode->pNext == NULL)//只有一个节点
	{
		free(pCurNode);
		*pHead = NULL;
	}
	else//有多个节点
	{
		while (pCurNode->pNext)
		{
			pReNode = pCurNode;
			pCurNode = pCurNode->pNext;
		}
		free(pCurNode);
		pReNode->pNext = NULL;
	}
}

void pushfront(pNode *pHead, DataType data)//头插法
{
	pNode pCurNode = NULL;
	assert(pHead);
	pCurNode = BuyBode(data);
	pCurNode->pNext = *pHead;
	*pHead = pCurNode;
}

void popfront(pNode *pHead)//头删法
{
	pNode pCurNode = *pHead;
	assert(pHead);
	if (NULL == *pHead)//链表为空
	{
		cout << "链表为空,删除失败!" << endl;
		return;
	}
	else//链表只有一个节点和链表有多个节点处理方式一样。
	{
		pNode pReNode = pCurNode->pNext;
		*pHead = pReNode;
		free(pCurNode);
	}
}

pNode Find(pNode pHead, DataType data)
{
	pNode pCur = NULL;
	assert(pHead);
	pCur = pHead;
	while (pCur)
	{
		if (pCur->data == data)
			return pCur;
		pCur = pCur->pNext;
	}
	return NULL;
}
void Insert(pNode pHead,pNode pos, DataType data)//随机位置插入元素
{
	assert(pHead);
	pNode pTemp = Find(pHead, pos->data);//寻找插入位置,并返回这个位置。
	pNode pTialNode = BuyBode(data);//插入节点。
	if (pTemp)//扎到插入位置
	{
		pTialNode->pNext = pTemp->pNext;
		pTemp->pNext = pTialNode;
	}
	else
	{
		cout << "没找到插入位置,插入失败!" << endl;
		return;
	}
}

void insert(pNode pos, DataType data)//随机位置插入元素
{
	pNode pTialNode = BuyBode(data);//插入节点。
	if (pos == NULL)
	{
		cout << "该节点不在链表中,插入失败!" << endl;
		return;
	}
	pTialNode->pNext = pos->pNext;
	pos->pNext = pTialNode;
}

void Erase(pNode *pHead, pNode pos)//删除任意位置的元素
{
	pNode pCurNode = NULL;
	assert(pHead);
	assert(pos);
	if (*pHead == NULL)
	{
		cout << "链表为空,删除失败!" << endl;
		return;
	}
	else if (*pHead == pos)
	{
		free(*pHead);
		*pHead = NULL;
	}
	else
	{
		pCurNode = *pHead;
		while (pCurNode->pNext != pos)
		{
			pCurNode = pCurNode->pNext;
		}
		if (pCurNode != NULL)
		{
			pCurNode->pNext = pos->pNext;
			free(pos);
		}
	}

}
void pRintList(pNode pHead)//打印单链表
{
	pNode pCur = NULL;
	if (NULL == pHead)
	{
		cout << "链表为空,不打印!" << endl;
	}
	pCur = pHead;
	while (pCur)
	{
		cout << pCur->data << "->";
		pCur = pCur->pNext;
	}
	cout << "NULL" << endl;
}
void Funtest1()
{
	pNode pHead1;
	InitSeqList(&pHead1);
	//尾插
	Pushback(&pHead1, 1);
	Pushback(&pHead1, 2); 
	Pushback(&pHead1, 3); 
	cout << "尾插成功!" << endl;
	pRintList(pHead1);
	//尾删
	popback(&pHead1);
	cout << "尾删成功!" << endl;
	pRintList(pHead1);
	//头插
	pushfront(&pHead1, 0);
	pushfront(&pHead1, 1);
	pushfront(&pHead1, 2);
	cout << "头插成功!" << endl;
	pRintList(pHead1);
	//头删
	popfront(&pHead1);
	cout << "头删成功!" << endl;
	pRintList(pHead1);
	//任意位置插入
	//第一种方法
	Insert(pHead1, pHead1->pNext, 9);
	pRintList(pHead1);
	//第二种方法
	insert(pHead1->pNext,4);
	cout << "任意位置插入成功!" << endl;
	pRintList(pHead1);
	//任意位置删除
	Erase(&pHead1,pHead1->pNext);
	cout << "任意位置删除成功!" << endl;
	pRintList(pHead1);
	//查找某一个值得位置
	pNode pTemp = Find(pHead1, 4);
	cout << pTemp->data << endl;
}
void ReversePrintList(pNode pHead)//递归逆序打印单链表
{
	if (pHead == NULL)
	{
		cout << "原链表为空,无法逆序!" << endl;
		return;
	}
	else
	{
		if (pHead->pNext)
			ReversePrintList(pHead->pNext);
		cout << pHead->data<<"->";
	}
}
pNode ReverseList(pNode pHead)//头插链表逆序
{
	pNode pCurNode = pHead;
	pNode pTialNode = pHead;
	pNode pNewNode = NULL;
	if (pHead == NULL && pHead->pNext == NULL)
	{
		return pHead;
	}
	else
	{
		while (pTialNode)
		{
			pTialNode = pCurNode->pNext;
			pCurNode->pNext = pNewNode;
			pNewNode = pCurNode;
			pCurNode = pTialNode;
		}
		return pNewNode;
	}
	return NULL;
}
void DeleteNotTailNode(pNode pos)//删除一个无头单链表的非尾节点(不能遍历链表) 这个问题的解决方案是删除pos后面那个节点。
{
	pNode pCurNode = NULL;
	//assert(pos);
	pCurNode = pos->pNext;//pCurNode指向pos后面的节点
	pos->data = pCurNode->data;//pCurNode所指节点的值赋给pos节点
	pos->pNext = pCurNode->pNext;//pos节点链接pCurNode的下一个节点
	free(pCurNode);//删除要删除的节点
}
void InsertNotHeadNode(pNode pos, DataType data) //在无头单链表的一个非头节点前插入一个节点
{
	assert(pos);
	pNode pCurNode = NULL;
	pCurNode = BuyBode(data);
	if (pCurNode == NULL)
	{
		return;
	}
	else
	{
		pCurNode->pNext = pos->pNext;
		pos->pNext = pCurNode;
		pCurNode->data = pos->data;
		pos->data = data;
	}
}
void RemoveAll(pNode *pHead, DataType data)//删除某个元素
{
	pNode pCurNode = NULL;
	pNode pPreNode = NULL;
	pNode pTemp = NULL;
	assert(pHead);
	if (*pHead == NULL)
	{
		cout << "链表为空,删除失败!" << endl;
		return;
	}
	else
	{
		pCurNode = *pHead;
		pPreNode = *pHead;
		while (pCurNode->pNext)
		{
			if (pCurNode->data == data)
			{
				if (pCurNode == *pHead)//如果要删除的节点刚好是头节点,删除头节点
				{
					pTemp = pCurNode;
					*pHead = pCurNode->pNext;
					pCurNode = pCurNode->pNext;
					free(pTemp);
				}
				else//要删除的不是头节点
				{
					pTemp = pCurNode;
					pPreNode->pNext = pCurNode->pNext;
					pCurNode = pCurNode->pNext;
					free(pTemp);
				}
			}
			pPreNode = pCurNode;
			pCurNode = pCurNode->pNext;
		}
		if (pCurNode->data == data)
		{
			free(pCurNode);
			pPreNode->pNext = NULL;
		}
	}	
}
void Clear(pNode *pHead)//清除和销毁一样
{
	assert(pHead);
	pNode pCurNode = *pHead;
	if (*pHead == NULL)
	{
		return;
	}
	else
	{
		while (pCurNode)
		{
			pNode pTemp = pCurNode;
			pCurNode = pCurNode->pNext;
			free(pTemp);
		}
		*pHead = NULL;
	}
}
void Funtest2()
{
	pNode pHead2;
	InitSeqList(&pHead2);
	Pushback(&pHead2, 2);
	Pushback(&pHead2, 1);
	Pushback(&pHead2, 2);
	Pushback(&pHead2, 3);
	Pushback(&pHead2, 2);

	cout << "尾插成功!" << endl;
	pRintList(pHead2);
	//递归逆序打印单链表
	//cout << "递归逆序打印:";
	//ReversePrintList(pHead2);
	//cout << "NULL" << endl;
	//头插逆序打印单链表
	/*cout << "头插逆序打印:";
	pNode pNewNode = ReverseList(pHead2);
	while (pNewNode)
	{
		cout << pNewNode->data<<"->";
		pNewNode = pNewNode->pNext;
	}
	cout << "NULL" << endl;*/

	//删除一个无头单链表的非尾节点
	/*cout << "删除无头单链表的非尾节点:";
	DeleteNotTailNode(pHead2->pNext);
	pRintList(pHead2);*/

	//删除所有元素值一样的节点
	//RemoveAll(&pHead2, 2);
	//pRintList(pHead2);
	//链表大小
	//cout << Size(pHead2) << endl;
	//清除链表
	//Clear(&pHead2);
	//pRintList(pHead2);
	//在无头单链表的一个非头节点前插入一个节点
	InsertNotHeadNode(pHead2->pNext, 0);
	pRintList(pHead2);
}
pNode MergeList(pNode pHead1, pNode pHead2) //合并两个有序链表。
{
	pNode pNewNode = NULL;
	if (pHead1 == NULL)
		return pHead2;
	else if (pHead2 == NULL)
		return pHead1;

	if (pHead1->data < pHead2->data)
	{
		pNewNode = pHead1;
		pNewNode->pNext = MergeList(pHead1->pNext, pHead2);
	}
	else
	{
		pNewNode = pHead2;
		pNewNode->pNext = MergeList(pHead1, pHead2->pNext);
	}
	return pNewNode;
}

void Funtest3()
{
	pNode pHead3;
	InitSeqList(&pHead3);
	Pushback(&pHead3, 1);
	Pushback(&pHead3, 3);
	Pushback(&pHead3, 5);

	cout << "尾插成功!" << endl;
	pRintList(pHead3);

	pNode pHead4;
	InitSeqList(&pHead4);
	Pushback(&pHead4, 2);
	Pushback(&pHead4, 4);
	Pushback(&pHead4, 6);

	cout << "尾插成功!" << endl;
	pRintList(pHead4);
	//递归实现合并两个有序单链表
	pNode pNewNode = MergeList(pHead3, pHead4);
	while (pNewNode)
	{
		cout << pNewNode->data << "->";
		pNewNode = pNewNode->pNext;
	}
	cout << "NULL" << endl;
}
pNode FindLastKNode(pNode pHead, int k)//寻找倒数第k个节点。
{
	if (pHead == NULL || k==0)
		return NULL;

	pNode pFastNode = pHead;
	pNode pSlowNode = NULL;
	for (int idx = 0; idx < k - 1; ++idx)
	{
		if (pFastNode->pNext != NULL)
			pFastNode = pFastNode->pNext;
		else
			return NULL;
	}
	pSlowNode = pHead;
	while (pFastNode->pNext)
	{
		pFastNode = pFastNode->pNext;
		pSlowNode = pSlowNode->pNext;
	}
	return pSlowNode;
}
void JosephCircle(pNode pHead, int M)  //单链表实现约瑟夫环(JosephCircle) 
{
	int count = 0;
	pNode pos = pHead;
	pNode pTemp = NULL;
	assert(pHead);
	if (pHead == NULL || M < 0)
	{
		cout << "链表为空,或者出环人数无效!" << endl;
		return;
	}
	while (pos->pNext)//单链表连成环
	{
		pos = pos->pNext;
	}
	pos->pNext = pHead;
	while (pos != pos->pNext)//直到找到最后一个节点
	{
		count = M;
		while (--count)//找到要被删除的节点,如果此处是count--那么就是每3位删除一个节点
		{
			pos = pos->pNext;
		}
		pTemp = pos->pNext;//保留要删除的节点
		pos->pNext = pTemp->pNext;//被删除的节点的前一个节点指向删除节点的后一个节点
		cout << "要删除的节点的是:" << pTemp->data << endl;
		free(pTemp);
		pTemp = NULL;
	}
	free(pos);
	pos = NULL;
}
void FunTest4()
{
	pNode pHead4;
	InitSeqList(&pHead4);
	/*for (int idx = 1; idx <= 10; idx++)
	{
		Pushback(&pHead4, idx);
	}
	pRintList(pHead4);*/
	Pushback(&pHead4, 1);
	//寻找倒数第K个节点
	pNode pFindLastNode = FindLastKNode(pHead4, 1);
	if (pFindLastNode)
		cout << pFindLastNode->data << endl;

	//单链表实现也约瑟夫环问题
	//JosephCircle(pHead4, 2);
}
int IsCross(pNode pHead1, pNode pHead2) //判断两个链表是否相交(假设链表不带环)
{
	pNode pCurNode = pHead1;
	pNode pTurNode = pHead2;
	if (pHead1 == NULL || pHead2 == NULL)
		return 0;
	while (pCurNode->pNext)
		pCurNode = pCurNode->pNext;
	while (pTurNode->pNext)
		pTurNode = pTurNode->pNext;
	if (pCurNode == pTurNode)//判断两个链表相交,就是判断尾节点是否一样。
		return 1;
	return 0;
}
pNode GetCrossNode(pNode pHead1, pNode pHead2)//判断两个链表是否相交,若相交,求交点。(假设链表不带环) 
{
	int count = 0;
	if (pHead1 == NULL || pHead2 == NULL)
		return NULL;
	pNode pCurNode = pHead1;
	pNode pTurNode = pHead2;
	if (!IsCross(pHead1, pHead2))//两个链表不相交
		return NULL;
	//两个链表有交点
	count = Size(pHead1) - Size(pHead2);
	if (count > 0)
	{
		while (count--)
			pCurNode = pCurNode->pNext;
	}
	if (count < 0)
	{
		count = -count;
		while (count--)
			pTurNode = pTurNode->pNext;
	}
	//两个链表到交点的距离相同
	while (pCurNode != pTurNode)
	{
		pCurNode = pCurNode->pNext;
		pTurNode = pTurNode->pNext;
	}
	return pCurNode;
}
pNode HasCircle(pNode pHead)// 判断单链表是否带环?返回快慢指针相遇的节点。
{
	assert(pHead);
	pNode pFastNode = pHead;
	pNode pSlowNode = pHead;
	while (pFastNode && pFastNode->pNext)
	{
		pFastNode = pFastNode->pNext->pNext;
		pSlowNode = pSlowNode->pNext;
		if (pFastNode == pSlowNode)
			return pSlowNode;
	}
	return NULL;
}
int GetCircleLen(pNode pMeetNode)//求环的长度,参数是快慢指针相遇的节点。
{
	int count = 1;
	assert(pMeetNode);
	pNode pCurNode = pMeetNode;
	while (pCurNode->pNext != pMeetNode)
	{
		count++;
		pCurNode = pCurNode->pNext;
	}
	return count;
}
pNode GetEnterNode(pNode pHead, pNode pMeetNode)//进环节点位置, 参数是快慢指针相遇的节点。
{
	pNode pCurNode = pHead;
	pNode pMeet = pMeetNode;
	if (pHead == NULL || pMeetNode == NULL)
		return NULL;
	while (pCurNode != pMeet)
	{
		pCurNode = pCurNode->pNext;
		pMeet = pMeet->pNext;
	}
	return pCurNode;
}
//复杂链表的复制。
//第一步:复制原始链表的任意节点N并创建新结点N',再把N'链接到N的后面
void CloneNode(ListNode* pHead)
{
	ListNode* pCurNode = pHead;
	while (pCurNode)
	{
		ListNode* pNewNode = new ListNode(0);
		pNewNode->_value = pCurNode->_value;
		pNewNode->Next = pCurNode->Next;
		pNewNode->_random = NULL;
		
		pCurNode->Next = pNewNode;
		pCurNode = pNewNode->Next;
	}
}
//第二步:设置复制出来节点的random,如果原始链表上的节点N的random指向S,则它对应的复制结点N'的random指向S的下一个S'
void ConnectSbioNode(ListNode* pHead)
{
	ListNode* pCurNode = pHead;
	while (pCurNode)
	{
		ListNode* pCloneNode = pCurNode->Next;
		if (pCurNode->_random)
		{
			pCloneNode->_random = pCurNode->_random->Next;
		}
		pCurNode = pCloneNode->Next;
	}
}
//第三步:奇数位上为原始链表,偶数为上为复制的链表
ListNode* ReconnectNode(ListNode* pHead)
{
	if (NULL == pHead)
		return NULL;
	ListNode* pCurNode = pHead;
	ListNode* pTempNode = NULL;
	ListNode* pTempHead = NULL;
	pTempHead = pTempNode = pCurNode->Next;
	pCurNode->Next = pTempNode->Next;
	pCurNode = pCurNode->Next;
	while (pCurNode)
	{
		pTempNode->Next = pCurNode->Next;
		pTempNode = pTempNode->Next;
		pCurNode->Next = pTempNode->Next;
		pCurNode = pCurNode->Next;
	}
	return pTempHead;
}


void FunTest5()
{
	pNode pHead1;
	InitSeqList(&pHead1);
	Pushback(&pHead1, 1);
	Pushback(&pHead1, 2);
	Pushback(&pHead1, 3);
	pRintList(pHead1);
	pNode pHead2;
	InitSeqList(&pHead2);
	pushfront(&pHead2, 6);
	pushfront(&pHead2, 5);
	pushfront(&pHead2, 4);
	pRintList(pHead2);

	//判断两个链表是否相交
	pHead1->pNext = pHead2->pNext->pNext;//两个链表连起来
	//cout << "两个链表是否相交:"<<IsCross(pHead1,pHead2) << endl;

	//找出两个链表相交的节点
	pNode CrossNode = GetCrossNode(pHead1, pHead2);
	if (NULL != CrossNode)
		cout << "两个链表相交的节点是:" << CrossNode->data << endl;
	else
		cout << "链表无交点!" << endl;


	//判断单链表成环
	pNode pHead3;
	InitSeqList(&pHead3);
	for (int idx = 1; idx <= 10; idx++)
	{
		Pushback(&pHead3, idx);
	}
	pRintList(pHead3);
	pNode pCur = pHead3;
	while (pCur->pNext)//单链表连成环。
		pCur = pCur->pNext;
	pCur->pNext = pHead3->pNext;
	pNode HasNode =  HasCircle(pHead3);
	if (HasNode)
		cout << "链表带环,相遇点是:" << HasNode->data << endl;
	else
		cout << "链表不带环!" << endl;

	//环的长度
	int Count = GetCircleLen(HasNode);
	cout << Count << endl;

	//入环的节点
	pNode EnterNode = GetEnterNode(pHead3, HasNode);
	cout << EnterNode->data << endl;
}
int main()
{
	//Funtest1(); 
	//Funtest2();
	//Funtest3();
	//FunTest4();
	FunTest5();
	system("pause");
	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值