编写函数求单链表的倒数第K个结点

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43909184/article/details/99651540

先说一说具体思路:
1.不可行的常规解法
  为了得到倒数第k个结点,先走到链表的尾端,再从尾端回溯k步。当时,从链表结点的定义可以看出本题中的链表是单向链表,单向链表的结点只有从前往后的指针而没有从后往前的指针,因此这种思路行不通,它只适用于双向链表。
  如果链表定义中有指向前一个节点的指针,那么此解法是可行的。
2.可行但不高效的常规解法
  假设整个链表有n个结点,那么倒数第k个结点就是从头结点开始的第n-k+1个结点。如果我们能够得到链表中结点的个数n,那我们只要从头结点开始往后走n-k+1步就可以了。
  那么,这里的重点就在于如何求链表中节点的个数n,只需要从头开始遍历链表,每经过一个结点,计数器加1就行了。
  但是,问题来了:这种思路需要遍历链表两次,第一次统计出链表中结点的个数,第二次才能找到倒数第k个结点。
3.可行且高效的解法
  为了能够只遍历一次就能找到倒数第k个节点,可以定义两个指针:
 (1)第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;
 (2)从第k步开始,第二个指针也开始从链表的头指针开始遍历;
 (3)由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第k个结点。

  下图展示了在有6个结点的链表上找倒数第3个结点的过程:
在这里插入图片描述
代码如下:

//找到倒数第k个结点 
node* find_Kth_to_tail(linklist *s, int k) {
	node* tmp = s->head;		//第一个指针 
	node* res = s->head;		//第二个指针 
	int i;
	for(i = 0; i < k - 1; ++i) {
		tmp = tmp->next;
	}
	while(tmp->next) {
		res = res->next;
		tmp = tmp->next; 
	}
	return res;
}

拓展

  1. 当我们用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表。可以让其中一个指针遍历的速度快一些(比如一次在链表上走两步),或者让它先在链表上走若干步。
  2. 求链表的中间节点如果链表的结点总数为奇数,返回中间节点,如果链表的总数为偶数,返回中间两个结点中的任意一个也可以定义两个指针,同时从链表的头出发,一个走一步,一个走两步,走的快的到表尾时,走得慢的正好是中间结点。
  3. 当用一个指针遍历链表不能解决问题的话,尝试用两个链表

猜你喜欢

转载自blog.csdn.net/qq_43909184/article/details/99651540