C++标准库算法std::lower_bound示例

C++标准库算法std::lower_bound示例

贺志国
2023.5.25

C++标准库算法std::lower_bound使用二分查找算法在已按升序排列的序列中返回指向第一个不小于给定值的元素的迭代器(std::upper_bound返回指向第一个大于给定值的元素的迭代器,注意二者的细微差别),例如:已按升序排列的序列为{100.0, 101.5, 102.5, 102.5, 107.3},第一个不小于83.2的元素为100.0,其索引值为0(起始序号为0),第一个不小于102.5的元素为102.5,其索引值为2,不小于110.2的值不存在。
std::lower_bound的声明如下:

// T类型提供大小比较语义,例如double
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );

// T类型不提供大小比较语义,例如自定义类Person,因此需要提供一个自定义的
// Compare comp用于比较数据值的大小
template< class ForwardIt, class T, class Compare >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                                 const T& value, Compare comp );

以下是示例代码ower_bound.cpp

#include 
#include 
#include 
#include 

template <class ForwardIt, class T>
ForwardIt CustomLowerBound(ForwardIt first, ForwardIt last, const T& value) {
  ForwardIt it;
  typename std::iterator_traits<ForwardIt>::difference_type count, step;
  count = std::distance(first, last);

  while (count > 0) {
    it = first;
    step = count / 2;
    std::advance(it, step);

    if (*it < value) {
      first = ++it;
      count -= step + 1;
    } else
      count = step;
  }

  return first;
}

int main(int, char**) {
  std::vector<int> data = {1, 2, 4, 5, 5, 6};
  for (int i = 0; i < 7; ++i) {
    // Search for first element x such that i ≤ x
    auto lower = std::lower_bound(data.begin(), data.end(), i);
    auto custom_lower = CustomLowerBound(data.begin(), data.end(), i);
    if (lower != custom_lower) {
      std::cerr << "CustomLowerBound implementation is wrong. \n";
    }
    std::cout << i << " ≤ ";
    lower != data.end() ? std::cout << *lower << " at index "
                                    << std::distance(data.begin(), lower)
                        : std::cout << " not found";
    std::cout << '\n';
  }

  std::vector<double> prices = {100.0, 101.5, 102.5, 102.5, 107.3};
  for (double target_val : {83.2, 102.5, 110.2}) {
    // Search for first element x such that target_val ≤ x
    auto lower = std::lower_bound(prices.begin(), prices.end(), target_val);
    auto custom_lower =
        CustomLowerBound(prices.begin(), prices.end(), target_val);
    if (lower != custom_lower) {
      std::cerr << "CustomLowerBound implementation is wrong. \n";
    }

    std::cout << target_val << " ≤ ";
    lower != prices.end() ? std::cout << *lower << " at index "
                                      << std::distance(prices.begin(), lower)
                          : std::cout << " not found";
    std::cout << '\n';
  }

  return 0;
}

CMake编译文件CMakeLists.txt的内容如下:

cmake_minimum_required(VERSION 3.0.0)
project(lower_bound VERSION 0.1.0)

include(CTest)
enable_testing()

# If the debug option is not given, the program will not have debugging information.
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")

add_executable(${PROJECT_NAME} ${PROJECT_NAME}.cpp)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

VSCode的调试配置文件内容.vscode/launch.json如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "cpp_gdb_launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/${workspaceFolderBasename}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable neat printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            // "preLaunchTask": "cpp_build_task",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}

编译命令如下:

mkdir build && cd build && cmake .. && make

如果build子目录已存在,则执行:

cd build && cmake .. && make

如果已在build子目录,则执行:

cmake .. && make

运行结果如下所示:

./lower_bound 
01 at index 0
11 at index 0
22 at index 1
34 at index 2
44 at index 2
55 at index 3
66 at index 5
83.2100 at index 0
102.5102.5 at index 2
110.2 ≤  not found

使用GDB调试的命令如下所示:

gdb -q ./lower_bound

调试截图如下所示:
C++标准库算法std::lower_bound示例_第1张图片

启动VSCode的调试界面如下图(调试快捷键与Visual Studio相同):
C++标准库算法std::lower_bound示例_第2张图片

你可能感兴趣的:(c++,算法,开发语言)