制作人 :TheShyclear
制作时间:2018-7-21
制作内容:查找单链表中的倒数第k个数据
版本号 :8.0
缺陷:头节点只能插入一次,不能在1号节点出插入,详细看Insert函数
注意:头指针的不可改变性
思路:单链表中的许多问题需要用到两个指针的配合,因为单链表只有后继节点,无法找到后继节点。
当我们拿到这个问题时,第一反应肯定是:用一个指针指向头节点然后呢循环计数到最后节点,这样我们就知道了链表的总长度le,然后那么倒数第k个节点就是第le+1-k个节点,这样的话时间复杂度就是O(n)。
那么我们是否有一种更简便的迅捷的方法呢?使其复杂度为O(1)呢?当然可以!由于单链表的特殊性,只能表示后继节点,而无法表示前驱节点,通常情况下,我们都会采取辅助指针的方法来解决相应的问题。
具体代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
typedef int Elemtype;
typedef struct ListNode
{
Elemtype data;//值域
ListNode *m_pNext;//指针域
}ListNode,*PListNode;
ListNode* BuyNode()
{
ListNode* p = (ListNode*)malloc(sizeof(ListNode));
if(NULL == p)
{
printf("buynode is error:\n");
exit(1);
}
memset(p,0,sizeof(ListNode));
return p;
}
void InitList(PListNode &p)
{
p = BuyNode();
p->m_pNext = NULL;
p->data = 0;
}
int GetLength(PListNode &head)//问题出现:不能直接操作head节点
{
int count = 0;
PListNode s = head;
while(s!=NULL)
{
count+=1;
s=s->m_pNext;
}
return count;
}
void InsertList(PListNode &p,Elemtype x,int pos)
{
if(pos<1 || pos>GetLength(p)+1)
{
printf("input pos is error:\n");
exit(1);
}
PListNode s = p;//头节点 s
if(pos == 1)
{
p->data = x;
p->m_pNext = NULL;
}
else
{
while(pos-2)
{
s = s->m_pNext;
--pos;
}//s指向前驱
PListNode r =s->m_pNext;
PListNode q = BuyNode();
q->data = x;
s->m_pNext = q;
q->m_pNext = r;
}
}
PListNode Find_Kth_To_Tail(PListNode &p,int k)
{
if(k<1 || k>GetLength(p))
{
printf("input k is error:\n");
exit(1);
}
PListNode s =p;
PListNode q =p;
for(int i=0;i<k-1;++i)
{
s = s->m_pNext;
}
while(s->m_pNext != NULL)
{
s = s->m_pNext;
q = q->m_pNext;
}
return q;
}
void Show_List(PListNode &head)
{
PListNode s =head;
while(s != NULL)
{
printf("%d ",s->data);
s = s->m_pNext;
}
}
void main()
{
PListNode head;
InitList(head);
for(int i=1;i<5;++i)
{
InsertList(head,i+10,i);
}
Show_List(head);
PListNode r = Find_Kth_To_Tail(head,2);
printf(" ");
printf("%d \n",r->data);
}
运行结果:
11 12 13 14 13
请按任意键继续. . .