1. 程式人生 > >六、判斷兩個單向連結串列是否相交

六、判斷兩個單向連結串列是否相交

判斷兩個單向連結串列是否相交,有兩種情況,一種是兩個不帶環的單向連結串列相交,一種是兩個帶環的單向連結串列相交。

情況1:兩個不帶環的單向連結串列相交

/*判斷兩個不帶環的單向連結串列是否相交。時間複雜度O(n),空間複雜度O(1)*/
/*思路:如果兩個沒有環的連結串列相交於某一節點,那麼在這個節點之後的*/
/*所有節點都是兩個連結串列共有的,如果它們相交,則最後一個節點一定是共有的*/
int is_intersect(struct list_head *head_one, struct list_head *head_two)
{
    if (!head_one || !head_two)
        return -1;

    /*先找到連結串列1的尾節點*/
    while (head_one->next != NULL)
        head_one = head_one->next;

    /*找連結串列2的尾節點並比較*/
    while (head_two->next != NULL) {
        head_two = head_two->next;

        /*判斷尾節點是否相同*/
        if (head_one == head_two)
            return 1;/*相交*/
    }

    return 0;/*相交*/
}

情況2:兩個帶環的單向連結串列相交

/*判斷兩個帶環的單向連結串列是否相交*/
/*思路:如果有環且兩個連結串列相交,則兩個連結串列都有共同一個環,即環上的任意一個節點都存在*/
/*於兩個連結串列上。因此,就可以判斷一連結串列上倆指標相遇的那個節點,在不在另一條連結串列上。*/
int is_intersect(struct list_head *head_one, struct list_head *head_two)
{
    struct list_head *slow = head_one;
    struct list_head *fast = head_one;
    struct list_head *temp = NULL;

    if (!head_one || !head_one->next ||
        !head_two || !head_two->next)
        return -1;
    /*判斷連結串列1有沒有環,並得到連結串列1的環內節點(兩指標相遇的那個節點)*/
    while (head_one != NULL || head_one->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast) {/*有環*/
            temp = slow;   /*獲取連結串列1的環內節點*/
            break;
        }
    }

    if (slow != fast)/*連結串列1沒有環*/
        return -1;

    /*判斷連結串列2有沒有環*/
    slow = head_two;
    fast = head_two;
    while (head_two != NULL || head_two->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast)/*有環*/
            break;
    }

    if (slow != fast)/*連結串列2沒有環*/
        return -1;

    /*這裡的slow、fast都為連結串列2的環內節點,現在遍歷這個環,看連結串列1的環內節點temp在不在這個環上*/
    slow = slow->next;
    while (slow != fast) {
        if (slow == temp)
            return 1;/*相交*/
        slow = slow->next;
    }

    return 0;/*不相交*/
}