【面试题】单链表的操作1

单链表的建立、插入等替他操作见本人博客:

单链表的基本操作 http://10741357.blog.51cto.com/10731357/1736387

【面试题】单链表的操作2 http://10741357.blog.51cto.com/10731357/1736403

介绍了6种有关单链表的面试题,对于以下链表要求的实现,解题的思路很重要。

各函数的实现,代码如下:

#include"SListNode.h"

void PrintTailToHead(SListNode* pHead)//从尾到头打印单链表
{//递归实现
	if (pHead)
	{
		PrintTailToHead(pHead->next);
		printf("%d->", pHead->data);
	}
}
void DelNonTailNode(SListNode* pos)//删除一个无头单链表的非尾节点(删除pos节点)
{//替换法
	//1->2->3->4删除第2个节点时,将第三个节点值赋给第二个1->3->2->4,删除第3个节点
	assert(pos);
	assert(pos->next);
	SListNode* del = pos->next;
	SListNode* next = del->next;//pos->next->next
	pos->data = del->data;
	pos->next = next;
	free(del);
}
void InsertFrontNode(SListNode* pos, DataType x)//在无头单链表的一个非头结点前插入一个节点
{//替换法
	//1->2->4->5第三个节点4前插入3,则4、5间插入3(1->2->4->3->5),再互换第三、四个节点值
	assert(pos);
	SListNode* tmp = _BuyNode(pos->data);
	tmp->next = pos->next;
	pos->next = tmp;//1->2->4->4->5
	tmp->data = x;
	//SListNode* tmp = _BuyNode(x);
	//tmp->next = pos->next;
	//pos->next = tmp;
	//DataType temp = pos->data;
	//pos->data = tmp->data;
	//tmp->data = temp;
}
SListNode* Rverse(SListNode* pHead)//逆置/反转单链表
{//头插思想,注意反转要检查该单链表是否为空
	//1->2->3->4新链表中依次取出1 2 3 4进行头插
	if (pHead == NULL)
	{
		printf("SListNode is NULL!\n");
		return NULL;
	}
	SListNode* newHead = NULL;
	SListNode* cur = pHead;
	while (cur)
	{
		SListNode* tmp = cur;
		cur = cur->next;
		tmp->next = newHead;
		newHead = tmp;
	}
	return newHead;
}
SListNode* FindMidNode(SListNode* pHead)//查找单链表的中间节点,要求只能遍历一次链表
{//利用快慢指针实现,快指针走2步的是慢指针走1步的2倍
	SListNode* fast = pHead;
	SListNode* slow = pHead;
	while (fast && fast->next)
	{
		fast = fast->next->next;
		//链表总数为偶数时加上if返回较小数,无if时返回较大数
		if (fast == NULL)
			break;
		slow = slow->next;
	}
	//while (fast)
	//{ 
	//	if(fast->next)
	//		fast = fast->next->next;
	//	else break;
	//	slow = slow->next;
	//}
	return slow;
}
SListNode* FindMidNode(SListNode* pHead, DataType k)//查找单链表的倒数第k个节点,要求只能遍历一次链表
{//快慢指针,快指针走k步,慢指针走一步,之后同速度走
	SListNode* fast = pHead;
	SListNode* slow = pHead;
	while (k-- && fast)
		fast = fast->next;
	if (k == -1)
	{
		while (fast)
		{
			slow = slow->next;
			fast = fast->next;
		}
	}
	else
		return NULL;
	//while (k-- && fast)
	//{
	//	fast = fast->next;
	//	if (fast == NULL)
	//		return NULL;
	//}
	//while (fast)
	//{
	//	slow = slow->next;
	//	fast = fast->next;
	//}
	return slow;
}

各函数测试用例如下:

void Test4()
{//【面试题一】从尾到头打印单链表
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 1);
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 3);
	PushBack_Cpp(phead, 4);
	PushBack_Cpp(phead, 5);
	PushBack_Cpp(phead, 6);
	PrintSList(phead);
	printf("\n---------------------\n");
	PrintTailToHead(phead);
	printf("NULL");
}

void Test5()
{//【面试题二】删除一个无头单链表的非尾节点
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 1);
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 3);
	PushBack_Cpp(phead, 8);
	PushBack_Cpp(phead, 4);
	PushBack_Cpp(phead, 5);
	PrintSList(phead);
	printf("\n---------------------\n");
	DelNonTailNode(Find(phead, 8));
	PrintSList(phead);
	DestoryList(phead);
}

void Test6()
{//【面试题三】在无头单链表的一个非头结点前插入一个节点
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 1);
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 4);
	PushBack_Cpp(phead, 5);
	PushBack_Cpp(phead, 6);
	PrintSList(phead);
	printf("\n---------------------\n");
	InsertFrontNode(Find(phead, 4), 3);
	PrintSList(phead);
	DestoryList(phead);
}

void Test7()
{//【面试题四】逆置/反转单链表
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 1);
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 3);
	PushBack_Cpp(phead, 4);
	PrintSList(phead);
	printf("\n---------------------\n");
	SListNode *newphead = Rverse(phead);
	PrintSList(newphead);
	DestoryList(phead);
}

void Test8()
{//【面试题五】查找单链表的中间节点,要求只能遍历一次链表
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 3);
	PushBack_Cpp(phead, 4);
	PushBack_Cpp(phead, 5);
	PushBack_Cpp(phead, 6);
	PushBack_Cpp(phead, 7);
	PrintSList(phead);
	printf("\n---------------------\n");
	printf("%d\n",FindMidNode(phead)->data);
	DestoryList(phead);
}

void Test9()
{//【面试题六】查找单链表的倒数第k个节点,要求只能遍历一次链表
	SListNode *phead = NULL;
	PushBack_Cpp(phead, 1);
	PushBack_Cpp(phead, 2);
	PushBack_Cpp(phead, 3);
	PushBack_Cpp(phead, 5);
	PushBack_Cpp(phead, 6);
	PushBack_Cpp(phead, 7);
	PrintSList(phead);
	printf("\n---------------------\n");
	SListNode *pos = FindMidNode(phead, 3);
	printf("%d\n",pos->data);
	DestoryList(phead);
}
int main()
{
	Test4();
	printf("\n***********************\n");
	Test5();
	printf("\n***********************\n");
	Test6();
	printf("\n***********************\n");
	Test7();
	printf("\n***********************\n");
	Test8();
	printf("\n***********************\n");
	Test9();
	system("pause");
}

本文出自 “Scen” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1736395

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值