线性表算法相关案例

  1. 线性表反转
  2. 查找出奇数个元素的链表中间位置的结点
  3. 判断链表是否有环

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;
}

你可能感兴趣的:(线性表算法相关案例)