C++ 数据结构算法细节相关

细节

队列

这段代码实现的是二叉树的层序遍历,也就是按照树的层次,一层一层地遍历节点。下面我会为你详细解释这段代码。

  1. queue <TreeNode*> q;

    • 这是一个队列,队列中存放的是指向TreeNode的指针。
    • 队列(queue)是一种先进先出(FIFO)的数据结构。你可以把元素添加到队列的尾部,并从队列的头部移除元素。
    • 在这段代码中,队列q用于暂存每一层的节点,以便按层遍历。
    • 详细用法 :
      • q.push(element): 将元素添加到队列尾部。
      • q.front(): 返回队列头部的元素,但不移除。
      • q.pop(): 移除队列头部的元素。
      • q.empty(): 判断队列是否为空,如果为空返回true,否则返回false
      • q.size(): 返回队列中的元素数量

广度优先搜索

所谓广度优先搜索,就是从起点出发,每次都尝试访问同一层的节点,如果同一层都访问完了,再访问下一层,最后广度优先搜索找到的路径就是从起点开始的最短合法路径

lower_bound和upper_bound

lower_bound

  • 定义 : lower_bound 返回一个指向容器中第一个不小于给定值的元素的迭代器。如果所有元素都小于该值,则返回容器的末尾迭代器。

  • 用法:

    #include <iostream>
    #include <vector>
    #include <algorithm>

    int main() {
    std::vector<int> v = {1, 2, 4, 4, 5, 6};

      // 查找值为 4 的第一个不小于 4 的位置
      auto it = std::lower_bound(v.begin(), v.end(), 4);
    
      if (it != v.end()) {
          std::cout << "lower_bound: " << *it << " at index " << (it - v.begin()) << std::endl;
      } else {
          std::cout << "No element found." << std::endl;
      }
    
      return 0;
    

    }

upper_bound

  • 定义 : upper_bound 返回一个指向容器中第一个大于给定值的元素的迭代器。如果所有元素都小于或等于该值,则返回容器的末尾迭代器。

  • 用法:

    #include <iostream>
    #include <vector>
    #include <algorithm>

    int main() {
    std::vector<int> v = {1, 2, 4, 4, 5, 6};

      // 查找值 4 的第一个大于 4 的位置
      auto it = std::upper_bound(v.begin(), v.end(), 4);
    
      if (it != v.end()) {
          std::cout << "upper_bound: " << *it << " at index " << (it - v.begin()) << std::endl;
      } else {
          std::cout << "No element found." << std::endl;
      }
    
      return 0;
    

    }

关键点总结

  • lower_bound 查找值范围的开始(第一个不小于给定值 ),而 upper_bound 查找值范围的结束(第一个大于给定值)。
  • 这两个函数都使用二分查找,因此时间复杂度为 O(log n)。
  • 返回值是指向容器中的迭代器,可以使用它来得到相应的元素或计算索引。

场景示例

  • 如果你想在一个有序数组中插入一个值并保持数组的有序性,可以使用这两个函数来决定插入的位置。
  • 在处理重复元素时,lower_bound可以帮助你找到第一个匹配的元素的位置 ,而 upper_bound 可以帮助你找到最后一个匹配元素之后的位置,从而可以知道有多少重复元素。

希望这能帮助你更好地理解这两个函数的使用!如果你有任何具体的疑问或者案例,欢迎随时询问。

class Solution { public: vector<int> searchRange(vector<int>& nums, int target) {

auto left=lower_bound(nums.begin(),nums.end(),target);

auto right=upper_bound(nums.begin(),nums.end(),target);

if(left==nums.end()||*left!=target) return {-1,-1};

return {(int)(left-nums.begin()),(int)(right-nums.begin()-1)}; } };

c++ 堆和栈简介,展示下详细用法

在 C++ 中,堆(Heap)和栈(Stack)是两种重要的内存管理区域,它们的用途、特点和使用方式各不相同。以下是对堆和栈的详细介绍,包括使用示例。

一、栈(Stack)

  1. 简介
  • 存储性质: 栈是一个后进先出(LIFO)的数据结构,主要用于存储局部变量、函数参数和返回地址。
  • 内存管理: 栈的内存由编译器自动管理,分配和释放速度较快,通常在程序运行时内存分配较小。
  • 生命周期: 栈中的变量在函数调用时分配内存,函数结束时释放。
  1. 使用示例

使用栈来定义局部变量和函数参数。

#include <iostream>

void function() {
    int a = 10; // 局部变量在栈上分配
    int b = 20;
    std::cout << "Sum: " << (a + b) << std::endl; // 输出 Sum: 30
}

int main() {
    function();
    // a 和 b 的内存会在 function() 结束时自动释放
    return 0;
}
  1. 栈操作

C++ STL 的 std::stack 来实现栈的数据结构,可以执行入栈、出栈等操作:

#include <iostream>
#include <stack>

int main() {
    std::stack<int> s;

    // 入栈
    s.push(1);
    s.push(2);
    s.push(3);

    std::cout << "栈顶元素: " << s.top() << std::endl; // 输出 3

    // 出栈
    s.pop();
    std::cout << "出栈后栈顶元素: " << s.top() << std::endl; // 输出 2

    return 0;
}

二、堆(Heap)

  1. 简介
  • 存储性质: 堆是一个可以动态分配内存的区域,适用于需要动态大小的结构,比如数组或对象。
  • 内存管理 : 堆的内存需要程序员手动管理,使用 new 分配内存和 delete 释放内存,操作比较灵活但速度较慢。
  • 生命周期: 在堆上分配的变量不会自动释放,程序员需要手动管理其生命周期。
  1. 使用示例

使用堆来分配单个变量和数组。

#include <iostream>

int main() {
    // 动态分配一个整数
    int* p = new int(10); // 在堆上分配内存
    std::cout << "动态分配的整数: " << *p << std::endl; // 输出 10

    // 动态分配一个数组
    int* arr = new int[5]; // 在堆上分配一个数组
    for (int i = 0; i < 5; ++i) {
        arr[i] = i + 1; // 给数组赋值
    }
    
    std::cout << "数组内容: ";
    for (int i = 0; i < 5; ++i) {
        std::cout << arr[i] << " "; // 输出 1 2 3 4 5
    }
    std::cout << std::endl;

    // 释放内存
    delete p; // 释放单个变量的内存
    delete[] arr; // 释放数组的内存

    return 0;
}
  1. 堆与栈的对比
特性
组织结构 后进先出(LIFO) 动态大小
内存管理 编译器自动管理 程序员手动管理
分配时间 分配和释放迅速 分配和释放相对较慢
生命周期 随函数调用自动销毁 需要手动释放
大小限制 通常比较小 可以很大,受限于系统
存储类型 基本数据类型和对象 动态分配的对象、数组

结论

  • 适合用于存储局部变量和函数调用上下文,具有快速分配和释放的优点,但大小有限。
  • 适合存储不确定大小的数据,提供更多的灵活性,但需要手动管理内存,容易导致内存泄漏。

希望这些示例能帮助你更清晰地理解 C++ 中的堆和栈的用法和特点!如果你还有其他问题,请随时问我

`unordered_map<char, char>` 是 C++ STL 中的一个哈希表实现,它可以存储 `char` 类型的键和值,并且通过哈希函数实现常数时间的查找、插入和删除操作。 以下是使用 `unordered_map<char, char>` 的一些常见操作:

  1. 创建一个空的 `unordered_map` 对象: ```c++ unordered_map<char, char> pairs; ```

  2. 插入一个键值对: ```c++ pairs.insert(make_pair('a', 'b')); ``` 或者: ```c++ pairs['a'] = 'b'; ```

  3. 查找一个键对应的值: ```c++ char value = pairs['a']; ```

  4. 检查一个键是否存在: ```c++ if (pairs.find('a') != pairs.end()) { // 'a' exists in the map } ```

  5. 删除一个键值对: ```c++ pairs.erase('a'); ```

  6. 遍历 `unordered_map` 中的键值对: ```c++ for (auto& pair : pairs) { cout << pair.first << " -> " << pair.second << endl; } ``` 或者使用迭代器: ```c++ for (auto it = pairs.begin(); it != pairs.end(); ++it) { cout << it->first << " -> " << it->second << endl; } ``` 注意,在使用 `unordered_map` 时,键必须是可哈希的类型,因此在使用自定义类型作为键时,需要提供自定义的哈希函数和相等比较函数。

其他细节点

INT_MAX

class MinStack { stack<int> x_stack; stack<int> min_stack; public: MinStack() { min_stack.push(INT_MAX); } min_stack.push(INT_MAX);这句啥意思 为什么用INT_MAX

行min_stack.push(INT_MAX)初始化min_stack,最大值为INT_MAX,表示int可以容纳的最大值。 这样做是为了确保"min_stack"中总是有一个最小值。当一个新值被推到"x_stack"上时,它将与"min_stack"的顶部元素进行比较。如果新值较小,它将被推到"x_stack"和"min_stack"上。如果它不小,只更新"x_stack"。 通过初始化值为INT_MAX的min_stack,我们确保推送到min_stack上的第一个元素总是比推送到它上的任何其他值都小。这保证了"min_stack"总是至少有一个元素,即使"x_stack"是空的。

其他

相关推荐
kingking442 分钟前
剖析:基于 RDMA 的多机数据分发和接收场景
服务器·网络·c++
Prejudices3 分钟前
QCommandLineParser简介
c++·qt
多喝热水-多读书25 分钟前
Qt C++设计模式->外观模式
c++·qt·设计模式·外观模式
云兮杜康1 小时前
B树和B+树
数据结构·b树
BadCherry1 小时前
代码随想录第二十天:动态规划、斐波那契数列、爬楼梯、最小体力爬楼梯
算法·动态规划
国中之林1 小时前
【qt】QQ仿真项目1
开发语言·c++·qt·学习·设计模式·ui设计
sp_fyf_20241 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25
人工智能·深度学习·算法·语言模型·自然语言处理
"Return"1 小时前
美团2024年秋招第一场笔试算法题题解【技术】
java·c++·python·算法
DA树聚1 小时前
人工智能-机器学习-深度学习-分类与算法梳理
人工智能·深度学习·算法·机器学习·语言模型·分类·transformer
lsnm1 小时前
<刷题笔记> 力扣105/106题 使用中序+前(后)序构造二叉树
c++·笔记·b树·算法·leetcode