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

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

贺志国
2023.5.25

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

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

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

以下是示例代码upper_bound.cpp

#include 
#include 
#include 
#include 

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

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

    if (!(value < *iter)) {
      first = ++iter;
      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 first element that is greater than i
    auto upper = std::upper_bound(data.begin(), data.end(), i);
    auto custom_upper = CustomUpperBound(data.begin(), data.end(), i);
    if (upper != custom_upper) {
      std::cerr << "CustomUpperBound implementation is wrong. \n";
    }
    std::cout << i << " < ";
    upper != data.end() ? std::cout << *upper << " at index "
                                    << std::distance(data.begin(), upper)
                        : 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 first element that is greater than target_val
    auto upper = std::upper_bound(prices.begin(), prices.end(), target_val);
    auto custom_upper =
        CustomUpperBound(prices.begin(), prices.end(), target_val);
    if (upper != custom_upper) {
      std::cerr << "CustomUpperBound implementation is wrong. \n";
    }
    std::cout << target_val << " < ";
    upper != prices.end() ? std::cout << *upper << " at index "
                                      << std::distance(prices.begin(), upper)
                          : std::cout << " not found";
    std::cout << '\n';
  }

  return 0;
}

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

cmake_minimum_required(VERSION 3.0.0)
project(upper_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

运行结果如下所示:

./upper_bound 
0 < 1 at index 0
1 < 2 at index 1
2 < 4 at index 2
3 < 4 at index 2
4 < 5 at index 3
5 < 6 at index 5
6 <  not found
83.2 < 100 at index 0
102.5 < 107.3 at index 4
110.2 <  not found

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

gdb -q ./upper_bound

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

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

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