第一题:找到单链表的中间节点(且时间复杂度为O(1))
快慢指针的方法:两个指针同时从头结点出发,快指针一次走2步,慢指针一次走1步,当快指针走完所有节点时,慢指针就恰好是该单链表的中间节点。(要注意单链表的长度是奇数还是偶数)
第二题:找到链表的倒数第K个节点(时间复杂度为O(1))
同样使用两个指针:让其中一个指针先走K步,然后让两个指针一起走。当先走的那个指针走完链表是,后出发的那个指针就是倒数第K个节点。倒数第K个节点也就是正数第单链表个数-K个节点。
下面是代码的实现:
LinkListTest.h文件
#pragma once
#define TextHeader printf("\n********************%s**********************\n",__FUNCTION
typedef char ElemType;
typedef struct LinkListT
{
ElemType data;
struct LinkListT* next;
}LinkListT;
LinkListT* head;
//初始化单链表
void LinkListT_Init(LinkListT** head);
//打印链表
void DisplayLinkListT(LinkListT* head);
//找到中间节点
LinkListT* FindMidNode(LinkListT* head);
//尾插
LinkListT* LinkListT_PushBack(LinkListT** head,ElemType value);
// 找到倒数第 K 个节点.
LinkListT* FindLastKNode(LinkListT* head, int K);
//创建一个节点
LinkListT* CreateNode(ElemType value);
LinkListTest.c文件
#include"LinkListTest.h"
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
//初始化
void LinkListT_Init(LinkListT** head)
{
if(head == NULL)
{
//非法输入
return;
}
*head = NULL;
}
//打印链表
void DisplayLinkListT(LinkListT* head)
{
LinkListT* cur = head;
if(head == NULL)
{
printf("空链表。\n");
return;
}
for(cur = head;cur != NULL;cur = cur->next )
{
printf("【 %c:%p 】->",cur->data ,cur);
}
printf(" NULL ");
printf("\n\n");
}
//创建节点
LinkListT* CreateNode(ElemType value)
{
LinkListT* new_node = (LinkListT*)malloc(sizeof(LinkListT));
new_node->data = value;
new_node->next = NULL;
return new_node;
}
//尾插
LinkListT* LinkListT_PushBack(LinkListT** head,ElemType value)
{
LinkListT* cur = (*head);
if(head == NULL)
{
//非法输入
return NULL;
}
if((*head) == NULL)
{
*head = CreateNode(value);
return *head;
}
while(cur->next != NULL)
{
cur = cur->next ;
}
cur->next = CreateNode(value);
return cur->next;
}
//找到中间节点
LinkListT* FindMidNode(LinkListT* head)
{
LinkListT* cur = head;
LinkListT* mid = head;
if(head == NULL || head->next == NULL)
{
//空链表
return NULL;
}
while((cur->next != NULL)&&(cur->next ->next != NULL))
{
cur = cur->next->next ;
mid = mid->next ;
}
return mid;
}
// 找到倒数第 K 个节点.
LinkListT* FindLastKNode(LinkListT* head,int K)
{
int c = 0;
LinkListT* fast = head;
LinkListT* slow = head;
if(head == NULL )
{
//空链表
return NULL;
}
if(K <= 0)
{
printf("输入错误.\n");
return NULL;
}
for(c = 0;c < K-1;c++)
{
fast = fast->next ;
}
while(fast->next != NULL)
{
fast = fast->next ;
slow = slow->next ;
}
return slow;
}
测试代码:
#include"LinkListTest.h"
#include<stdio.h>
void TEST_FindMidNode()
{
LinkListT* ret = NULL;
TextHeader;
LinkListT_Init(&head);
LinkListT_PushBack(&head,'l');
LinkListT_PushBack(&head,'h');
LinkListT_PushBack(&head,'e');
LinkListT_PushBack(&head,'c');
LinkListT_PushBack(&head,'b');
LinkListT_PushBack(&head,'f');
LinkListT_PushBack(&head,'n');
DisplayLinkListT(head);
ret = FindMidNode(head);
printf("中间的节点是:【 %c:%p 】\n",ret->data ,ret);
}
void TEST_FindLastKNode()
{
LinkListT* ret = NULL;
TextHeader;
LinkListT_Init(&head);
LinkListT_PushBack(&head,'l');
LinkListT_PushBack(&head,'h');
LinkListT_PushBack(&head,'e');
LinkListT_PushBack(&head,'c');
LinkListT_PushBack(&head,'b');
LinkListT_PushBack(&head,'f');
LinkListT_PushBack(&head,'n');
DisplayLinkListT(head);
ret = FindLastKNode(head, 3);
printf("倒数第%d个节点是:【 %c:%p 】\n",3,ret->data);
}
int main()
{
TEST_FindMidNode();
TEST_FindLastKNode();
return 0;
}