STL中的二分查找——lower_bound 、upper_bound 、binary_search
二分查找很简单,原理就不说了。STL中关于二分查找的函数有三个lower_bound 、upper_bound 、binary_search 。这三个函数都运用于有序区间(当然这也是运用二分查找的前提)。
其中如果寻找的value存在,那么lower_bound返回一个迭代器指向其中第一个这个元素。upper_bound返回一个迭代器指向其中最后一个这个元素的下一个位置(明确点说就是返回在不破坏顺序的情况下,可插入value的最后一个位置)。如果寻找的value不存在,那么lower_bound和upper_bound都返回“假设这样的元素存在时应该出现的位置”。要指出的是lower_bound和upper_bound在源码中只是变换了if—else语句判定条件的顺序,就产生了最终迭代器位置不同的效果。
binary_search试图在已排序的[first,last)中寻找元素value,若存在就返回true,若不存在则返回false。返回单纯的布尔值也许不能满足需求,而lower_bound、upper_bound能提供额外的信息。事实上由源码可知binary_search便是利用lower_bound求出元素应该出现的位置,然后再比较该位置 的值与value的值。该函数有两个版本一个是operator< ,另外一个是利用仿函数comp进行比较。
具体分析见源码:
1 //这是forward版本 2 template <class ForwardIterator, class T> 3 inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, 4 const T& value) { 5 return __lower_bound(first, last, value, distance_type(first), 6 iterator_category(first)); 7 } 8 9 // 这是版本一的 forward_iterator 版本 10 template <class ForwardIterator, class T, class Distance> 11 ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, 12 const T& value, Distance*, 13 forward_iterator_tag) { 14 Distance len = 0; 15 distance(first, last, len); // 求取整个范围的长度,ForwardIterator没有-n操作 16 Distance half; 17 ForwardIterator middle; 18 19 while (len > 0) { //为了跳出循环,而定义了len,如果用while(true) 然后每次判定长度在break,也行,不过没这个好 20 half = len >> 1; // 除以2,注意这种移位写法,不需编译器进行优化 21 middle = first; // 这两行令middle 指向中间位置 22 advance(middle, half); //ForwardIterator没有+n的操作 23 if (*middle < value) { // 如果中间位置的元素值 < 标的值,value在后半区间 24 first = middle; // 这两行令 first 指向 middle 的下一位置 25 ++first; 26 len = len - half - 1; // 修正 len,回头测试循环条件 27 } 28 else // 注意如果是相等的话,那么执行的是else语句,在前半部分找 29 // 与opper_bound进行比较 30 len = half; // 修正 len,回头测试循环条件 31 } 32 return first; 33 } 34 // 这是带comp反函数的 forward_iterator 版本 35 template <class ForwardIterator, class T, class Compare, class Distance> 36 ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, 37 const T& value, Compare comp, Distance*, 38 forward_iterator_tag) { 39 Distance len = 0; 40 distance(first, last, len); 41 Distance half; 42 ForwardIterator middle; 43 44 while (len > 0) { 45 half = len >> 1; 46 middle = first; 47 advance(middle, half); 48 if (comp(*middle, value)) { 49 first = middle; 50 ++first; 51 len = len - half - 1; 52 } 53 else 54 len = half; 55 } 56 return first; 57 } 58 59 // 这是random_access_iterator版本 60 template <class ForwardIterator, class T, class Compare> 61 inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, 62 const T& value, Compare comp) { 63 return __lower_bound(first, last, value, comp, distance_type(first), 64 iterator_category(first)); 65 } 66 67 // 这是版本一的 random_access_iterator 版本 68 template <class RandomAccessIterator, class T, class Distance> 69 RandomAccessIterator __lower_bound(RandomAccessIterator first, 70 RandomAccessIterator last, const T& value, 71 Distance*, random_access_iterator_tag) { 72 Distance len = last - first; //求取整个范围的长度,与ForwarIterator版本进行比较 73 Distance half; 74 RandomAccessIterator middle; 75 76 while (len > 0) { 77 half = len >> 1; 78 middle = first + half; 79 if (*middle < value) { 80 first = middle + 1; 81 len = len - half - 1; //修正 len,回头测试循环条件,RamdonAccessIterator版本 82 } 83 else 84 len = half; 85 } 86 return first; 87 } 88 89 90 91 //这是带comp仿函数 random_access_iterator 版本 92 template <class RandomAccessIterator, class T, class Compare, class Distance> 93 RandomAccessIterator __lower_bound(RandomAccessIterator first, 94 RandomAccessIterator last, 95 const T& value, Compare comp, Distance*, 96 random_access_iterator_tag) { 97 Distance len = last - first; 98 Distance half; 99 RandomAccessIterator middle; 100 101 while (len > 0) { 102 half = len >> 1; 103 middle = first + half; 104 if (comp(*middle, value)) { 105 first = middle + 1; 106 len = len - half - 1; 107 } 108 else 109 len = half; 110 } 111 return first; 112 } 113 114 // 这是forward_iterator版本 115 template <class ForwardIterator, class T> 116 inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, 117 const T& value) { 118 return __upper_bound(first, last, value, distance_type(first), 119 iterator_category(first)); 120 } 121 122 // 这是版本一的 forward_iterator 版本 123 template <class ForwardIterator, class T, class Distance> 124 ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, 125 const T& value, Distance*, 126 forward_iterator_tag) { 127 Distance len = 0; 128 distance(first, last, len); 129 Distance half; 130 ForwardIterator middle; 131 132 while (len > 0) { 133 half = len >> 1; 134 middle = first; 135 advance(middle, half); 136 if (value < *middle) // 如果中间位置的元素值大于标的值,证明在前半部分 137 len = half; // 修正len 138 else { // 注意如果元素值相等的话,那么是在后半部分找 139 // 与lower_bound进行比较 140 first = middle; // 在下半部分,令first指向middle的下一个位置 141 ++first; 142 len = len - half - 1; // 修正 len 143 } 144 } 145 return first; 146 } 147 148 // 这是版本一的 random_access_iterator 版本 149 template <class RandomAccessIterator, class T, class Distance> 150 RandomAccessIterator __upper_bound(RandomAccessIterator first, 151 RandomAccessIterator last, const T& value, 152 Distance*, random_access_iterator_tag) { 153 Distance len = last - first; 154 Distance half; 155 RandomAccessIterator middle; 156 157 while (len > 0) { 158 half = len >> 1; 159 middle = first + half; 160 if (value < *middle) 161 len = half; 162 else { 163 first = middle + 1; 164 len = len - half - 1; 165 } 166 } 167 return first; 168 } 169 170 // 这是带comp的版本 171 template <class ForwardIterator, class T, class Compare> 172 inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, 173 const T& value, Compare comp) { 174 return __upper_bound(first, last, value, comp, distance_type(first), 175 iterator_category(first)); 176 } 177 178 // 这是带comp的 forward_iterator 版本 179 template <class ForwardIterator, class T, class Compare, class Distance> 180 ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, 181 const T& value, Compare comp, Distance*, 182 forward_iterator_tag) { 183 Distance len = 0; 184 distance(first, last, len); 185 Distance half; 186 ForwardIterator middle; 187 188 while (len > 0) { 189 half = len >> 1; 190 middle = first; 191 advance(middle, half); 192 if (comp(value, *middle)) 193 len = half; 194 else { 195 first = middle; 196 ++first; 197 len = len - half - 1; 198 } 199 } 200 return first; 201 } 202 203 // 这是带comp的 random_access_iterator 版本 204 template <class RandomAccessIterator, class T, class Compare, class Distance> 205 RandomAccessIterator __upper_bound(RandomAccessIterator first, 206 RandomAccessIterator last, 207 const T& value, Compare comp, Distance*, 208 random_access_iterator_tag) { 209 Distance len = last - first; 210 Distance half; 211 RandomAccessIterator middle; 212 213 while (len > 0) { 214 half = len >> 1; 215 middle = first + half; 216 if (comp(value, *middle)) 217 len = half; 218 else { 219 first = middle + 1; 220 len = len - half - 1; 221 } 222 } 223 return first; 224 } 225 226 // 版本一 227 template <class ForwardIterator, class T> 228 bool binary_search(ForwardIterator first, ForwardIterator last, 229 const T& value) { 230 ForwardIterator i = lower_bound(first, last, value); 231 //这里的实现就是调用的lower_bound ,并且如果元素不存在那么lower_bound指向的元素一定是 232 //operator < 为ture的地方。 233 return i != last && !(value < *i); 234 } 235 236 // 版本二 237 template <class ForwardIterator, class T, class Compare> 238 bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, 239 Compare comp) { 240 ForwardIterator i = lower_bound(first, last, value, comp); 241 return i != last && !comp(value, *i); 242 }