数据结构:单链表相关面试题

单链表基本功能实现:

https://blog.csdn.net/W_J_F_/article/details/80007864

ListNode.h

// 逆序打印单链表 
void PrintSListFromTail(pNode pHead);

// 删除链表的非尾结点,要求:不能遍历链表 
void DeleteListNotTailNode(pNode *pHead, pNode pos);

// 查找链表的中间结点,要求只能遍历一次链表 
pNode FindMiddleNode(pNode pHead);

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

// 删除链表的倒数第K个结点,要求只能遍历一次链表 
pNode DeleteLastKNode(pNode pHead, int K);

// 用单链表实现约瑟夫环 
int JosephCircle(pNode* pHead, const int M);

// 链表的逆置--三个指针 
void ReverseSList(pNode* pHead);

// 链表的逆置--头插法 
pNode ReverseSListOP(pNode pHead);

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

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

// 判断两个单链表是否相交---链表不带环 
int IsSListCross(pNode pHead1, pNode pHead2);

// 求两个单链表相交的交点---链表不带环 
pNode GetCorssNode(pNode pHead1, pNode pHead2);

ListNode.c

// 逆序打印单链表 
void PrintSListFromTail(pNode pHead)
{
	if (NULL == pHead)
	{
		return;
	}
	PrintSListFromTail(pHead->_pnext);
	printf("%d-> ",pHead->_pdata);
}

// 删除链表的非尾结点,要求:不能遍历链表 
void DeleteListNotTailNode(pNode *pHead,pNode pos)
{
	assert(pHead);
	if (NULL == *pHead || NULL == pos)//可能改变头结点指向时传二级指针
	{
		return;
	}
	//要删除节点为头节点和非头结点两种情况
	if (pos == *pHead)
	{
		pNode pDel = *pHead;
		*pHead = (*pHead)->_pnext;
		free(pDel);
	}
	else
	{
		pNode pDel = pos;
		pDel = pDel->_pnext;
		if (pDel->_pnext)
		{
			pos->_pdata = pDel->_pdata;
			pos->_pnext = pDel->_pnext;
			free(pDel);
		}
	}

}

// 查找链表的中间结点,要求只能遍历一次链表 
pNode FindMiddleNode(pNode pHead)
{
	if (NULL == pHead)
	{
		return NULL;
	}
	//偶数个和奇数个节点
	pNode pFas = pHead;
	pNode pLow = pHead;
	pNode pPre = NULL;
	while (pFas && pFas->_pnext)
	{
		pPre = pLow;
		pLow = pLow->_pnext;
		pFas = pFas->_pnext->_pnext;
	}
	//如果pFas为空,有偶数个节点,如果pFas->_pnext为空,有奇数个节点
	if (NULL == pFas)
	{
		return pPre;
	}
	else
	{
		return pLow;
	}
}
// 查找链表的倒数第K个结点,要求只能遍历一次链表 
pNode FindLastKNode(pNode pHead, int K)
{
	if (NULL == pHead || K <= 0)
	{
		return NULL;
	}
	pNode pFir = pHead;
	while (K--)//第一个指针走k步
	{
		if (NULL == pFir)
		{
			return NULL;
		}
		pFir = pFir->_pnext;
	}
	pNode pSec = pHead;
	while (pFir)//第一个指针向后走(N(总数)- k)步
	{
		pFir = pFir->_pnext;
		pSec = pSec->_pnext;//相当于第二个指针倒着走k步
	}
	return pSec;

}

// 删除链表的倒数第K个结点,要求只能遍历一次链表 
pNode DeleteLastKNode(pNode pHead, int K)
{
	if (NULL == pHead || K <= 0)
	{
		return NULL;
	}
	pNode pFir = pHead;
	while (K--)//第一个指针走k步
	{
		if (NULL == pFir)
		{
			return NULL;
		}
		pFir = pFir->_pnext;
	}
	pNode pSec = pHead;
	pNode pPre = NULL;
	while (pFir)//第一个指针向后走(N(总数)- k)步
	{
		pPre = pSec;
		pFir = pFir->_pnext;
		pSec = pSec->_pnext;//相当于第二个指针倒着走k步
	}
	if (pHead == pSec)
	{
		pNode pNew = pHead;
		pHead = pHead->_pnext;
		free(pNew);
		return pHead;
	}
	else
	{
		pPre->_pnext = pSec->_pnext;
		free(pSec);
		return pHead;
	}
}


// 用单链表实现约瑟夫环 
int JosephCircle(pNode* pHead, const int M)
{
	assert(pHead);
	if (NULL == *pHead || M <= 1) {
		return -1;
	}
	pNode pStr = *pHead;
	pNode pCur = NULL;
	while (pStr->_pnext != pStr) {
		//报数
		int count = M;
		while (--count) {
			pCur = pStr;
			pStr = pStr->_pnext;
		}
		//剔除
		pCur->_pnext = pStr->_pnext;
		free(pStr);
		pStr = pCur->_pnext;
	}
	return pStr->_pdata;
}

// 链表的逆置--三个指针 
void ReverseSList(pNode* pHead)
{
	assert(pHead);
	if (NULL == *pHead)//可能改变头结点指针指向传二级指针
	{
		return;
	}
	pNode pCur = *pHead;
	pNode pNex = pCur;
	pNode pPre = NULL;
	while (pCur)
	{
		pNex = pCur->_pnext;
		pCur->_pnext = pPre;
		pPre = pCur;
		pCur = pNex;
	}
	*pHead = pPre;
}

// 链表的逆置--头插法 
pNode ReverseSListOP(pNode pHead)
{
	if (NULL == pHead)
	{
		return NULL;
	}
	pNode pCur = NULL;
	pNode pNew = NULL;
	//处理第一个节点
	pNew = pHead;
	pHead = pHead->_pnext;
	pNew->_pnext = NULL;
	while (pHead)
	{
		pCur = pHead->_pnext;
		pHead->_pnext = pNew;
		pNew = pHead;
		pHead = pCur;
	}
	return pNew;
}

// 用冒泡排序思想对单链表进行排序 
void BubbleSort(pNode pHead)
{
	if (NULL == pHead)
	{
		return;
	}
	pNode pTail = pHead;
	while (pTail->_pnext)
	{
		pTail = pTail->_pnext;
	}
	pNode pCur = NULL;
	pNode pPre = NULL;
	while (pTail != pHead)//pTail指向头说明只有一个节点,不需要再比较
	{
		pCur = pHead;
		while (pCur != pTail)
		{
			if ((pCur->_pdata) > (pCur->_pnext->_pdata))
			{
				int tmp = pCur->_pdata;
				pCur->_pdata = pCur->_pnext->_pdata;
				pCur->_pnext->_pdata = tmp;
			}
			pPre = pCur;
			pCur = pCur->_pnext;
		}
		pTail = pPre;
	}
}

// 合并两个有序单链表,合并后依然有序 
pNode MergeSList(pNode p1, pNode p2)
{
	pNode pNew = NULL;
	//处理头结点
	if (p1 && (p1->_pdata <= p2->_pdata))
	{
		pNew = p1;
		p1 = p1->_pnext;
	}
	else if (p2)
	{
		pNew = p2;
		p2 = p2->_pnext;
	}
	pNode pNewHead = pNew;
	//如果p1,p2都存在节点
	while (p1 && p2)
	{
		if (p1->_pdata <= p2->_pdata)
		{
			pNew->_pnext = p1;
			p1 = p1->_pnext;
		}
		else
		{
			pNew->_pnext = p2;
			p2 = p2->_pnext;
		}
		pNew = pNew->_pnext;
	}
	//p1或者p2为空
	if (p1)
	{
		pNew->_pnext = p1;
	}
	else
	{
		pNew->_pnext = p2;
	}
	return pNewHead;
}

// 判断两个单链表是否相交---链表不带环 
int IsSListCross(pNode pHead1, pNode pHead2)
{
	if (NULL == pHead1 || NULL == pHead2)
	{
		return -1;
	}
	//找到两个链表的最后一个节点
	while (pHead1->_pnext)
	{
		pHead1 = pHead1->_pnext;
	}
	while (pHead2->_pnext)
	{
		pHead2 = pHead2->_pnext;
	}
	//相交节点只可能是y型,不可能是x型,因为一个节点只有一个后继
	if (pHead1 == pHead2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

// 求两个单链表相交的交点---链表不带环 
pNode GetCorssNode(pNode pHead1, pNode pHead2)
{
	if (NULL == pHead1 || NULL == pHead2)
	{
		return NULL;
	}
	int len1 = 0;
	int len2 = 0;
	pNode pCur1 = pHead1;
	pNode pCur2 = pHead2;
	while (pCur1)
	{
		len1++;
		pCur1 = pCur1->_pnext;
	}
	while (pCur2)
	{
		len2++;
		pCur2 = pCur2->_pnext;
	}
	int diff = len1 - len2;
	while (0 != diff)
	{
		if (diff > 0)
		{
			pHead1 = pHead1->_pnext;
			diff--;
		}
		else
		{
			pHead2 = pHead2->_pnext;
			diff++;
		}
	}
	//到同一节点,距离交点有相同距离
	while (pHead1 != pHead2)
	{
		pHead1 = pHead1->_pnext;
		pHead2 = pHead2->_pnext;
	}
	return pHead1;
}

test.c

int main()
{
	pNode Slist,p,P,T;
	pNode pos;
	SListInit(&Slist);
	printf("初始化之后的链表为: ");
	PrintList(&Slist);

	SListPushBack(&Slist, 1);
	SListPushBack(&Slist, 2);
	SListPushBack(&Slist, 3);
	SListPushBack(&Slist, 4);
	SListPushBack(&Slist, 5);
	SListPushBack(&Slist, 6);
	printf("尾插之后的链表为:");
	PrintList(&Slist);

	pos = SListFind(&Slist, 3);
	PrintSListFromTail(Slist);
	printf("\n");

	DeleteListNotTailNode(&Slist,pos);
	PrintList(&Slist);

	printf("中间节点:%d\n",FindMiddleNode(Slist)->_pdata);

	printf("倒数第1个:%d\n", FindLastKNode(Slist, 1)->_pdata);

	DeleteLastKNode(Slist, 1);
	PrintList(&Slist);

	SListPushBack(&Slist, 6);
	SListPushBack(&Slist, 4);
	SListPushBack(&Slist, 2);
	SListPushBack(&Slist, 1);
	PrintList(&Slist);
	BubbleSort(Slist);
	PrintList(&Slist);

	SListInit(&Slist);
	SListInit(&P);
	SListInit(&T);
	SListPushBack(&P, 3);
	SListPushBack(&P, 4);
	SListPushBack(&P, 5);
	SListPushBack(&P, 7);
	SListPushBack(&T, 1);
	SListPushBack(&T, 2);
	SListPushBack(&T, 6);
	SListPushBack(&T, 8);
	PrintList(&P);
	PrintList(&T);
	p = MergeSList(T, P);
	printf("合并: \n");
	PrintList(&p);

	pos = ReverseSListOP(p);
	PrintList(&pos);

	ReverseSList(&pos);
	PrintList(&pos);

	//约瑟夫
	pNode pTail = SListFind(&pos,8);
	pTail->_pnext = pos;
	int tmp = JosephCircle(&pos, 2);
	printf("约瑟夫环最后返回值:%d\n",tmp);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/W_J_F_/article/details/81454600