题目来自:http://fayaa.com/tiku/view/6/
1.问题:
设计一个算法,找出一个无环的单链表里面倒数第k个元素,速度要快!
2.思路:
找中间那个,可以用二个指针同时遍历,一个步进2,一个步进1,当前面的到达末尾的时候,后面正好指向中间。 找第K个的话,也是用二个first,second. first先走,当走到第(k-1)个时候,second开始走,当first大道链表末尾的时候,second即为倒数第k个元素。
3.代码实例:
#include<iostream> #include<stdlib.h> using namespace std; typedef int ElemType; //链表结点结构体 typedef struct Node { ElemType data; //链表结点中的数据域 struct Node *next; //链表结点中的指针域 }Node,*LinkList; void LinkListCreateHead(LinkList &L,int n)//创建指定长度的单链表,使用头插法,逆序插入 { L=(LinkList)malloc(sizeof(Node)); L->next=NULL; LinkList p; for(int i=0;i<n;i++)//在头结点L后面插入新的结点p { p=(LinkList)malloc(sizeof(Node)); cin>>p->data; p->next=L->next; L->next=p;//L一直都是头结点 } } void LinkListCreateTail(LinkList &L,int n)//创建指定长度的单链表,使用尾插法,顺序插入 { L=(LinkList)malloc(sizeof(Node)); L->next=NULL; LinkList p,q; q=L; for(int i=0;i<n;i++)//在单链表最后插入结点 { p=(LinkList)malloc(sizeof(Node)); cin>>p->data; q->next=p; q=p; } p->next=NULL;//最后p指向NULL } /* //已经排好序的两个链表合并 void Merge(LinkList &LM,LinkList LH,LinkList LT)//使用尾插法。 { //cout<<"111"<<endl; LM=(LinkList)malloc(sizeof(Node));//建立合并单链表 LM->next=NULL; LinkList pm,ph,pt; ph=LH->next; pt=LT->next; pm=LM; while(ph&&pt)//当pt或者pt有一个到达链表末尾,就可以停止while循环 { if(ph->data<pt->data) { pm->next=ph; pm=ph; ph=ph->next; } else { pm->next=pt; pm=pt; pt=pt->next; } } pm->next=ph?ph:pt;//如果最后ph不为空则pm->next指向ph,否则指向pt } */ /*1 2 3 4 5 6 7 8 9 10*/ int FindElem(LinkList L,int k) { LinkList first,second; first=L; second=L; int count=0; while(count<k-1) { first=first->next; //cout<<first->data<<endl; count++; } while(first->next!=NULL) { first=first->next; second=second->next; //cout<<second->data; } cout<<"first->data:"<<first->data<<endl; return second->data; //return 0; } int main() { LinkList LH,LT,LM; int n; cout<<"输入链表长度:"<<endl; cin>>n; /* cout<<"构建LinkListCreateHead(LH,n)"<<endl; LinkListCreateHead(LH,n); while(LH->next!=NULL) { //注意点,输出的是:LH->next->data,而不是LH->data,头结点没有数据 cout<<LH->next->data<<" "; LH=LH->next; } cout<<endl; */ cout<<"构建LinkListCreateTail(LT,n)"<<endl; LinkListCreateTail(LT,n); /* while(LT->next!=NULL) { //注意点,输出的是:LT->next->data,而不是LT->data,头结点没有数据 cout<<LT->next->data<<" "; LT=LT->next; } cout<<endl; */ int k=4; int e=FindElem(LT,k); cout<<"倒数第"<<k<<"个元素:"<<e<<endl; system("pause"); return 0; } /* 输入链表长度: 5 构建LinkListCreateHead(LH,n):逆序输出 1 2 3 4 5 5 4 3 2 1 构建LinkListCreateTail(LT,n):顺序输出 1 2 3 4 5 1 2 3 4 5 请按任意键继续. . . */ /* 输入链表长度: 10 构建LinkListCreateTail(LT,n) 1 2 3 4 5 6 7 8 9 10 first->data:10 倒数第4个元素:7 请按任意键继续. . . */
second-first=k-1,即first和second指针所指向的元素位置应该相差k-1个。