📜  在单链表上的二进制搜索

📅  最后修改于: 2021-04-29 17:08:19             🧑  作者: Mango

给定一个单链表和一个密钥,请使用二进制搜索方法查找密钥。
为了执行基于分而治之算法的二分搜索,中间元素的确定很重要。对于数组,二进制搜索通常是快速而有效的,因为访问两个给定索引之间的中间索引既简单又快速(时间复杂度O(1))。但是,单链接列表的内存分配是动态且不连续的,这使得查找中间元素变得困难。一种方法可能是使用跳过列表,一种可能是使用一个指针遍历链接列表。

先决条件:找到链表的中间部分。

注意:下面提供的方法和实现旨在说明如何在链接列表上实现二进制搜索。该实现需要O(n)时间。

方法 :

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

在主函数,函数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


输出:
Present

时间复杂度: O(n)