热门题---链表面试题总结

14 篇文章 0 订阅
13 篇文章 0 订阅


单链表一直是面试中的重点,今天就把常见的单链表面试题总结了一下

冒泡排序:

先将tail置为空,让prev和cur不停的往前走,条件cur不等于tail 控制每一趟冒泡,找出每次的最大值,再用prev不等于tail控制每一层冒泡,每趟交换完成后将prev的值给tail,让tail 不停的往前走,

代码实现

void Bubble(pLinkList list)
{
	pLinkNode cur = NULL;
	pLinkNode prev = NULL;
	pLinkNode tail = NULL;
	int exage = 0;
	assert(list);
	cur = list->pHead;
	if (list->pHead == NULL)
	{
		return;
	}
	while (list->pHead != tail)
	{
		prev = list->pHead;
		cur = prev->next;
		while (cur != tail)
		{
			exage = 0;
			if (cur->data < prev->data)
			{
				DataType x = cur->data;
				cur->data = prev->data;
				prev->data = x;
				exage = 1;
			}
			prev = cur;
			cur = cur->next;
		}
		tail = prev;
		if (exage == 0)
		{
			return;
		}
	}
}

合并两个有序链表,合并后链表依然有序,

比较两条链表的第一个节点的大小,让新链表的头指向比较后的结果,如上图中指向第二条链表的第一个节点,则让指向cur2往后走,再与cur1进行比较,newhead的next指向下一个比较后的结果

代码实现

pLinkNode MerageSortList(pLinkList p1, pLinkList p2)//合并两个有序链表
{
	assert(p1);
	assert(p2);
	if (p1->pHead == NULL)
		return p2->pHead;
	if (p2->pHead == NULL)
		return p1->pHead;
	
	pLinkNode cur1 = p1->pHead;
	pLinkNode cur2 = p2->pHead;
	pLinkNode newHead = cur1->data < cur2->data ? p1->pHead:p2->pHead;

	pLinkNode Tail = newHead;

	while (cur1&&cur2)
	{
		if (cur1->data > cur2->data)
		{
			Tail ->next = cur1;
			cur1 = cur1->next;
		}
		else
		{
			Tail ->next = cur2;
			cur2 = cur2->next;
		}
		Tail = Tail->next;

		Tail->next = NULL;
	}

	if (cur1)
	{
		Tail->next = cur1;
	}
	if (cur2)
	{
		Tail->next = cur2;
	}
	return newHead;
}

约瑟夫环的问题

代码实现

pLinkNode JosePhCycle(pLinkList p, size_t m)//约瑟夫环
{
	pLinkNode cur = p->pHead;
	assert(p);

	while (1)
	{
		if (cur == NULL)
			return NULL;
		else if (cur == cur->next)//只剩一个节点了
			return cur;
		else
		{
			int x = m;
			
			while (--x)
			{
				cur = cur->next;
			}
			pLinkNode del = cur->next;
			cur->data = del->data;
			cur->next = del->next;
			free(del);
			del = NULL;

		}

	}

}

链表相交问题:

  1. 链表不带环相交

    1)一旦两个链表相交,那么两个链表中的节点一定有相同地址。

2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。

 

只有这一种情况,一共有四种解决方法

  1. 直接将两个链表中的节点进行比较,如果节点相同就说明链表相交,如果直到其中一个链表遍历完都没有找到相同节点,说明链表不相交。但效率很低

  2. 如果两个链表相交,则链表最后一个节点肯定相同,则只需判断链表的最后一个节点是否相同,相同则说明两链表相交

  3. 将链表一的尾节点指针指向链表二的头节点,判断链表是否有环,如果链表有环则两链表相交,如果链表无环,则证明两链表不相交,优化想法:因为链表二的头节点肯定在环中,所以可以直接从链表二的头节点开始判断

  4. 将链表一建立hash表,用链表二中的节点在hash表中进行查询,看是否有相同节点,缺点:增加了内存消耗

代码实现

pLinkNode IslistCricle1(pLinkList plist1, pLinkList plist2)
{
	assert(plist1);
	assert(plist2);
	pLinkNode cur1 = plist1->pHead;
	pLinkNode cur2 = plist2->pHead;
	if (plist1->pHead == NULL)
	{
		printf("链表不相交\n");
		return NULL;
	}
	if (plist2->pHead == NULL)
	{
		printf("链表不相交\n");
		return NULL;
	}

	while (cur1 && cur2)
	{
		cur1 = plist1->pHead;
		while (cur1&&cur2)
		{
			if (cur1 == cur2)
			{
				printf("链表相交于%d结点\n", cur1->data);
				return cur1;
			}
			cur1 = cur1->next;
			//cur2 = cur2->next;
		}
		cur2 = cur2->next;
	}

	return NULL;
}

void IslistCricle2(pLinkList plist1, pLinkList plist2)
{
	assert(plist1);
	assert(plist2);
	pLinkNode cur1 = plist1->pHead;
	pLinkNode cur2 = plist2->pHead;
	
	if (plist1->pHead == NULL)
	{
		printf("链表不相交\n");
		return;
	}
	if (plist2->pHead == NULL)
	{
		printf("链表不相交\n");
		return;
	}

	while (cur1->next)
	{
		cur1 = cur1->next;
	}
	while (cur2->next)
	{
		cur2 = cur2->next;
	}

	if (cur1 == cur2)
	{
		printf("链表相交\n");
	}
	return;
}

pLinkNode IslistCricle3(pLinkList plist1, pLinkList plist2)
{
	assert(plist1);
	assert(plist2);
	pLinkNode cur1 = plist1->pHead;
	pLinkNode cur2 = plist2->pHead;

	if (plist1->pHead == NULL)
	{
		printf("链表不相交\n");
		return NULL;
	}
	if (plist2->pHead == NULL)
	{
		printf("链表不相交\n");
		return NULL;
	}
	while (cur2->next)
	{
		cur2 = cur2->next;
	}
	cur2->next = cur1;
	cur2 = plist2->pHead;
	cur1 = plist1->pHead;
	while (cur2&&cur2->next)
	{
		cur1 = cur1->next;
		cur2 = cur2->next->next;
		if (cur1 == cur2)
		{
			printf("链表相交\n");
			return cur1;
		}
	}

}

复杂链表的拷贝

代码实现

#define _CRT_SECURE_NO_WARNINGS 1

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

typedef int  Datatype;

typedef struct Complex
{
	Datatype data;
	Complex* next;
	Complex* redom;
}Complex, *pComplex;

pComplex BuyNode(Datatype x)
{
	pComplex tmp = (pComplex)malloc(sizeof(Complex));
	if (tmp)
	{
		tmp->data = x;
		tmp->next = NULL;
		tmp->redom = NULL;
	}
	return tmp;
}

void Printf(pComplex head)
{
	while (head)
	{
		printf("head:%d,redom->%d\n", head->data, head->redom->data);
		head = head->next;
	}
}


pComplex CopyComplexLinkList(pComplex head)
{
	pComplex newhead = head;
	pComplex tail = head;
	pComplex cur = head;

	while (cur)
	{
		pComplex tmp = BuyNode(cur->data);
		tmp->next = cur->next;
		cur->next = tmp;
		cur = cur->next->next;
	}
	cur = head;
	while (cur)
	{
		cur->next->redom = cur->redom;
		cur = cur->next->next;
	}

	cur = head;
	newhead = cur->next;
	while (cur && cur->next)
	{
		tail = cur->next;
		tail = tail->next;
		cur->next = cur->next->next;
		cur = cur->next;
	}
	return newhead;
}



void Test()
{
	pComplex c1 = BuyNode(1);
	pComplex c2 = BuyNode(2);
	pComplex c3 = BuyNode(3);
	pComplex c4 = BuyNode(4);
	pComplex c5 = BuyNode(5);

	c1->next = c2;
	c2->next = c3;
	c3->next = c4;
	c4->next = c5;

	c1->redom = c3;
	c2->redom = c4;
	c3->redom = c5;
	c4->redom = c1;
	c5->redom = c2;

	c1 = CopyComplexLinkList(c1);

	Printf(c1);


}
int main()
{
	Test();
	system("pause");
	return 0;
}

下面是用c++的引用实现的一份功能相同的代码

代码实现

//冒泡排序
void Bubble(SListNode* pHead)
{
	int exange = 0;
	if (pHead == NULL || pHead->next == NULL)
	{
		return;
	}
	SListNode* prev = pHead;
	SListNode* cur = pHead->next;
	SListNode* Tail = NULL;
	while (Tail != pHead)
	{
		cur = pHead->next;
		prev = pHead;
		while (cur != Tail)
		{
			if (prev->data > cur->data)
			{
				DataType x;
				x = cur->data;
				cur->data = prev->data;
				prev->data = x;
			}
			prev = cur;
			cur = cur->next;
		}
		Tail = prev;
	}
}

//删除一个无头单链表的非尾节点
void DelNonTailNode(SListNode* pos)
{
	assert(pos);
	assert(pos->next);

	SListNode* del = pos->next;
	pos->data = del->data;
	pos->next = del->next;
	free(del);
	del = NULL;
}


//在无头单链表的非头节点插入一个节点
void InsertNonTailNode(SListNode* pos,DataType x)
{
	assert(pos);
	SListNode* cur = Buynode(pos->data);
	SListNode* temp = pos->next;
	cur->next = temp;
	pos->next = cur;
	pos->data = x;
}


//查找单链表的中间节点并只能遍历一次链表(快慢指针)

SListNode* FindMidNode(SListNode* pHead)
{
	assert(pHead);
	
	if (pHead->next == NULL)
	{
		return pHead;
	}
	else
	{
		SListNode* slow = pHead;
		SListNode* fast = pHead;
	/*	while (fast)
		{
			if (fast->next)
			{
				fast = fast->next->next;
			}
			else
			{
				break;
			}
			slow = slow->next;
		}*/
		while (fast && fast->next)
		{
			slow = slow->next;
			fast = fast->next->next;
		}
		return slow;
	}
	return NULL;
}

//查找链表的倒数第k个节点,且只能遍历链表一次

SListNode* FindNode(SListNode* pHead, int k)
{
	assert(pHead);
	assert(k >= 0);

	SListNode* slow = pHead;
	SListNode* fast = pHead;
	//有问题
	/*while (fast && fast->next)
	{
		while (k--)
		{
			fast = fast->next;
		}
		fast = fast->next;
		slow = slow->next;
	}*/
	while (fast && --k)
	{
		fast = fast->next;
		if (fast == NULL)
		{
			return NULL;
		}
	}

	while (fast->next)
	{
		fast = fast->next;
		slow = slow->next;
	}
	return slow;
}

//从尾到头打印单链表

void PrintTailToHead(SListNode* pHead)
{
	if (pHead == NULL)
	{
		return;
	}
	else
	{
		PrintTailToHead(pHead->next);
		printf("%d ", pHead->data);
	}
}


//逆置单链表   很重要
SListNode*  Reverse(SListNode* pHead)
{
	SListNode* cur = pHead;
	SListNode* newHead = NULL;
	
	while (cur)
	{
		SListNode* temp = cur;
		cur = cur->next;

		temp->next = newHead;
		newHead = temp;
	}
	return newHead;
}


//单链表实现约瑟夫环
//运行时先构造环,注意在代码结尾解环

SListNode* JosePhCycle(SListNode* pHead, int m)
{
	SListNode* cur = pHead;
	while (1)
	{
		if (cur == NULL)
		{
			return NULL;
		}
		else if (cur == cur->next)//只剩一个节点
		{
			return cur;
		}
		else
		{
			int x = m;
			while (--x)
			{
				cur = cur->next;
			}
			SListNode* del = cur->next;
			cur->data = del->data;
			cur->next = del->next;
			free(del);
			del = NULL;
		}
	}
	
}

//合并两个有序链表,合并后依然有序

SListNode* Meragelist(SListNode* pHead1, SListNode* pHead2)
{
	if (pHead1 == NULL)
	{
		return pHead2;
	}
	if (pHead2 == NULL)
	{
		return pHead1;
	}
	/*SListNode* newHead = pHead1->data < pHead2->data ? pHead1:pHead2;

	while (pHead1 == NULL || pHead2 == NULL)
	{
		if (pHead1->data < pHead2->data)
		{
			newHead = pHead1;
			pHead1 = pHead1->next;
		}
		else if (pHead1->data == pHead2->data)
		{
			newHead = pHead1;
			newHead->next = pHead2;
			pHead1 = pHead1->next;
			pHead2 = pHead2->next;
		}
		else
		{
			newHead = pHead2;
			pHead2 = pHead2->next;
		}
		newHead = newHead->next;
		newHead->next = NULL;
	}
	while (pHead1)
	{
		newHead->next = pHead1;
		pHead1 = pHead1->next;
	}
	while (pHead2)*/

	SListNode* newHead = NULL;
	SListNode* cur1 = pHead1;
	SListNode* cur2 = pHead2;
	if (cur1->data < cur2->data)
	{
		newHead = cur1;
		cur1 = cur1->next;
	}
	SListNode* Tail = newHead;
	while (cur1 && cur2)
	{
		if (cur1->data < cur2->data)
		{
			Tail->next = cur1;
			cur1 = cur1->next;
		}
		else
		{
			Tail->next = cur2;
			cur2 = cur2->next;
		}
		Tail = Tail->next;
		Tail->next = NULL;
	}
	if (cur1 != NULL)
	{
		Tail->next = cur1;
	}
	if (cur2 != NULL)
	{
		Tail->next = cur2;
	}
	return newHead;
}

//判断链表是否带环(可以用快慢指针解决)
bool IsSListCycle(SListNode* pHead)
{
	if (pHead == NULL)
	{
		printf("The SList is empty\n");
		return false;
	}
	SListNode* slow = pHead;
	SListNode* fast = pHead;

	while (fast && fast->next)
	{
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow)
		{
			SListNode* cur = slow;
			int length = 0;       //环的长度
			do
			{
				slow = slow->next;
				length++;

			} while (cur != slow);
			
			printf("%d\n", length);
			printf("The SList have cycle\n");
			return true;
		}
	}
	printf("The SList NO cycle\n");
	return false;
}

//环的入口点

SListNode* CycleEntry(SListNode* pHead)
{
	if (pHead == NULL)
	{
		printf("The SList is empty\n");
		return NULL;
	}
	SListNode* slow = pHead;
	SListNode* fast = pHead;

	while (fast && fast->next)
	{
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow)
		{
			return slow;
		}
	}
}

//链表是否相交,若相交,求交点(不带环)

SListNode* IsItersect(SListNode* pHead1,SListNode* pHead2)
{
	if (pHead1 == NULL)
	{
		printf("链表不相交\n");
		return pHead2;
	}
	if (pHead2 == NULL)
	{
		printf("链表不相交\n");
		return pHead1;
	}
	SListNode* cur1 = pHead1;
	SListNode* cur2 = pHead2;

	while (cur1 && cur2)
	{
		if (cur1 == cur2)
		{
			printf("链表相交,交点为:%d\n", cur1->data);
			return cur1;
		}
		cur1 = cur1->next;
		cur2 = cur2 ->next;
	}
	return NULL;
}
 





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值