数据结构基础04(单链表典型题目)

1.判断两个单链表是否相交,求相交的那个结点

思路一:通过两个指针,直接跑到最后一个结点,判断两个结点的地址是否相等。 但是无法求得相交的那一个结点。
思路二:先求得两个链表的长度,求差值,指向长的链表的指针先跑差值的结点数,两个指针再同时向后跑,每跑一个结点,判断其地址是否相等,如果相等,则直接返回其中一个指针,即为相交的第一个结点。

LinkList TwoListIntersection(LinkList list1, LinkList list2)
{
	DeterPointIsNull(list1);
	DeterPointIsNull(list2);

	int len1 = list1->length;
	int len2 = list2->length;

	LinkList p = list1;
	LinkList q = list2;

	if (len1 > len2)
	{
		for(int i = 0; i < len1 - len2; ++i)
		{
			p = p->next;
		}
	}
	else
	{
		for (int i = 0; i < len2 - len1; ++i)
		{
			q = q->next;
		}
	}
	while (p != NULL)  //pq长度相等,只需要判断p或只需判断q即可
	{
		if (p == q)   //如果地址相同,则就是要找的结点
		{
			return p;
		}
		p = p->next; //如果地址不同,pq都向后移,继续寻找
		q = q->next;
	}
	return NULL; //当pq均为空,即查找完也没找到地址相同的,则不想交
}

2.判断-个单链表是否有环

static LinkList RingList(LinkList list)
{
	DeterPointIsNull(list);
	LinkList p = list, q = list;//p为慢指针  q为快指针
	while (q != NULL)
	{
		p = p->next;
		q = q->next;
		if (q == NULL)
		{
			return NULL;
		}
		q = q->next;
		if (p == q)
		{
			return p;
		}
	}
}

3.如果有环,返回入环的第一 个结点

入环的第一个结点

LinkList IsRingList(LinkList list)
{
	DeterPointIsNull(list);
	//pNode是快慢指针相遇的结点,不一定是入环的第一个结点
	LinkList pNode = RingList(list);
	if (pNode == NULL)
	{
		return NULL;
	}
	LinkList p = pNode;
	LinkList q = list;
	while (p != q)
	{
		p = p->next;
		q = q->next;
	}
	return p; //入环的第一个结点
} 

4.O(1)删除结点p (p结点不是最后一一个结点)

void DeleteLinkListNode(LinkList list,LinkList p)
{
	if (p == list || p == NULL || p->next == NULL)
	{
		return;
	}
	LinkList q = p->next;
	p->data = q->data;
	p->next = q->next;
	free(q);
}

5.O(1)在结点P之前插入一个新的数据val

void InsertOfNode(LinkList list ,LinkList p, ElemType val)
{
	if (list == NULL || p == NULL || p == list)
	{
		return;
	}
	LinkList s = _ApplyNode(p->data, p->next);
	p->data = val;
	p->next = s;

} 

6.将单链表逆置 12345 54321

void ResverLinkList(LinkList list)
{
	DeterPointIsNull(list);

	//至少两个节点才需要逆置
	if (list->length < 2)
	{
		return;
	}
	
	//分为三个指针  因为要逆序所以有一个必须先指向NULL
	//另外两个是前后关系
	LinkList s = NULL;
	LinkList p = list->next;
	LinkList q = p->next;
	//三个指针完成,q是最快的指针,只需要每次加一,p在q的后面,s跟着p
	while (p != NULL)
	{
		p->next = s; //先让p指向s
		s = p; //s来到p的位置   s向前一步
		p = q; //p来到q      p向前一步
		//如果q已经到了尾结点的下一个  再执行这一步就会出错
		if (q != NULL)
		{
			q = q->next;  //q向前一步
		}
	}
	list->next = s;
}

7.返回倒数第k个结点

//思路一:如果有链表长度,则长度减k+1
//思路二:没有链表长度,使用两个指针p先走k个  q一个一个开始走  当p为空则q为求的结点
LinkList FindAfterK(LinkList list, int k)
{
	DeterPointIsNull(list);
	if (k <= 0||list->next==NULL)
	{
		return NULL;
	}
	LinkList p = list;
	LinkList q = list;
	for (int i = 0; i < k; ++i)
	{
		p = p->next;
		if (p == NULL)
		{
			return NULL;
		}
	}
	while (p != NULL)
	{
		p = p->next;
		q = q->next;
	}	 
	return q;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值