算法思想:定义两个指针,pFast和pSlow,都指向头结点,pFast先后移k-1位,使pFast指向第k个结点,此时pSlow就是相对pFast的倒数第k个结点。然后同时后移,当pFast走到表尾时,pSlow正好指向倒数第k个结点。然后将pSlow指向的结点删除。
删除单链表中的倒数第k个结点,首先要确定倒数第k个结点的位置。
//查找指向链表中的倒数第k个结点的指针
Node* Find_k_Node(LinkList pHead, int k)
{
if (pHead == NULL || k < 0)
{
return NULL;
}
Node* pFast = pHead;
Node* pSlow = pHead;
//pFast指针后移k-1位
while (--k)
{
pFast = pFast->Next;
}
//循环结束后pFast指向表尾,pSlow指向链表的倒数第k个结点
while (pHead&&(pFast->Next))
{
pSlow = pSlow->Next;
pFast = pFast->Next;
}
//返回指向倒数第k个结点的指针
return pSlow;
}
//删除链表中的倒数第k个结点
int Del_k_Node(LinkList pHead, int k)
{
if (k < 1 || k > length(pHead))
{
printf("input error!\n");
return NULL;
}
//调用Find_k_Node,得到指向倒数第k个结点的指针
Node* pDel = Find_k_Node(pHead, k);
Node* pPre = pHead;
Node* pNext = pDel->Next;
//使pPre从pHead开始后移,循环结束时,pPre->Next=pDl;
while (pPre->Next != pDel)
{
pPre = pPre->Next;
}
pPre->Next = pNext;
free(pDel);
//打印删除倒数第k个结点后链表中的元素
PrintList(pHead);
return 0;
}
完整源代码:
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
typedef int DataType;
typedef struct Node
{
DataType Data;
struct Node* Next;
}Node, *LinkList;
//初始化,将头指针pHead置空
void InitList(LinkList* pHead)
{
*pHead = NULL;
}
//尾插,在表尾插入一个元素data
void PushBack(LinkList* pHead, DataType data)
{
//如果链表为空则头插一个元素data
if (NULL == (*pHead))
{
*pHead = (LinkList)malloc(sizeof(Node));
if (NULL == *pHead)
{
printf("申请空间失败!\n");
}
(*pHead)->Data = data;
(*pHead)->Next = NULL;
/*PushFornt(pHead, data);*/
return;
}
Node* pCur = (*pHead);
Node* pNewNode = (LinkList)malloc(sizeof(Node));
if (pNewNode == NULL)
{
printf("申请空间失败!\n");
}
//跳出循环时pCur指向链表的尾结点
while (pCur->Next != NULL)
{
pCur = pCur->Next;
}
pNewNode->Data = data;
pCur->Next = pNewNode;
pNewNode->Next = NULL;
}
//求表长,求链表中元素的个数
int length(LinkList pHead)
{
if (pHead == NULL)
{
return 0;
}
int count = 0;
Node* p;
p = pHead;
while (p)
{
p = p->Next;
count++;
}
return count;
}
//打印表中元素
void PrintList(LinkList pHead)
{
Node* pCur = pHead;
while (pCur)
{
printf("%-3d", pCur->Data);
pCur = pCur->Next;
}
printf("\n");
}
//查找指向链表中的倒数第k个结点的指针
Node* Find_k_Node(LinkList pHead, int k)
{
if (pHead == NULL || k < 0)
{
return NULL;
}
Node* pFast = pHead;
Node* pSlow = pHead;
//pFast指针后移k-1位
while (--k)
{
pFast = pFast->Next;
}
//循环结束后pFast指向表尾,pSlow指向链表的倒数第k个结点
while (pHead && (pFast->Next))
{
pSlow = pSlow->Next;
pFast = pFast->Next;
}
//返回指向倒数第k个结点的指针
return pSlow;
}
//删除链表中的倒数第k个结点
int Del_k_Node(LinkList pHead, int k)
{
if (k < 1 || k > length(pHead))
{
printf("input error!\n");
return NULL;
}
//调用Find_k_Node,得到指向倒数第k个结点的指针
Node* pDel = Find_k_Node(pHead, k);
Node* pPre = pHead;
Node* pNext = pDel->Next;
//使pPre从pHead开始后移,循环结束时,pPre->Next=pDl;
while (pPre->Next != pDel)
{
pPre = pPre->Next;
}
pPre->Next = pNext;
free(pDel);
//打印删除倒数第k个结点后链表中的元素
PrintList(pHead);
return 0;
}
int main()
{
LinkList L;
//初使化链表
InitList(&L);
int k = 0;
int data = 0;
scanf("%d", &data);
//在链表中循环插入元素data,以-1作为结束标志
while (data != -1)
{
PushBack(&L, data);
scanf("%d", &data);
}
//打印表中元素
PrintList(L);
//输入要删除的元素序号k,倒数
scanf("%d", &k);
//删除表L中的倒数第k个结点,并打印删除后链表中的元素
Del_k_Node(L, k);
system("pause");
return 0;
}