21.已知一个带有表头节点的单链表,结点结构为
data | link |
假设该链表只给出了头指针。
在不改变链表的前提下,请设计一个尽可能高效的算法,
查找链表中倒数第k个位置上的结点(k为正整数)。
若查找成功,算法输出该结点的data域的值,并返回1;
否则,只返回0,要求:
1)描述算法的基本设计思想。
2)描述算法的详细实现步骤。
3)根据设计思想和实现步骤,采用程序设计语言描述算法(使用C、C++或java语言实现),
关键之处请给出简要注释。
/*
有一个带头节点的单链表,设计一个函数找到指定的倒数第K个节点,
输出节点值,并返回1,否则返回0,前提不能改变链表,尽可能高效
分析:
我们可以先统计出总共的节点数count,那么该节点的顺序数num=count-k+1,
当然如果K>count,直接返回0,时间复杂度为0(n),这里还有另一种更加便捷的方法,
只需对链表遍历一次,我们设立两个指针,最开始均指向首节点,然后让q先移动k个节点,
之后p,q同步移动,当q为NULL时,p所在的位置便是倒数第k个节点的位置
*/
#define_CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"linkStruct.h"//通过自创建头文件引入结构体,ctrl+鼠标左键点击即可查看
int findTheReciprocalk(Link *h,int k){//这是第一种解法
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){//这是第二种解法
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;
Link *head;
Link*createLink(int);
head=createLink(0);
printf("请输入要查倒数第几个数:k=");
scanf("%d",&k);
//findTheReciprocalk(head,k);
findTheReciprocalk2(head,k);
return 0;
}