📜  单向链表上的二分搜索

📅  最后修改于: 2021-09-16 11:06:12             🧑  作者: Mango

给定一个单向链表和一个键,使用二分搜索方法找到键。
为了执行基于分而治之算法的二分搜索,中间元素的确定很重要。二分搜索通常对数组快速有效,因为访问两个给定索引之间的中间索引既简单又快速(时间复杂度为 O(1))。但是单向链表的内存分配是动态的且不连续的,这使得查找中间元素变得困难。一种方法可能是使用跳过列表,一种可能是使用一个指针遍历链表。
先决条件:找到链表的中间。
注意:下面提供的方法和实现是为了展示如何在链表上实现二分搜索。实现需要 O(n) 时间。
方法 :

  • 这里给出了起始节点(设置为列表的头部)和最后一个节点(最初设置为 NULL)。
  • Middle 是使用两个指针的方法计算的。
  • 如果中间的数据与搜索所需的值匹配,则返回它。
  • 否则如果中间的数据<值,移动到上半部分(设置开始到中间的下一个)。
  • 否则转到下半部分(设置最后到中间)。
  • 出来的条件是,找到元素或遍历整个列表。当遍历整个列表时,last 指向开始,即 last -> next == start。

在 main函数,函数InsertAtHead在链表的开头插入值。插入这样的值(为了简单起见),以便对创建的列表进行排序。
例子 :

Input : Enter value to search : 7
Output : Found

Input : Enter value to search : 12
Output : Not Found
C++
// CPP code to implement binary search
// on Singly Linked List
#include
#include
 
struct Node
{
    int data;
    struct Node* next;
};
 
Node *newNode(int x)
{
    struct Node* temp = new Node;
    temp->data = x;
    temp->next = NULL;
    return temp;
}
 
// function to find out middle element
struct Node* middle(Node* start, Node* last)
{
    if (start == NULL)
        return NULL;
 
    struct Node* slow = start;
    struct Node* fast = start -> next;
 
    while (fast != last)
    {
        fast = fast -> next;
        if (fast != last)
        {
            slow = slow -> next;
            fast = fast -> next;
        }
    }
 
    return slow;
}
 
// Function for implementing the Binary
// Search on linked list
struct Node* binarySearch(Node *head, int value)
{
    struct Node* start = head;
    struct Node* last = NULL;
 
    do
    {
        // Find middle
        Node* mid = middle(start, last);
 
        // If middle is empty
        if (mid == NULL)
            return NULL;
 
        // If value is present at middle
        if (mid -> data == value)
            return mid;
 
        // If value is more than mid
        else if (mid -> data < value)
            start = mid -> next;
 
        // If the value is less than mid.
        else
            last = mid;
 
    } while (last == NULL ||
             last != start);
 
    // value not present
    return NULL;
}
 
// Driver Code
int main()
{
    Node *head = newNode(1);
    head->next = newNode(4);
    head->next->next = newNode(7);
    head->next->next->next = newNode(8);
    head->next->next->next->next = newNode(9);
    head->next->next->next->next->next = newNode(10);
    int value = 7;
    if (binarySearch(head, value) == NULL)
        printf("Value not present\n");
    else
        printf("Present");
    return 0;
}


Java
// Java code to implement binary search
// on Singly Linked List
 
// Node Class
class Node
{
    int data;
    Node next;
 
    // Constructor to create a new node
    Node(int d)
    {
        data = d;
        next = null;
    }
}
 
class BinarySearch
{
    // function to insert a node at the beginning
    // of the Singaly Linked List
    static Node push(Node head, int data)
    {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
        return head;
    }
 
    // Function to find middle element
    // using Fast and Slow pointers
    static Node middleNode(Node start, Node last)
    {
        if (start == null)
            return null;
 
        Node slow = start;
        Node fast = start.next;
 
        while (fast != last)
        {
            fast = fast.next;
            if (fast != last)
            {
                slow = slow.next;
                fast = fast.next;
            }
        }
        return slow;
    }
 
    // function to insert a node at the beginning
    // of the Singly Linked List
    static Node binarySearch(Node head, int value)
    {
        Node start = head;
        Node last = null;
 
        do
        {
            // Find Middle
            Node mid = middleNode(start, last);
 
            // If middle is empty
            if (mid == null)
                return null;
 
            // If value is present at middle
            if (mid.data == value)
                return mid;
 
            // If value is less than mid
            else if (mid.data > value)
            {
                start = mid.next;
            }
 
            // If the value is more than mid.
            else
                last = mid;
        } while (last == null || last != start);
 
        // value not present
        return null;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        Node head = null;
 
        // Using push() function to
        // convert singly linked list
        // 10 -> 9 -> 8 -> 7 -> 4 -> 1
        head = push(head, 1);
        head = push(head, 4);
        head = push(head, 7);
        head = push(head, 8);
        head = push(head, 9);
        head = push(head, 10);
        int value = 7;
 
        if (binarySearch(head, value) == null)
        {
            System.out.println("Value not present");
        }
        else
        {
            System.out.println("Present");
        }
    }
}
 
// This code is contributed by Vivekkumar Singh


Python
# Python code to implement binary search
# on Singly Linked List
 
# Link list node
class Node:
     
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prev = None
         
def newNode(x):
 
    temp = Node(0)
    temp.data = x
    temp.next = None
    return temp
 
# function to find out middle element
def middle(start, last):
 
    if (start == None):
        return None
 
    slow = start
    fast = start . next
 
    while (fast != last):
     
        fast = fast . next
        if (fast != last):
         
            slow = slow . next
            fast = fast . next
         
    return slow
 
# Function for implementing the Binary
# Search on linked list
def binarySearch(head,value):
 
    start = head
    last = None
 
    while True :
     
        # Find middle
        mid = middle(start, last)
 
        # If middle is empty
        if (mid == None):
            return None
 
        # If value is present at middle
        if (mid . data == value):
            return mid
 
        # If value is more than mid
        elif (mid . data < value):
            start = mid . next
 
        # If the value is less than mid.
        else:
            last = mid
 
        if not (last == None or last != start):
            break
 
    # value not present
    return None
 
# Driver Code
 
head = newNode(1)
head.next = newNode(4)
head.next.next = newNode(7)
head.next.next.next = newNode(8)
head.next.next.next.next = newNode(9)
head.next.next.next.next.next = newNode(10)
value = 7
if (binarySearch(head, value) == None):
    print("Value not present\n")
else:
    print("Present")
     
# This code is contributed by Arnab Kundu


C#
// C# code to implement binary search
// on Singly Linked List
 
using System;
 
// Node Class
public class Node
{
    public int data;
    public Node next;
 
    // Constructor to create a new node
    public Node(int d)
    {
        data = d;
        next = null;
    }
}
 
class BinarySearch
{
    // function to insert a node at the beginning
    // of the Singaly Linked List
    static Node push(Node head, int data)
    {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
        return head;
    }
 
    // Function to find middle element
    // using Fast and Slow pointers
    static Node middleNode(Node start, Node last)
    {
        if (start == null)
            return null;
 
        Node slow = start;
        Node fast = start.next;
 
        while (fast != last)
        {
            fast = fast.next;
            if (fast != last)
            {
                slow = slow.next;
                fast = fast.next;
            }
        }
        return slow;
    }
 
    // function to insert a node at the beginning
    // of the Singly Linked List
    static Node binarySearch(Node head, int value)
    {
        Node start = head;
        Node last = null;
 
        do
        {
            // Find Middle
            Node mid = middleNode(start, last);
 
            // If middle is empty
            if (mid == null)
                return null;
 
            // If value is present at middle
            if (mid.data == value)
                return mid;
 
            // If value is less than mid
            else if (mid.data > value)
            {
                start = mid.next;
            }
 
            // If the value is more than mid.
            else
                last = mid;
        } while (last == null || last != start);
 
        // value not present
        return null;
    }
 
    // Driver Code
    public static void Main(String []args)
    {
        Node head = null;
 
        // Using push() function to
        // convert singly linked list
        // 10 -> 9 -> 8 -> 7 -> 4 -> 1
        head = push(head, 1);
        head = push(head, 4);
        head = push(head, 7);
        head = push(head, 8);
        head = push(head, 9);
        head = push(head, 10);
        int value = 7;
 
        if (binarySearch(head, value) == null)
        {
            Console.WriteLine("Value not present");
        }
        else
        {
            Console.WriteLine("Present");
        }
    }
}
 
// This code is contributed by Arnab Kundu


Javascript


输出:
Present

时间复杂度: O(N)
辅助空间: O(1)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程