如何设置两个指针和一个计数器,假设p和p1是指针,p2是计数器,P要遍历整个链表,那么,当p走过m的整数倍的时候,计数器P2清零,p1赋p的指针,p1是跳跃地向前进,当p走到头的时候呢,p1再走P2的计数个数。从而实现要求
你的逻辑是错误的,假设链表中一个12个元素,你要找倒数第5个,走过两轮之后,p走到末尾,p2计数是2,p1指向第10个元素,p1再走2次不也到头了吗,怎么会是你要的元素呢?
以你的逻辑的话,应该是p先走m步,用pt记录这个点,这时候p1不变,然后p再走m步,此时,让p1 等于pt,pt再次记录p的位置。当最后一次不足m步的时候,计数是p2,这时候,只需要让p1再走p2步,就是倒数第m个元素。
代码如下,如有帮助,请帮忙采纳一下,谢谢。
#include <stdio.h>
#include <stdlib.h>
struct StNode
{
int data;
struct StNode* next;
};
//创建节点
struct StNode* CreateNode(int d)
{
struct StNode* node = (struct StNode*)malloc(sizeof(struct StNode));;
node->data = d;
node->next = 0;
return node;
}
//创建链表
struct StNode* CreateList()
{
struct StNode* head,*p,*t;
int data;
head = 0;
p = head;
t = head;
printf("创建链表,请输入链表数据:");;
while(1)
{
scanf("%d",&data);
t = CreateNode(data);
if(head ==0)
{
head = t;
p = head;
}
else
{
p->next = t;
p = t;
}
if(getchar() == '\n') break;
}
return head;
}
//打印链表
void Display(struct StNode* head)
{
while(head)
{
printf("%d ",head->data);
head = head->next;
}
printf("\n");
}
struct StNode* GetNode(struct StNode* head,int m)
{
struct StNode *p1=0,*pt = 0,*p;
int i,cnt = 1;
p = head;
p1 = head;
while (p)
{
if(cnt !=0 && cnt%m == 0)
{
if(pt!=0)
p1 = pt;
pt = p;
cnt = 0;
}
cnt++;
p = p->next;
}
if(pt==0) return 0; //说明链表长度不足m
i=0;
if(p1 == head) cnt--;
while(i<cnt && p1)
{
i++;
p1 = p1->next;
}
return p1;
}
int main()
{
struct StNode* list1 = CreateList();
//打印链表
Display(list1);
struct StNode* p = GetNode(list1,2);//倒数第2个
if(p)
printf("倒数第2个:%d\n",p->data);
else
printf("没有那么多数据\n");
p = GetNode(list1,5);//倒数第5个
if(p)
printf("倒数第5个:%d\n",p->data);
else
printf("没有那么多数据\n");
p = GetNode(list1,8);//倒数第8个
if(p)
printf("倒数第8个:%d\n",p->data);
else
printf("没有那么多数据\n");
p = GetNode(list1,15);//倒数第15个
if(p)
printf("倒数第15个:%d\n",p->data);
else
printf("没有那么多数据\n");
return 0;
}
好像有点疑问,p1应该指向p前一个m倍数的节点,而不是p1赋p的指针。如果p1赋值p,那p1岂不是一直跳着跟着p了。当p到尾部时,p1和p的距离不足m。
应该是当p指向p2计数为m的倍数时,记住该位置,然后p继续往前移动,遇到下一个p2为m倍数时,才把p1指向前一个记录的p位置。这样当p到尾部时,p1向前移动p2最后的值,那么p1与链表尾部的距离正好是m,输出p1的值就可以了