单链表是一种十分常见和应用广泛的数据结构,也是面试题经常会问到的一个。近期复习单链表,就将这个单链表常见的考点顺便复习了一遍。
面试题:如何最快的获取单链表的中间节点的位置?
一般思路,从头节点开始一个一个元素去遍历,而后确定链表的长度。然后又从头开始遍历单链表,并且进行计数。当计数到达单链表长度一半的位置即为单链表的中间节点。
高级思路,设置两个指针,步长分别为1和2.即为慢和快指针。当快指针指向链表的末尾时,慢结点刚好位于链表的中间位置。直接进行返回即可获得链表的中间节点。
相关示例代码如下:
//
// main.cpp
// 快速查找链表的中间节点
//
//
#include <iostream>
using namespace std;
// 算法思想,采用快慢两个指针,同时从指针的头节点开始遍历。快指针每次一动2个结点,慢指针每次移动一个结点。经过L/2次移动之后就可以完成中间节点的寻找。
struct Node{
int data;
Node* pNext;// 节点指针
};
typedef Node* LinkList;
// 头插法创建单链表
LinkList LinkedListCreatH()
{
Node *L;
L = (Node *)malloc(sizeof(Node)); //申请头结点空间
L->pNext = NULL; //初始化一个空链表
int x; //x为链表数据域中的数据
cout<<"请输入数据"<<endl;
while(scanf("%d",&x) != EOF)
{
Node *p;
p = (Node *)malloc(sizeof(Node)); //申请新的结点
p->data = x; //结点数据域赋值
p->pNext = L->pNext; //将结点插入到表头L-->|2|-->|1|-->NULL
L->pNext = p;
}
return L;
}
// 插入节点
void Insert(LinkList L,Node* node,int index){
int i = 0;
Node* ptemp = L;
while (i < index&&ptemp->pNext != NULL) {// 找到节点
ptemp = ptemp->pNext;
i++;
}
node->pNext = ptemp->pNext;
ptemp->pNext = node;
}
// 遍历单链表
void printList(LinkList L){
while (L != NULL) {
cout<<L->data<<endl;
L = L->pNext;
}
}
// 寻找单链表的中间节点
void findMinNode(LinkList L){
Node* pNode = L;
while (L != NULL&&pNode->pNext !=NULL) {
L = L->pNext;
pNode = pNode->pNext;
pNode = pNode->pNext;
}
cout<<"中间节点为:"<<L->data<<endl;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
LinkList m_list = LinkedListCreatH();
Node tempData;
tempData.data = 9;
Insert(m_list, &tempData, 4);
printList(m_list);
findMinNode(m_list);
return 0;
}
最后获得单链表的中间节点为4.当然,快慢指针还可以用于判断一个单链表是否存在环以及两个单链表是否相交等场景。