面试题之链表篇

        链表是面试重中之重,但题型比较死,考的是细心。这里做一个总结,给出模板实现。如果错误,请不吝指教!

1. 判断链表是否有环
2.求链表中间节点(偶数则返回前一个节点)
3.约瑟夫环问题
4. 链表逆序输出(递归)
5. 链表反转(非递归与递归)
6.两个有序单链表的合并(非递归与递归)
7.判断两个单链表是否相交
8.接题7,若相交求第一个交点
9. 删除链表某个节点
10. 求倒数第K个节点
11. 单链表排序

节点定义:

template<class T>
struct LNode
{
	 T value;
	 LNode *next;
};

1. 判断链表是否有环

template <typename T>
int IsCyclicList(LNode<T> *list)
{
	LNode<T> *pSlow = list;
	LNode<T> *pFast = list;

	while(pFast != NULL && pFast->next != NULL)
	{
		pFast = pFast->next->next;
		pSlow = pSlow->next;

		if (pFast == pSlow)
			return 1;
	}
	return 0;
}

2. 求单链表链表中间节点(偶数则返回前一个节点)

template <typename T>
int GetMidNode(LNode<T> *list)
{
	if (NULL == list)
		return NULL;

	LNode<T> *pAhead = list;
	LNode<T> *pBehind = list;

	while(pAhead->next != NULL)             
	{
		pAhead = pAhead->next;
		if (pAhead->next != NULL)           
		{
			pBehind = pBehind->next;
			pAhead = pAhead->next;
		}
	}
	return pBehind->value;
}

3. 约瑟夫环问题

template <typename T>            
void joseph(LNode<T> *list, int m)
{
	if (NULL == list)
		return;
		
	int count = m;
	LNode<T> *cur = list;

	while(cur->next != cur)
	{
		while ( count > 2)     //默认当前节点报数为1,故此处取2;若当前节点报数为0,则此处取1
		{
			cur = cur->next;
			--count;
		}
		LNode<T> *temp = cur->next;
		cur->next = temp->next;
		cur = cur->next;
		
		delete temp;
		count = m;
	}
	cout << cur->value << endl;
}

4. 单链表逆序输出(递归)

template <typename T>
void PrintFromLastToFirst(LNode<T> *list)
{
	if (NULL == list)
		return ;
	PrintFromLastToFirst(list->next);
	cout << list->value << " ";
}

5. 单链表反转(非递归与递归)
非递归法:

template <typename T>
LNode<T> * ReverseList_NoRecurse(LNode<T> *list)
{
	if (NULL == list)
		return NULL;
	LNode<T> *pHead = list;
	LNode<T> *pCur = pHead->next;
	pHead->next = NULL;

	while (pCur != NULL)
	{
		LNode<T> *temp = pCur->next;
		pCur->next = pHead;
		pHead = pCur;
		pCur = temp;
	}
	return pHead;
}

递归法:

template <typename T>
LNode<T> *DoReverseList(LNode<T> *list, LNode<T> *&pre)
{
	if (NULL == list->next)
	{
		pre = list;
		return list;
	}

	LNode<T> * temp = DoReverseList(list->next, pre);
	pre->next = list;
	pre = list;
	pre->next = NULL;
	return temp;
}

template <typename T>
LNode<T> *ReverseList_Recurse(LNode<T> *list)
{
	if (NULL == list || NULL == list->next )
		return list;

	LNode<T> *pre;

	return DoReverseList(list,pre);
}

6.两个有序单链表的合并(非递归与递归)

非递归法:

template <typename T>
LNode<T> * MergeList_NoRecurse(LNode<T> *list1, LNode<T>  *list2)
{
	if (NULL == list1)
		return list2;
	if (NULL == list2)
		return list1;
	
	LNode<T> node;        //附加头节点,方便处理
	LNode<T> *temp = &node;
	while(list1 != NULL && list2 != NULL)
	{
		if (list1->value < list2->value)
		{
			temp->next = list1;
			list1 = list1->next;
		}
		else
		{
			temp->next = list2;
			list2 = list2->next;
		}

		temp = temp->next;
	}

	if (NULL == list1)
		temp->next = list2;
	if (NULL == list2)
		temp->next = list1;

	return node.next;
}

递归法:

template <typename T>
LNode<T> * MergeList_Recurse(LNode<T> *list1, LNode<T>  *list2)
{
	if (NULL == list1)
		return list2;
	if (NULL == list2)
		return list1;

	LNode<T> *pHead = NULL;

	if (list1->value < list2->value)
	{
		pHead = list1;
		pHead->next = MergeList_Recurse(list1->next, list2);
	}
	else
	{
		pHead = list2;
		pHead->next = MergeList_Recurse(list1, list2->next);
	}
	return pHead;
}

7.判断两个单链表是否相交

template <typename T>
int IsIntersect(LNode<T> *list1, LNode<T> *list2)
{
	if (NULL == list1 || NULL == list2)
		return 0;

	while (list1->next != NULL)
		list1 = list1->next;

	while (list2->next != NULL)
		list2 = list2->next;

	return (list1==list2);
}

8.接题7,若相交求第一个交点

template <typename T>
LNode<T> * GetFirstIntersection(LNode<T> *list1, LNode<T> *list2)
{
	if (NULL == list1 || NULL == list2)
		return NULL;

	LNode<T> *temp1 = list1;
	LNode<T> *temp2 = list2;

	int len1=0, len2=0;

	while (temp1 != NULL)
	{
		len1++;
		temp1 = temp1->next;
	}
	while (temp2 != NULL)
	{
		len2++;
		temp2 = temp2->next;
	}

	if (len1 > len2)
	{
		int count = len1-len2;
		while (count>0)
		{
			list1 = list1->next;
			count--;
		}
	}
	if (len1 < len2)
	{
		int count  = len2-len1;
		while (count>0)
		{
			list2 = list2->next;
			count--;
		}
	}

	while (list1->value != list2->value)
	{
		list1 = list1->next;
		list2 = list2->next;
	}
	
	return list1;
}

9. 删除链表某个节点

template <typename T>
void DeleteNode(LNode<T> * &list, LNode<T> *pToBeDeleted)
{
	if (NULL == list || NULL == pToBeDeleted) 
		return ;

	if (list == pToBeDeleted)  //删除头节点
	{
		list = list->next;
		delete  pToBeDeleted;
		pToBeDeleted = NULL;
	}
	else
	{
		if (NULL == pToBeDeleted->next )  //删除尾节点
		{
			LNode<T> *temp = list;
			while (temp->next != pToBeDeleted)
				temp = temp->next;

			temp->next = NULL;
			delete pToBeDeleted;
			pToBeDeleted = NULL;

		}
		else    //删除中间节点
		{
			LNode<T> *temp = pToBeDeleted->next;
			pToBeDeleted->value = temp->value;
			pToBeDeleted->next = temp->next;
			delete temp;
		}
	}
}

10. 求倒数第K个节点

template <typename T>
LNode<T> * FindKthToEnd(LNode<T> *list, int k)
{
	if (NULL == list || k <= 0)
		return NULL;
	LNode<T> * pAhead = list;
	LNode<T> *pBehind = list;

	for (int i=0; i<k-1; i++)
	{
		if (pAhead->next != NULL)
			pAhead = pAhead->next;
		else
			return NULL;
	}
	while (pAhead->next != NULL)
	{
		pAhead = pAhead->next;
		pBehind = pBehind->next;
	}
	return pBehind;
}

11. 单链表排序

template <typename T>
LNode<T> * BubbleSort(LNode<T> *list)
{
	if (NULL == list || NULL == list->next)
		return NULL;

	LNode<T> *pA = list;
	LNode<T> *pB = list;
	int tmp;
	
	int flag = 1;

	for (; pA != NULL && flag; pA = pA->next)
	{
		flag = 0;
		for (pB = list; pB->next != NULL; pB = pB->next)
		{
			if (pB->value > pB->next->value)
			{
				tmp = pB->value;
				pB->value = pB->next->value;
				pB->next->value = tmp;
				flag = 1;
			}
		}
	}
	return list;
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值