单链表详解以及单链表相关面试题总结

目录

1.单链表的定义

2.获取单链表的第i个元素

3.单链表的插入操作

4.单链表的删除操作

5.单链表的整表删除

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

7.如果两个链表相交,如何寻找相交的节点

8.判断一个单链表是否有环

9.如果一个链表有环,如何找到环的入口

10.找到单链表中的倒数第k个节点

11.两个有序链表的合并

12.找链表的中间节点


相信大家对单链表都不是很陌生,在这里介绍一下单链表的基本的操作和相关问题。

1.单链表的定义

typedef  struct Node
{
	int data;
	Node* next;
}Node;
typedef struct Node* LinkList;//定义链表

2.获取单链表的第i个元素

bool GetElem(LinkList l, int i, int* e)
{
	int j;
	LinkList p;
	p = l->next;
	j = 1;
	while (p && j < i)
	{
		p = p->next;
		++j;
	}
	if (!p)
	{
		return false;
	}
	*e = p->data;
	return true;
}

3.单链表的插入操作

bool LinkInsert(LinkList l, int i, int e)
{
	int j;
	LinkList p, s;
	p = l;
	while (p && j < i)
	{
		p = p->next;
		++j;
	}
	if (!p)
	{
		return false;
	}
	s = (Node*)malloc(sizeof(Node));//申请新的结点
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

4.单链表的删除操作

bool ListDelete(LinkList l, int i, int* e)
{
	int j;
	LinkList p, q;
	p = l;
	j = 1;
	while (p->next && j < i)
	{
		p = p->next;
		++j;
	}
	if (!(p->next))
	{
		return false;
	}
	q = p->next;
	p->next = q->next;
	*e = q->data;
	free(q);
	return true;
}

5.单链表的整表删除

bool ClearList(LinkList l)
{
	LinkList p, q;
	p = l->next;
	while (p)
	{
		q = p->next;
		free(p);
		p = q;
	}
	l->next = NULL;
	return true;
}

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

bool IsCUt(LinkList pList1, LinkList pList2)
{
	int len1 = GetLength(pList1);
	int len2 = GetLength(pList2);
	Node* pLong = pList1;
	Node* pShort = pList2;
	int len = len1 - len2;
	if (len < 0)
	{
		pLong = pList2;
		pShort = pList1;
		len = len2 - len1;
	}
	//先将长的链表遍历到和短链表长度一样的地方
	for (int i = 0; i < len; ++i)
	{
		pLong = pLong->next;
	}
	while (pLong != NULL && pShort != NULL && pLong != pShort)
	{
		pLong = pLong->next;
		pShort = pShort->next;
	}
	//由于pLong和pShort后面的长度是一样的,且是同时向后遍历的,如果跳出循环的条件不是
	//pLong==null,那么也不是pShort==null,一定是pLong==pShort且不等于null.
	if (pLong != NULL)
	{
		return true;
	}
	return false;
}

7.如果两个链表相交,如何寻找相交的节点

在第6个问题中,当条件:

if (pLong != NULL)

成立的时候,pLong和pShort会同时指向两个链表的相交点。

8.判断一个单链表是否有环

解法1:可以用hashSet,将链表依次遍历存入hashSet,如果在遍历的过程中出现了相同的节点,就表明这个链表是有环的。

解法2:设置两个指针,fast和slow,fast每次向前遍历两个节点,slow每次向前遍历一个节点,如果链表有环,那么slow会很快追上fast节点。

bool hasCircle(LinkList l)
{
	Node* fast = l;
	Node* slow = l;
	while (fast != NULL && fast->next != NULL)
	{
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow)
		{
			return true;
		}
	}
	return false;
}

9.如果一个链表有环,如何找到环的入口

环入口的找寻

10.找到单链表中的倒数第k个节点

本人的另一篇博客

11.两个有序链表的合并

本人的另一篇博客

12.找链表的中间节点

可以设立两个指针,,fast和slow,fast每次向前遍历两个节点,slow每次向前遍历一个节点,当fast遍历到链表末端的时候,slow正好指向链表的中间节点。

Node* getMid(LinkList l)
{
	Node* fast = l;
	Node* slow = l;
	while (fast && fast->next)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值