单链表操作(1)(经典题目:链表的逆置与查找倒数第k个元素)

目录

1.链表的逆置

2.查找单链表倒数第k个元素


1.链表的逆置

 给定链表如下:

给定链表如上图:将除了头节点以外的其他节点依次成为0号节点,1号节点等等。

要想完成链表的逆置,可以从1号这个节点开始一直头插,即将1号节点插入到头节点后边,再将2号节点插入到头节点后边,依次直到将最后一个节点头插完毕,此时0节点的next为nullptr,这个时候,链表的逆置就完成了。

 

 先定义p指针指向头节点下一个节点,也就是0节点;再来判断p是否还有下一个节点。如果p后面没有任何元素了,那么说明链表只有一个节点,就不需要逆置了。如果p后面还有元素,那么就要进行下一步操作:将p的next赋值给q;让q指向要头插的节点。

(1):先将p->next赋值为q->next;防止q后面的节点丢失;(图中绿色部分)

 

(2):再将q与head后面的节点连接起来,也就是将q->next赋值为phead.next;

(图中黄色部分)

(3):再将q与head连接起来,phead.next=q;(蓝色部分)

这个时候就已经完成第一个节点的头插了;

整理一下:

接着,让q继续往后跑,也就是q=p->next;

一直重复上述操作,一直到原来链表的第一个节点的next为nullptr;也就是一直到p->next==nullptr

到此链表的逆置就已经完成了。

代码实现:

bool Contrary(List& phead)  //逆置
{
	if (phead.next ==nullptr)
	{
		return false;
	}
	List* p = phead.next;
	List* q = nullptr;
	if (p->next != nullptr)
	{
		q = p->next;
		while (q != nullptr)
		{
			p->next = q->next;
			q->next = phead.next;
			phead.next = q;
			q = p->next;
		}
	}
	return true;
}

 看一眼结果

2.查找单链表倒数第k个元素

对于双向循环链表来说,查找倒数第k个元素很容易,但是对于单链表而言,就显得稍微有点麻烦。我们还是用刚才的链表来举例:

如果给了链表的长度,或者说允许计算链表的长度,那么这个问题就很简单了;

倒数第k个节点也就是正数第(长度-k+1)个节点。

如果不允许去计算链表的长度的话,可以这样想:先将整个链表逆置,这样的话就是去找正数第k个节点了。找到节点就可以对其进行操作(删除,修改等等);

//找到倒数第k个节点
int Reciprocal(List& p, int k)
{
	if (p.next == nullptr)
	{
		return -1;
	}
	List* q = p.next;
	List* ql = nullptr;
	if (q->next != nullptr)
	{
        ql=q->next;
		while (ql != nullptr)
		{
			q->next = ql->next;
			ql->next = p.next;
			p.next = ql;
			ql = q->next;
		}
	}
	List* qq = p.next;
	if (qq == nullptr)
	{
		return 0;
	}
	for (int i = 0; i < k-1; ++i)
	{
		qq = qq->next;
	}
	return qq->data;
}

先逆置,再进行遍历,查找。

第二种方法也比较好理解:

定义俩个指针,让其中一个先先后走k步,也就是q=q->next先执行k次,然后再让俩个指针同步向后走。当q走到最后一个节点的时候,ql指向的就是要查找的节点!

代码实现:

List* Reciprocal(List& p, int k)
{
	List* q = p.next;
	List* ql = p.next;
	for (int i = 0; i < k; ++i)
	{
		q = q->next;
	}
	while (q != nullptr)
	{
		q = q->next;
		ql = ql->next;
	}
	return ql;
}

以上就是单链表的逆置和查找倒数第k个元素的方法。

感谢阅读!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

g162512

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值