[2026] C++ Search Algorithms: find, binary_search, lower_bound & equal_range
이 글의 핵심
Choose between linear find and binary search on sorted ranges; use lower_bound, upper_bound, and equal_range for positions and equal-key runs in C++.
What are search algorithms?
They locate values or predicates in ranges: linear find / find_if, or binary search algorithms on sorted ranges. Search family overview
| Algorithm | Time | Sorted? | Role |
|---|---|---|---|
find | O(n) | No | First equal value |
find_if | O(n) | No | First pred true |
binary_search | O(log n) | Yes | Existence |
lower_bound | O(log n) | Yes | First not-before value |
upper_bound | O(log n) | Yes | First after value |
equal_range | O(log n) | Yes | Subrange of equal keys |
std::find and std::find_if
Basic find
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
#include <iostream>
std::vector<int> numbers = {1, 3, 5, 7, 9, 11};
// Find specific value
auto it = std::find(numbers.begin(), numbers.end(), 7);
if (it != numbers.end()) {
std::cout << "Found: " << *it << " at index "
<< std::distance(numbers.begin(), it) << "\n";
} else {
std::cout << "Not found\n";
}
find_if with predicate
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
// Find first even number
auto it = std::find_if(numbers.begin(), numbers.end(),
[](int x) { return x % 2 == 0; });
if (it != numbers.end()) {
std::cout << "First even: " << *it << "\n"; // 2
}
find_if_not
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// Find first NOT matching predicate
auto it = std::find_if_not(numbers.begin(), numbers.end(),
[](int x) { return x < 5; });
// Finds first element >= 5
Binary search algorithms
Critical: Range must be sorted first!
std::binary_search
Returns bool indicating existence:
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
std::vector<int> sorted = {1, 3, 5, 7, 9, 11, 13};
bool found = std::binary_search(sorted.begin(), sorted.end(), 7);
// true
bool notFound = std::binary_search(sorted.begin(), sorted.end(), 6);
// false
std::lower_bound
Finds first position where element could be inserted maintaining order: 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> sorted = {1, 3, 5, 5, 5, 7, 9};
auto it = std::lower_bound(sorted.begin(), sorted.end(), 5);
// Points to first 5
std::cout << "Index: " << std::distance(sorted.begin(), it) << "\n"; // 2
std::cout << "Value: " << *it << "\n"; // 5
// For value not present
auto it2 = std::lower_bound(sorted.begin(), sorted.end(), 6);
// Points to 7 (first element >= 6)
std::upper_bound
Finds first position strictly greater than value: 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::vector<int> sorted = {1, 3, 5, 5, 5, 7, 9};
auto it = std::upper_bound(sorted.begin(), sorted.end(), 5);
// Points to 7 (first element > 5)
std::cout << "Index: " << std::distance(sorted.begin(), it) << "\n"; // 5
std::cout << "Value: " << *it << "\n"; // 7
std::equal_range
Returns pair of iterators [lower_bound, upper_bound):
std::vector<int> sorted = {1, 3, 5, 5, 5, 7, 9};
auto [first, last] = std::equal_range(sorted.begin(), sorted.end(), 5);
std::cout << "Count of 5: " << std::distance(first, last) << "\n"; // 3
// Print all occurrences
for (auto it = first; it != last; ++it) {
std::cout << *it << " ";
}
// Output: 5 5 5
Real-world examples
1. User search by ID
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
#include <string>
struct User {
int id;
std::string name;
bool operator<(const User& other) const {
return id < other.id;
}
};
std::vector<User> users = {
{1, "Alice"},
{3, "Bob"},
{5, "Charlie"},
{7, "David"}
};
// Must be sorted by id
std::sort(users.begin(), users.end());
// Binary search by id
User target{5, ""};
auto it = std::lower_bound(users.begin(), users.end(), target);
if (it != users.end() && it->id == 5) {
std::cout << "Found: " << it->name << "\n"; // Charlie
}
2. Range query
#include <algorithm>
#include <vector>
std::vector<int> timestamps = {100, 150, 200, 250, 300, 350, 400};
// Find all events between 180 and 320
auto start = std::lower_bound(timestamps.begin(), timestamps.end(), 180);
auto end = std::upper_bound(timestamps.begin(), timestamps.end(), 320);
std::cout << "Events in range: ";
for (auto it = start; it != end; ++it) {
std::cout << *it << " ";
}
// Output: 200 250 300
3. Insert maintaining sorted order
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
std::vector<int> sorted = {1, 3, 5, 7, 9};
int newValue = 6;
auto pos = std::lower_bound(sorted.begin(), sorted.end(), newValue);
sorted.insert(pos, newValue);
// sorted is now {1, 3, 5, 6, 7, 9}
4. Finding first/last occurrence
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> data = {1, 2, 2, 2, 3, 4};
// First occurrence of 2
auto first = std::lower_bound(data.begin(), data.end(), 2);
// Last occurrence of 2
auto last = std::upper_bound(data.begin(), data.end(), 2);
--last; // Move back to last 2
std::cout << "First 2 at index: " << std::distance(data.begin(), first) << "\n"; // 1
std::cout << "Last 2 at index: " << std::distance(data.begin(), last) << "\n"; // 3
Performance comparison
Benchmark (1M sorted elements, 10K searches):
| Algorithm | Time (ms) | Notes |
|---|---|---|
std::find | 450 | Linear scan |
std::binary_search | 2 | O(log n) |
std::lower_bound | 2 | O(log n) |
std::upper_bound | 2 | O(log n) |
std::equal_range | 3 | Two binary searches |
| Key insight: Binary search is 225× faster for large sorted data. |
Common mistakes
Mistake 1: Binary search on unsorted data
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::vector<int> unsorted = {5, 2, 8, 1, 9};
// ❌ Undefined behavior!
bool found = std::binary_search(unsorted.begin(), unsorted.end(), 5);
// ✅ Sort first
std::sort(unsorted.begin(), unsorted.end());
bool found = std::binary_search(unsorted.begin(), unsorted.end(), 5);
Mistake 2: Not checking iterator validity
아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> data = {1, 2, 3};
auto it = std::find(data.begin(), data.end(), 5);
// ❌ Dereferencing end()
std::cout << *it << "\n"; // Undefined behavior!
// ✅ Check first
if (it != data.end()) {
std::cout << *it << "\n";
}
Mistake 3: Using wrong bound
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::vector<int> sorted = {1, 3, 5, 5, 5, 7, 9};
// Want to insert after all 5s
auto it = std::lower_bound(sorted.begin(), sorted.end(), 5); // ❌ Wrong!
// This gives position of first 5
auto it = std::upper_bound(sorted.begin(), sorted.end(), 5); // ✅ Correct
// This gives position after last 5
Mistake 4: Iterator invalidation
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> data = {1, 2, 3, 4, 5};
auto it = std::find(data.begin(), data.end(), 3);
data.push_back(6); // May reallocate!
// ❌ it may be invalid now
std::cout << *it << "\n"; // Undefined behavior
// ✅ Store index or re-search
size_t index = std::distance(data.begin(), it);
data.push_back(6);
std::cout << data[index] << "\n";
Advanced patterns
1. Custom comparator
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <algorithm>
#include <vector>
#include <string>
struct Person {
std::string name;
int age;
};
std::vector<Person> people = {
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35}
};
// Sort by age
std::sort(people.begin(), people.end(),
[](const Person& a, const Person& b) {
return a.age < b.age;
});
// Binary search by age (must use same comparator!)
Person target{"", 30};
auto it = std::lower_bound(people.begin(), people.end(), target,
[](const Person& a, const Person& b) {
return a.age < b.age;
});
if (it != people.end() && it->age == 30) {
std::cout << "Found: " << it->name << "\n"; // Bob
}
2. Count occurrences in sorted range
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::vector<int> data = {1, 2, 2, 2, 3, 4, 4, 5};
int value = 2;
auto range = std::equal_range(data.begin(), data.end(), value);
size_t count = std::distance(range.first, range.second);
std::cout << "Count of " << value << ": " << count << "\n"; // 3
3. Closest element
다음은 cpp를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
std::vector<int> sorted = {10, 20, 30, 40, 50};
int target = 27;
auto it = std::lower_bound(sorted.begin(), sorted.end(), target);
// Check both it and it-1 for closest
int closest;
if (it == sorted.begin()) {
closest = *it;
} else if (it == sorted.end()) {
closest = *(it - 1);
} else {
int before = *(it - 1);
int after = *it;
closest = (target - before < after - target) ? before : after;
}
std::cout << "Closest to " << target << ": " << closest << "\n"; // 30
Choosing the right algorithm
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TD
A[Need to search?]
B{Data sorted?}
C{Need position?}
D[std::find]
E{Existence only?}
F[std::binary_search]
G{Need range?}
H[std::equal_range]
I[std::lower_bound]
A --> B
B -->|No| C
C -->|No| D
C -->|Yes| D
B -->|Yes| E
E -->|Yes| F
E -->|No| G
G -->|Yes| H
G -->|No| I
Compiler support
| Compiler | find/find_if | Binary search | equal_range |
|---|---|---|---|
| GCC | All versions | All versions | All versions |
| Clang | All versions | All versions | All versions |
| MSVC | All versions | All versions | All versions |
Related posts
Keywords
std::find, binary_search, lower_bound, upper_bound, equal_range, STL, binary search, C++, algorithm, search