
/*
有一个带头结点的单链表,设计一个函数找到指定的倒数第k个节点,输出节点值,并返回1,否则返回0,前提不能改变链表,尽可能高效
分析:
我们可以先统计出总共的节点数count,那么该节点的顺序数num=count-k+1,当然如果k>count,直接返回0,时间复杂度为O(n)
这里还有另一种更加便捷的方法,只需对链表遍历一次,我们设立两个指针,最开始均指向首节点,然后让q先移动k个节点,之后p
q同步移动,当q为NULL时,p所在的位置便是倒数第k个节点的位置
*/
struct Link {
int data;
struct Link *next;
};
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int findTheReciprocalK(Link *h,int k) {//这是第一种解法
struct Link *p = h->next;
int count = 0,num;
while (p) {//统计元素个数
count++;
p = p->next;
}
p = h->next;
if (k > count) {
return 0;
}
else {
num = count - k + 1;
while (--num) {//这里要用--num,如果用num--,会导致p为下一个元素,注意
p = p->next;
}
printf("%d",p->data);
return 1;
}
}
int findTheReciprocalK2(Link *h,int k) {//这是第二种解法
struct Link *p = h->next, *q = h->next;
int count = k;
while (count--) {
if (q==NULL) {
printf("倒数第%d个节点不存在",k);
return 0;
}
q = q->next;
}
while (q!=NULL) {
p = p->next;
q = q->next;
}
printf("倒数第%d个节点值为:%d",k,p->data);
return 1;
}
int main() {
int k;
struct Link *head;
Link *createLink(int);
head = createLink(0);
printf("请输入要查倒数第几个数:k=");
scanf("%d",&k);
//findTheReciprocalK(head,k);
findTheReciprocalK2(head, k);
return 0;
}