链表的相关面试题

在实现了单链表的简单函数实现之后,在此基础上,我们可以实现链表的一部分扩展:

一、删除无头结点单链表的非尾结点

void EraseNotTail(pLinkNode pos);
既然是无头结点的链表,那么就不能考虑从头结点开始遍历找到这个结点时直接free。

我们可以换个思路考虑一下,将此结点的data值改为下一个结点的data值,而将下一个结点删除,这样,我们也可以得到同样的效果。分析如图:



代码如下:

void EraseNotTail(pLinkNode pos)//删除无头单链表的非尾结点
{
	pLinkNode cur = NULL;
	assert(pos->next);
	cur = pos->next;
	pos->data = pos->next->data;
	pos->next = pos->next->next;
	free(cur);
}

二、逆序链表

void ReverList(pLinkList pList);

逆序链表,首先,我们应该清楚这是一个单向链表,所以我们不可能定义两个结点指针分别指向链表的头和尾,然后每交换一次,一个指针向后移动,一个指针向前移动。因此,我们只能从前向后遍历。那么应该怎么做呢?!

我们可以利用“头插”的思想,请看图分析:


void ReverList(pLinkList pList)//逆序链表
{
	pLinkNode cur = NULL;
	pLinkNode tmp = NULL;
	pLinkNode newHead = NULL;
	assert(pList);
	cur = pList->pHead;
	while(cur)
	{
		tmp = cur;
		cur = cur->next;
		tmp->next = newHead;
		newHead = tmp;
	}
	pList->pHead = newHead;
}
三、在指定结点位置前插入数据(无头结点)

void InsertFrontNode(pLinkNode pos,DataType x);

既然时无头结点的单向链表,我们可以参考第一题的思路。解决该问题,可以在pos位置后插入一个新的结点newnode,然后交换newnode->data和pos->data,就ok了!

分析如图:


代码如下:

void InsertFrontNode(pLinkNode pos,DataType x)//在当前结点前插入一个数据(无头结点单链表)
{
	pLinkNode newnode = BuyNode(x);
	DataType tmp = 0;
	assert(pos->next != NULL);
	newnode->next = pos->next;
	pos->next = newnode;
	tmp = pos->data;
	pos->data = newnode->data;
	newnode->data = tmp;
}

四、查找一个链表的中间结点

pLinkNode FindMiddleNode(pLinkList pList);

该问题可以利用快慢指针来解决,即:快指针每次走两步,慢指针每次走一步,那么快指针肯定先到达链表尾部的,当快指针遍历完链表停下来后,慢指针所指向的位置一定是链表的中间位置。

代码实现如下:

pLinkNode FindMiddleNode(pLinkList pList)//查找一个链表的中间节点
{
	pLinkNode fast = NULL;
	pLinkNode slow = NULL;
	assert(pList);
	fast = pList->pHead;
	slow = pList->pHead;
	while(fast && fast->next)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值