सर्चिंग (Searching) का अर्थ है किसी डेटा संग्रह में से एक विशिष्ट तत्व (लक्ष्य) को खोजना। जब हम किसी सूची में किसी विशेष संख्या, स्ट्रिंग या रिकॉर्ड को खोजना चाहते हैं तो हम सर्चिंग एल्गोरिथ्म का उपयोग करते हैं। सर्चिंग कंप्यूटर विज्ञान की सबसे सामान्य क्रियाओं में से एक है, चाहे वह फोन बुक में नाम खोजना हो, ईमेल में कोई संदेश खोजना हो या डेटाबेस में कोई रिकॉर्ड ढूंढना हो।
सर्चिंग के दो मुख्य एल्गोरिथ्म हैं: रैखिक सर्च (Linear Search) और बाइनरी सर्च (Binary Search)। रैखिक सर्च किसी भी सूची (सॉर्टेड या असॉर्टेड) पर कार्य करती है, जबकि बाइनरी सर्च के लिए सूची का सॉर्ट होना अनिवार्य है। बाइनरी सर्च रैखिक सर्च से अधिक तेज़ होती है, परंतु केवल सॉर्ट किए गए डेटा पर।
रैखिक सर्च सबसे सरल खोज विधि है। इसमें हम सूची के पहले तत्व से प्रारंभ करके क्रमशः प्रत्येक तत्व की तुलना लक्ष्य तत्व से करते हैं। जैसे ही लक्ष्य मिलता है, हम उसकी स्थिति (index) लौटाते हैं। यदि पूरी सूची में तत्व नहीं मिलता तो उचित संदेश लौटाया जाता है। यह विधि सॉर्टेड और असॉर्टेड दोनों सूचियों पर कार्य करती है।
def linear_search(lst, target):
for i in range(len(lst)):
if lst[i] == target:
return i
return -1
numbers = [10, 23, 45, 70, 11, 15]
result = linear_search(numbers, 70)
print("तत्व अनुक्रमांक:", result) # 3
result2 = linear_search(numbers, 99)
print("तत्व अनुक्रमांक:", result2) # -1 (नहीं मिला)
रैखिक सर्च का उपयोग तब उचित है जब सूची छोटी हो या असॉर्टेड हो, या जब हम केवल कुछ ही बार खोज करना चाहते हैं।
बाइनरी सर्च एक अधिक कुशल खोज विधि है जो विभाजित और जीत (Divide and Conquer) सिद्धांत पर कार्य करती है। इसके लिए सूची का सॉर्ट होना अनिवार्य है। इस विधि में हम बार-बार सूची के मध्य (middle) तत्व की तुलना लक्ष्य से करते हैं:
mid = (low + high) // 2def binary_search(lst, target):
low = 0
high = len(lst) - 1
while low <= high:
mid = (low + high) // 2
if lst[mid] == target:
return mid
elif lst[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
numbers = [2, 5, 8, 12, 16, 23, 38, 56, 72]
print(binary_search(numbers, 23)) # 5
print(binary_search(numbers, 10)) # -1
def binary_search_recursive(lst, target, low, high):
if low > high:
return -1
mid = (low + high) // 2
if lst[mid] == target:
return mid
elif lst[mid] < target:
return binary_search_recursive(lst, target, mid + 1, high)
else:
return binary_search_recursive(lst, target, low, mid - 1)
मान लीजिए सूची [2, 5, 8, 12, 16, 23, 38] है और लक्ष्य 23 है।
low=0, high=6 → mid=(0+6)//2 = 3 → lst[3]=12
12 < 23 → low=4
low=4, high=6 → mid=(4+6)//2 = 5 → lst[5]=23
23 == 23 → स्थिति 5 लौटाएँ
इस उदाहरण में केवल 2 तुलनाओं में उत्तर मिल गया, जबकि रैखिक सर्च में 6 तुलनाएँ होतीं।
| विशेषता | रैखिक सर्च | बाइनरी सर्च |
|---|---|---|
| सूची की आवश्यकता | कोई भी (सॉर्टेड/असॉर्टेड) | सॉर्टेड अनिवार्य |
| मूल सिद्धांत | क्रमिक तुलना | विभाजित और जीत |
| सबसे खराब जटिलता | O(n) | O(log n) |
| सर्वश्रेष्ठ जटिलता | O(1) | O(1) |
| कार्यान्वयन | सरल | तुलनात्मक रूप से जटिल |
| बड़े डेटा के लिए | अकुशल | कुशल |
बाइनरी सर्च बड़ी सूचियों पर रैखिक सर्च से काफी तेज़ होती है। उदाहरण के लिए, 1,000,000 तत्वों की सूची में रैखिक सर्च अधिकतम 1,000,000 तुलनाएँ करेगी, जबकि बाइनरी सर्च अधिकतम 20 तुलनाओं में (क्योंकि log₂(1000000) ≈ 20) उत्तर दे देगी।
सर्च विधि का चयन निम्नलिखित परिस्थितियों पर निर्भर करता है:
यदि सूची छोटी है तो सॉर्टिंग का अतिरिक्त खर्च उचित नहीं होता और रैखिक सर्च ही बेहतर है। लेकिन यदि सूची बड़ी है और कई खोजें करनी हैं तो एक बार सॉर्ट करके बाइनरी सर्च करना लाभदायक होता है। इस प्रकार के विश्लेषणात्मक निर्णय परीक्षा के उच्च-मूल्य वाले प्रश्नों में पूछे जाते हैं।
कोड-आउटपुट प्रश्नों को हल करने का अभ्यास:
def linear_search(lst, target):
for i in range(len(lst)):
if lst[i] == target:
return i
return -1
def binary_search(lst, target):
low, high = 0, len(lst) - 1
while low <= high:
mid = (low + high) // 2
if lst[mid] == target:
return mid
elif lst[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
numbers = [10, 20, 30, 40, 50]
print(linear_search(numbers, 30)) # 2
print(binary_search(numbers, 40)) # 3
print(binary_search(numbers, 25)) # -1
इस उदाहरण में रैखिक सर्च 30 को तीसरी स्थिति (अनुक्रमांक 2) पर पाता है। बाइनरी सर्च सॉर्टेड सूची में 40 को अनुक्रमांक 3 पर पाता है, जबकि 25 अनुपस्थित होने पर -1 लौटता है। दोनों एल्गोरिथ्मों के चरणबद्ध विश्लेषण से आउटपुट सही-सही लिखा जा सकता है।
| एल्गोरिथ्म | आवश्यकता | सिद्धांत | सबसे खराब जटिलता |
|---|---|---|---|
| रैखिक सर्च | कोई आवश्यकता नहीं | क्रमिक तुलना | O(n) |
| बाइनरी सर्च | सॉर्टेड सूची | विभाजित और जीत | O(log n) |
| चरण | क्रिया |
|---|---|
| 1 | low = 0, high = n-1 |
| 2 | mid = (low + high) // 2 |
| 3 | lst[mid] == target हो तो लौटें |
| 4 | lst[mid] < target हो तो low = mid + 1 |
| 5 | lst[mid] > target हो तो high = mid - 1 |
| 6 | low > high होने तक दोहराएँ |
(low + high) // 2 सही है; गलत कोष्ठक से फ़्लोट या गलत मान आ सकता है।for i in range क्रमिक तुलना है तो रैखिक; यदि mid और low/high है तो बाइनरी।सर्चिंग डेटा संरचना का सबसे बुनियादी और आवश्यक ऑपरेशन है। रैखिक सर्च सरल और सार्वभौमिक है परंतु बड़ी सूचियों पर धीमी है, जबकि बाइनरी सर्च केवल सॉर्टेड सूचियों पर O(log n) में अत्यधिक कुशल खोज करती है। बाइनरी सर्च "विभाजित और जीत" सिद्धांत पर मध्य तत्व की तुलना कर खोज क्षेत्र को आधा करती है। दोनों विधियों का चुनाव डेटा की प्रकृति और सूची के आकार पर निर्भर करता है। इन एल्गोरिथ्मों की चरणबद्ध समझ, जटिलता विश्लेषण और पाइथन कार्यान्वयन का अभ्यास परीक्षा में सफलता के लिए अनिवार्य है।