1. 描述
输入一个单向链表(可带表头), 输出该链表中倒数第 k 个结点。链表的倒数第 0 个结点为链表的尾指针,即链表的最后一个结点。结点定义如下:
typedef struct BiNode {
int data;
struct BiNode *next;
}BiNode;
2. 思路
在遍历时维持两个指针,第一个指针从链表的头指针开始遍历, 在第 k-1 (k从0开始)步之前,第二个指针保持不动;在第 k-1 步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在 k-1, 当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第 k 个结点。
代码如下(链表带头结点):
BiNode* k_th_tailing_node(BiNode *H, int k)
{
if (! H || k < 0) return NULL;
BiNode *p, *q;
p = q = H;
while (q && k--)
q = q->next;
while (q && q->next) //当k大于结点个数时,q为NULL;当k等于结点个数时q指向最后一个结点,p未移动
{
p = p->next;
q = q->next;
}
if (! q) return NULL;
return p;
}
创建单链表的函数如下:
void createList(BiNode **H, int A[], int n) //根据数组A[0..n-1]中的值建立链表
{
BiNode *p;
*H = (BiNode *)malloc(sizeof(BiNode)); //头结点
(*H)->next = NULL;
while (n--) //到序建立单链表
{
p = (BiNode *)malloc(sizeof(BiNode));
p->data = A[n];
p->next = (*H)->next;
(*H)->next = p;
}
}
3. 类似的一道题
输入一个单向链表。如果该链表的结点数为奇数,输出中间的结点;如果链表结点数为偶数,输出中间两个结点前面的一个。
思路:使用两个指针进行遍历:
(1) 快指针每次前进2
(2) 慢指针每次前进1
这样当快指针到达最后一个结点时,慢指针指向的为中间结点(奇数结点个数时)或中间两个结点前面的那个(结点个数为偶数时)。
代码如下
BiNode* midList(BiNode *H)
{
BiNode *p, *q;
p = q = H;
while (q->next) {
q = q->next;
if (q->next)
q = q->next;
p = p->next;
}
return p;
}