输入一个链表,输出该链表中倒数第k个结点

本文介绍了一种有效的算法,用于找到单链表中倒数第K个节点的方法,并通过多个测试案例验证了算法的正确性。文章详细展示了如何通过双指针技巧解决这一常见数据结构问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法描述:

输入一个链表,输出该链表中倒数第k个结点

算法实现:

/*************************************************************************
	> File Name: main.c
	> Author: cyf
	> Mail: XXX@qq.com
	> Created Time: 2016年05月19日 星期四 09时38分46秒
 ************************************************************************/

#include "findKthToTail.h"
void Test1()
{
    printf("=====Test1 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 4.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 2);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试要找的结点是链表的尾结点
void Test2()
{
    printf("=====Test2 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 5.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 1);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试要找的结点是链表的头结点
void Test3()
{
    printf("=====Test3 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 1.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 5);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试空链表
void Test4()
{
    printf("=====Test4 starts:=====\n");
    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(NULL, 100);
    PrintListNode(pNode);
}

// 测试输入的第二个参数大于链表的结点总数
void Test5()
{
    printf("=====Test5 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 6);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试输入的第二个参数为0
void Test6()
{
    printf("=====Test6 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 0);
    PrintListNode(pNode);

    DestroyList(pNode1);
}
int main()
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	return 0;
}/*************************************************************************
	> File Name: main.c
	> Author: cyf
	> Mail: XXX@qq.com
	> Created Time: 2016年05月19日 星期四 09时38分46秒
 ************************************************************************/

#include "findKthToTail.h"
void Test1()
{
    printf("=====Test1 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 4.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 2);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试要找的结点是链表的尾结点
void Test2()
{
    printf("=====Test2 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 5.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 1);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试要找的结点是链表的头结点
void Test3()
{
    printf("=====Test3 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: 1.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 5);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试空链表
void Test4()
{
    printf("=====Test4 starts:=====\n");
    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(NULL, 100);
    PrintListNode(pNode);
}

// 测试输入的第二个参数大于链表的结点总数
void Test5()
{
    printf("=====Test5 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 6);
    PrintListNode(pNode);

    DestroyList(pNode1);
}

// 测试输入的第二个参数为0
void Test6()
{
    printf("=====Test6 starts:=====\n");
    struct ListNode* pNode1 = CreateListNode(1);
    struct ListNode* pNode2 = CreateListNode(2);
    struct ListNode* pNode3 = CreateListNode(3);
    struct ListNode* pNode4 = CreateListNode(4);
    struct ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    printf("expected result: NULL.\n");
    struct ListNode* pNode = findKthToTail(pNode1, 0);
    PrintListNode(pNode);

    DestroyList(pNode1);
}
int main()
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	return 0;
}

/*************************************************************************
	> File Name: findKthToTail.h
	> Author: cyf
	> Mail: XXX@qq.com
	> Created Time: 2016年05月19日 星期四 09时21分05秒
 ************************************************************************/

#ifndef _FINDKTHTOTAIL_H
#define _FINDKTHTOTAIL_H

#include <stdio.h>
#include <stdlib.h>
#include "List.h"
struct ListNode *findKthToTail(struct ListNode *pHead, unsigned int k);

#endif
/*************************************************************************
	> File Name: findKthToTail.c
	> Author: cyf
	> Mail: XXX@qq.com
	> Created Time: 2016年05月19日 星期四 09时32分11秒
 ************************************************************************/

#include "findKthToTail.h"
struct ListNode *findKthToTail(struct ListNode *pHead, unsigned int k)
{
	if (pHead == NULL || k==0)
		return NULL;
	struct ListNode *pFirst = pHead;
	struct ListNode *pLast = NULL;
	unsigned int i = 0;
	for (i=0; i< k-1; i++)
	{
		if (pFirst->next != NULL)
			pFirst = pFirst->next;
		else
			return NULL;
	}
	pLast = pHead;
	while (pFirst->next != NULL)
	{
		pFirst = pFirst->next;
		pLast = pLast->next;
	}
	return pLast;

}
/************************************************************************
	> File Name: List.h
	> Author: cyf
	> Mail: 1097189275@qq.com 
	> Created Time: 2016年03月23日 星期三 17时27分15秒
 ************************************************************************/

#ifndef ALGRITHMN_LIST_H
#define ALGRITHMN_LIST_H


struct ListNode
{
	int data;
	struct ListNode *next;
};
struct ListNode *CreateListNode(int value);
void ConnectListNodes(struct ListNode *pCurrent, struct ListNode *pNext);
void PrintListNode(struct ListNode *pNode);
void PrintList(struct ListNode *pHead);
void AddToTail(struct ListNode **pHead, int value);
void RemoveNode(struct ListNode **pHead,int value);
unsigned int GetListLength(struct ListNode *pHead);
void DestroyNode(struct ListNode *pNode);
void DestroyList(struct ListNode *pHead);

#endif

/*************************************************************************
	> File Name: List.cpp
	> Author: cyf
	> Mail: 1097189275@qq.com 
	> Created Time: 2016年03月23日 星期三 17时32分11秒
 ************************************************************************/

#include "List.h"
#include <stdio.h>
#include <stdlib.h>
/*
 * 创建一个链表的结点
 * */
struct ListNode *CreateListNode(int value)
{
	struct ListNode *pNode =(struct ListNode *)malloc(sizeof(struct ListNode));
	pNode->data = value;
	pNode->next = NULL;

	return pNode;
}
/*
 * 将两个结点连接起来
 * */
void ConnectListNodes(struct ListNode *pCurrent, struct ListNode *pNext)
{
	if(!pCurrent)
	{
		printf("ERROR!connect two ListNode.\n");
		exit(1);
	}
	pCurrent->next = pNext;
}
/*
 * 打印结点
 * */
void PrintListNode(struct ListNode *pNode)
{
	if(!pNode)
	{
		printf("the node is null!\n");
		exit(1);
	}
	printf("The value of the node is %d\n",pNode->data);
}
/*
 * 打印链表
 * */
void PrintList(struct ListNode *pHead)
{
	printf("print the list:\n");
	struct ListNode *pNode = pHead;
	if(!pNode)
	{
		printf("the list is null\n");
		exit(1);
	}
	while(pNode != NULL)
	{
		printf("%d ",pNode->data);
		pNode = pNode->next;
	}
}
/*
 * 在链表结尾添加结点
 * */
void AddToTail(struct ListNode **pHead, int value)
{
	struct ListNode *pNew = (struct ListNode*)malloc(sizeof(struct ListNode));
	pNew->data = value;
	pNew->next = NULL;

	if(!pHead)
		*pHead = pNew;
	else
	{
		struct ListNode *pNode = *pHead;
		while(pNode != NULL)
		{
			pNode = pNode->next;
		}
		pNode->next = pNew;
	}
	
}
/*
 * 删除链表中结点值为value的结点
 * */
void RemoveNode(struct ListNode **pHead, int value)
{
	if(pHead == NULL||*pHead == NULL)
	{
		printf("the list is null");
		return;
	}
	struct ListNode *ToBeDel = NULL;

	if((*pHead)->data == value)
	{
		ToBeDel = *pHead;
		*pHead = (*pHead)->next;
	}
	else
	{
		struct ListNode *pNode = *pHead;

		while(pNode->next != NULL && pNode->next->data != value)
			pNode = pNode->next;
		if(pNode->next != NULL && pNode->next->data == value)
		{
			ToBeDel = pNode->next;
			pNode->next = pNode->next->next;
		}
	}

	if(ToBeDel != NULL)
	{
		free(ToBeDel);
		ToBeDel = NULL;
	}
}
/*
 * 计算链表的长度
 * */
unsigned int GetListLength(struct ListNode *pHead)
{
	unsigned int length = 0;
	struct ListNode *pNode = pHead;

	while(pNode != NULL)
	{
		++length;
		pNode = pNode->next;
	}

	return length;
}
/*
 * 销毁一个结点
 * */
void DestroyNode(struct ListNode *pNode)
{
	free(pNode);
	pNode = NULL;
}
void DestroyList(struct ListNode* pHead)
{
	struct ListNode *pNode = pHead;
	while (pNode != NULL)
	{
		pHead = pHead->next;
		free(pNode);
		pNode = pHead;
	}
}

.SUFFIXES:.c.o

CC = gcc
CFLAGS = -g -O2 -Wall
SRCS = main.c\
	   List.c\
	   findKthToTail.c
OBJS = $(SRCS:.c=.o)
EXE = main

all:$(OBJS)
	$(CC) $(OBJS) -o $(EXE) $(CFLAGS)

.c.o:
	$(CC) -o $@ -c $(CFLAGS) $<

clean:
	rm -rf $(OBJS) $(EXE)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yiluohan0307

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值