链表(特别是单链表)的定位是链表这种数据结构的一个软肋所在,定位某一个元素你就不得不通过遍历的方式获得。如果要寻找一个单链表的中间节点,普通的方法就是先遍历得到链表的长度,然后再通过长度遍历得到链表的中间节点。当然有一些链表通过一个特殊的头节点记录链表的长度的情况,可能要简单一些。 前一段时间,在看链表的归并排序的时候,就不得不面临着寻找链表中间节点的问题。这里给出一种实现,很可能是大家想不到的:
1) 使用两个指针进行遍历,快指针每次步进2,慢指针每次步进1;
2) 当快指针到达链表尾部的时候,慢指针指向的就是链表的中点。
这个算法的思想和经典问题“判定链表中是否存在环”的思想是一致的,但是如果不是有启发,真的是很难想出来。
实现源码为:
#include <stdio.h>
#include <malloc.h>
struct node {
int value;
struct node *pNext;
};
typedef struct node* PLTIDNA;
PLTIDNA pHead = NULL,pTail = NULL;
PLTIDNA FindMiddle(PLTIDNA head)
{
if(head == NULL)
{
return NULL;
}
PLTIDNA pFast,pSlow;
pFast = head;
pSlow = head;
while((pFast != NULL) && (pFast->pNext != NULL))//思考,判断条件为什么是这两样,缺一不可!!
{
pFast = pFast->pNext->pNext;
pSlow = pSlow->pNext;
}
return pSlow;
}
int main()
{
PLTIDNA p1,p2,p3,p4,p5,p6;
p1 = (PLTIDNA)malloc(sizeof(struct node));
p2 = (PLTIDNA)malloc(sizeof(struct node));
p3 = (PLTIDNA)malloc(sizeof(struct node));
p4 = (PLTIDNA)malloc(sizeof(struct node));
p5 = (PLTIDNA)malloc(sizeof(struct node));
p6 = (PLTIDNA)malloc(sizeof(struct node));
p1->value = 1;
p2->value = 2;
p3->value = 3;
p4->value = 4;
p5->value = 5;
p6->value = 6;
p1->pNext = p2;
p2->pNext = p3;
p3->pNext = p4;
p4->pNext = p5;
p5->pNext = p6;
p6->pNext = NULL;
pHead = p1;
pTail = p6;
PLTIDNA tmp = FindMiddle(pHead);
printf("%d\n",tmp->value);
return 0;
}