查找链表的倒数第k个结点
方法:设置两个指针fast,slow
让快指针先走k步,随后两个指针一起向后移动,当快指针为空时,慢指针指向的结点即为链表的倒数第k个结点。
#define DataType int
typedef struct Node{
DataType data;
struct Node* next;
}linklist;
linklist * FindLastKNode(linklist *head,int k)
{
linklist *fast = head;
linklist *slow = head;
if (head == NULL && k < 0)
{
return NULL;
}
while (k--)
{
if (fast == NULL)
return NULL;
fast = fast->next;
}
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
注意判断,若k为负数,或者链表为空时返回空指针;若k的值大于链表的长度,导致fast为空也返回空指针。
删除链表的倒数第k个结点
方法:用如上所示方法先找到倒数第k个结点,然后删除结点,若倒数第k个结点是尾结点则运用尾删法删除。若为其他结点,则将该结点的下一个结点的值赋给此结点之后删除这个结点的下一个结点。即:
void EraseLastKNode(linklist *head, int k)
{
linklist *fast = head;
linklist *slow = head;
linklist *cur = NULL;
if (head == NULL && k < 0)
{
return ;
}
//快指针先走k步
while (k--)
{
if (fast == NULL)
return ;
fast = fast->next;
}
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
//slow即倒数第k个结点
//若删除的不是尾结点
if (slow->next != NULL)
{
EraseNotTailNode(slow);
}
//删除尾结点
else
{
LinkListPopBack(&head);
}
}
若删除的不是尾结点:
//删除无头单链表的非尾结点
void EraseNotTailNode(linklist *pos)
{
linklist *cur = NULL;
//链表为空,或者只有一个头结点(尾结点)
if (pos == NULL && pos->next == NULL)
{
return;
}
cur = pos->next;
//将pos后面的值赋给pos
pos->data = cur->data;
pos->next = cur->next;
free(cur);
cur = NULL;
}
- pos为要删除结点的位置。
若删除的是尾结点:
//尾删法
void LinkListPopBack(linklist **phead)
{
linklist *cur = NULL;
linklist *pre = NULL;
assert(phead);
//1.无结点
if (*phead == NULL)
{
printf("链表为空,无法删除!\n");
return;
}
//2.只有一个头结点
else if ((*phead)->next == NULL)
{
free(*phead);
*phead = NULL;
}
//3.多个结点
else
{
cur = *phead;
while (cur->next != NULL)
{
pre = cur;
cur = cur->next;
}
free(cur);
cur = NULL;
pre->next = NULL;
}
}