只遍历链表一次求链表中间结点

Posted ssopp24

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了只遍历链表一次求链表中间结点相关的知识,希望对你有一定的参考价值。


ListNode* MidNode( ListNode* pHead )

	if ( NULL == pHead )
		return NULL;
	else if ( NULL == pHead->m_pNext )
		return pHead;
	else if ( NULL == pHead->m_pNext->m_pNext )
		return pHead;

	ListNode* pFast = pHead;
	ListNode* pSlow = pHead;

	while ( NULL != pFast->m_pNext/*最后一个结点*/ )
		if ( NULL == pFast->m_pNext->m_pNext )//pFast->m_pNext不可能为NULL. 所以我们不必担心NULL->m_pNext情况发生
			break;

		pFast = pFast->m_pNext->m_pNext;
		pSlow = pSlow->m_pNext;
	

	return pSlow;



测试代码:

//求链表的中间节点,链表中元素个数为奇数返回中间节点,偶数返回中间结点中任一个(这里返回第一个)
#include <iostream>
using namespace std;


struct ListNode
	int m_nKey;
	ListNode* m_pNext;

	ListNode( ListNode* pNext, int value )
		: m_pNext( pNext )
		, m_nKey( value )
	
;


ListNode* MidNode( ListNode* pHead );
void push_back( ListNode** pHead, int value );


int main( )

	ListNode* pHead = NULL;
	//push_back( &pHead, 1 );
	//push_back( &pHead, 2 );
	//push_back( &pHead, 3 );
	
	//push_back( &pHead, 1 );

	//push_back( &pHead, 1 );
	//push_back( &pHead, 2 );
	
	push_back( &pHead, 1 );
	push_back( &pHead, 2 );
	push_back( &pHead, 3 );
	push_back( &pHead, 4 );


	cout << MidNode( pHead )->m_nKey << endl;

	return 0;



void push_back( ListNode** pHead, int value )

	if ( NULL == pHead )
		return;

	ListNode* pNewNode = new ListNode( NULL, value );

	if ( NULL == *pHead )
		*pHead = pNewNode;
		return;
	

	ListNode* pNode = *pHead;

	while ( NULL != pNode->m_pNext )
		pNode = pNode->m_pNext;

	pNode->m_pNext = pNewNode;


//我们不用那种 遍历一遍得出链表个数,再找中间结点的需要遍历链表两次的方法,我们用只遍历链表一次就得出中间结点方法
//我们利用两个指针,pFast和pSlow:快指针一次走两步,慢指针一次走一步。
//当快指针到达链表结尾或链表倒数第二个结点时(分别对应链表结点个数为奇数和偶数),慢指针到达链表最中间(奇数)或中间两个结点的前一个结点(偶数)
//我们把 链表为空, 链表只有一个结点,和链表有两个结点的情况单独拿出来处理.
ListNode* MidNode( ListNode* pHead )

	if ( NULL == pHead )
		return NULL;
	else if ( NULL == pHead->m_pNext )
		return pHead;
	else if ( NULL == pHead->m_pNext->m_pNext )
		return pHead;

	ListNode* pFast = pHead;
	ListNode* pSlow = pHead;

	while ( NULL != pFast->m_pNext/*最后一个结点*/ )
		if ( NULL == pFast->m_pNext->m_pNext )//pFast->m_pNext不可能为NULL. 所以我们不必担心NULL->m_pNext情况发生
			break;

		pFast = pFast->m_pNext->m_pNext;
		pSlow = pSlow->m_pNext;
	

	return pSlow;



以上是关于只遍历链表一次求链表中间结点的主要内容,如果未能解决你的问题,请参考以下文章

头插法链表的基本操作:创建空链表,插入结点,遍历链表,求链表长度,查找结点,删除结点

各种求链表中间节点

各种求链表中间节点

算法热门:链表中倒数第k个结点(剑指Offer 22)

5种常见的链表基本操作

力扣92反转链表中指定长度的结点(中等)