带头结点的单链表,结点结构为(data,next),在不改变链表的前提下,设计一个尽可能高效的算法,查找出链表中倒数第k(k为正整数)个位置上的结点。
第一种方法是先循环一遍链表确定结点个数n,则倒数第k个结点就是就是正数的第n+1-k个,然后在遍历一次链表就可以找到指定结点了,但显然需要遍历两遍链表。
第二种方法可以使用两个指针,第一个指针先走k-1步,然后第二个指针开始走。当第一个指针移动到最后时,第二个指针正好指向倒数第k个结点,只需要遍历一遍链表,显然更高效。
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct Node
{
int data;
Node *next;
}*LinkList;
//创建链表
void createList(LinkList &l,int n)
{
l=(LinkList)malloc(sizeof(Node));
l->next=NULL;
Node *s;
for(int i=0;i<n;i++)
{
s=(Node*)malloc(sizeof(Node));
cin>>s->data;
s->next=l->next; //头插法
l->next=s;
}
}
/*
查找结点,并返回结点数据
如果更完美的话可以考虑一下输入的k的合理性(我懒 所以我就不写了。
*/
int findNode(LinkList l,int k)
{
Node *s1,*s2;
s1=s2=l;
int counter=0;
while(s1->next)
{
if(counter<k-1)
{
s1=s1->next;
counter++;
}
else
{
s1=s1->next;
s2=s2->next;
}
}
return s2->data;
}
//显示链表
void showList(LinkList l)
{
Node *s;
s=l->next;
while(s)
{
cout<<s->data<<" ";
s=s->next;
}
}
int main()
{
LinkList l;
cout<<"输入结点个数:";
int n;
cin>>n;
cout<<"输入各结点数据:";
createList(l,n);
cout<<"链表:";
showList(l);
cout<<endl<<"输入查找的结点位置k:";
int k;
cin>>k;
cout<<"倒数第"<<k<<"个结点数据为:"<<findNode(l,k);
return 0;
}
运行结果: