- 线性表反转
- 查找出奇数个元素的链表中间位置的结点
- 判断链表是否有环
1. 线性表反转
前面已有一篇文章介绍线性表反转的四种算法
2. 查找出奇数个元素的链表中间位置的结点
暴力解法:先通过一次遍历去计算链表的长度并计算出中间位置,接着再通过一次遍历去查找这个位置的数值。
巧妙解法:
利用快慢指针:定义两个指针,一个快指针,一个慢指针,其中快指针每次走两步,而慢指针每次走一步。定义两个指针fast和slow,开始时两个指针都指向链表头head,然后在每一步操作中slow向前走一步即:slow = slow->next,而fast每一步向前两步即:fast = fast->next->next。过程如下:
C 语言实现如下:
// 查找出奇数个元素的链表中间位置的结点
Node* middle_value(Node* head){
// 快指针,每次步进为2
Node* fast = head;
// 快指针,每次步进为1
Node* slow = head;
// 由于总数是奇数个,当fast跳转到最后一个时,slow刚好为中间结点
while (fast&&fast->next&&fast->next->next) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
伪代码如下:
while(fast && fast.next && fast.next.next){
fast = fast.next.next;
slow = slow.next;
}
3. 判断链表是否有环
下图便是一个循环链表
判断链表是否有环依然可以通过快慢指针去实现。
由于fast要比slow移动的快,如果有环,fast一定会先进入环,而slow后进入环。当两个指针都进入环之后,经过一定步的操作之后,二者一定能够在环上相遇,并且此时slow还没有绕环一圈,也就是说一定是在slow走完第一圈之前相遇。如果没有环,最终会结束循环
C 语言实现如下:
// 判断链表是否有环
int have_ring(Node* head)
{
// 快指针,每次步进为2
Node* fast = head;
// 快指针,每次步进为1
Node* slow = head;
// 由于总数是奇数个,当fast跳转到最后一个时,slow刚好为中间结点
while (fast&&fast->next&&fast->next->next) {
fast = fast->next->next;
slow = slow->next;
if(slow == fast) {
return 1;
}
}
return 0;
}
伪代码如下:
while(fast && fast.next && fast.next.next){
fast = fast->next->next;
slow = slow->next;
if(slow == fast)
return true;
}