数据结构知识点

【1】栈(stack)

C++ 标准库提供了 std::stack 模板类,用于实现栈的功能。std::stack 是基于其他容器(如 std::vector、std::deque 或 std::list)实现的适配器类。

std::stack 可以使用不同的底层容器来实现,如 std::vector、std::deque 或 std::list。默认情况下,std::stack 使用 std::deque 作为底层容器,但你可以指定其他容器。

栈是一种后进先出(LIFO, Last In First Out)的数据结构,即最后添加的元素将最先被移除。

要使用 std::stack,需要包含 头文件

#include 

1. 声明栈

std::stack s;  // 声明一个存储 int 类型的栈

std::stack:模板类,T 是栈中存储的元素类型。 

2. 栈的基本操作

• push(x):将元素 x 压入栈顶。

s.push(10);  // 向栈中添加元素 10

pop():移除栈顶元素。

注意:如果栈为空,调用 pop 会导致未定义行为(如程序崩溃)。

s.pop();  // 从栈中移除顶部元素

top():返回栈顶元素,但不移除它。

注意:如果栈为空,调用 top 会导致未定义行为(如程序崩溃)。

int topElement = s.top();  // 获取栈顶元素

empty():检查栈是否为空,返回 true 表示栈为空,返回 false 表示栈不为空。

if (s.empty()) {
    std::cout << "Stack is empty" << std::endl;
}

size():返回栈中元素的数量。

std::cout << "Stack size: " << s.size() << std::endl;

栈的输入输出示例

#include 
#include 

int main() {
    std::stack s;

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

    while (!s.empty()) {
        std::cout << s.top() << " ";//输出栈顶
        s.pop();//移除栈顶
    }//栈的循环遍历输出
    std::cout << std::endl;

    return 0;
}

2. 栈的复杂度

• push(x):时间复杂度为 O(1)。

• pop():时间复杂度为 O(1)。

• top():时间复杂度为 O(1)。

• empty():时间复杂度为 O(1)。

• size():时间复杂度为 O(1)。

3.栈的应用

• 函数调用:在程序执行过程中,每次函数调用时,函数的局部变量和返回地址等信息会被压入调用栈。函数返回时,这些信息会被弹出。

• 表达式求值:可以使用栈来求解算术表达式,特别是处理括号和运算符优先级。

• 括号匹配:可以使用栈来检查括号是否匹配。每遇到一个左括号,将其压入栈中;每遇到一个右括号,检查栈顶是否有对应的左括号。

• 深度优先搜索(DFS):在图或树的遍历中,可以使用栈来实现深度优先搜索。

4. 栈的限制

• 固定大小的栈:数组实现的栈有固定的大小,可能会导致栈溢出(Stack Overflow)。

• 动态扩展的栈:链表实现的栈可以动态扩展,但每次分配内存可能会有额外的开销。

5自定义容器

可以使用 std::vector、std::deque 或 std::list 作为底层容器。

样例:使用 std::vector 作为底层容器

std::stack> s;

这行代码声明了一个 std::stack,其中存储的元素类型为 int,并且使用 std::vector 作为底层容器。int:栈中存储的元素类型。  std::vector:作为底层容器的类型。 

【2】集合(set)

在C++标准模板库(STL)中,std::set 是一个关联容器,用于存储唯一的元素,并且这些元素会自动按照特定的顺序排列,包含在#include 中。默认情况下,std::set 使用 std::less 进行排序,即按升序排列。

应用实例:C++/C语言判断重复数组(zznu)⭐-CSDN博客

主要特点

1. 唯一性:std::set 中的元素是唯一的,不允许重复。

2. 排序:元素会自动按照升序排列,但可以通过自定义比较函数来改变排序方式。

3. 高效的操作:插入、删除和查找操作的时间复杂度均为 O(log n),其中 n 是容器中元素的数量。

常用操作

1.  定义和初始化

std::set 的定义格式如下: 

std::set<元素类型> 变量名;
std::set s; // 定义一个存储整数的set
std::set s = {1, 2, 3, 4, 5}; // 初始化时插入元素
std::set s2(s); // 使用另一个set进行初始化

std::set> s1;// 定义一个存储int类型元素的set,按降序排列

2. 插入(Insert)

• 操作:将一个新元素插入到集合中。

• 时间复杂度:O(log n),其中 n 是集合中元素的数量。

s.insert(6); // 插入单个元素
s.insert({7, 8, 9}); // 插入多个元素
s.insert(s2.begin(), s2.end()); // 插入另一个set的元素

3. 删除清空元素

操作:从集合中删除一个元素。

时间复杂度:O(log n),其中 n 是集合中元素的数量

操作:删除集合中的所有元素。 •

时间复杂度:O(n),其中 n 是集合中元素的数量。这个操作需要遍历所有元素并逐个删除。

s.erase(6); // 删除指定元素
s.erase(s.begin()); // 删除第一个元素
s.erase(s.lower_bound(3), s.upper_bound(5)); // 删除指定范围内的元素
s.clear(); // 清空所有元素

  4.查找元素

在 C++ 中,std::set 的 find 方法用于在集合中查找指定的元素。如果找到了该元素,find 方法返回一个指向该元素的迭代器;如果未找到,则返回一个指向集合末尾的迭代器(end())。

操作:在集合中查找一个元素。
时间复杂度:O(log n),其中 n 是集合中元素的数量。

auto it = s.find(3);
    if (it != s.end()) {
        std::cout << "Found: " << *it << std::endl;
    } else {
        std::cout << "Not found" << std::endl;
    }

 5.遍历(Iterate

使用范围基于的 for 循环遍历 std::set,时间复杂度为 O(n)。

for (const auto& elem : s) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

6. 大小(Size)
操作:获取集合中元素的数量。
时间复杂度:O(1)。`std::set` 内部维护了一个元素计数器,因此获取大小是常数时间操作。

//  大小(Size): O(1)
    std::cout << "Number of elements: " << s.size() << std::endl;

  7. 最大大小(Max Size)
操作:获取集合可能的最大元素数量。
时间复杂度:O(1)。这个值是固定的,不依赖于集合中元素的数量。

  std::cout << "Maximum number of elements: " << s.max_size() << std::endl;

 8. 交换(Swap)
操作:交换两个集合的内容。
时间复杂度:O(1)。交换操作只涉及指针的交换,因此是常数时间操作。

//  交换(Swap): O(1)
    std::set s2 = {10, 11, 12};
    s.swap(s2);

9.检查元素是否存在

在 C++ 中,std::set 的 count 方法用于检查集合中是否存在某个特定的元素。由于 std::set 中的元素是唯一的,count 方法的返回值只能是 0 或 1。具体来说:

• 如果元素存在于集合中,count 返回 1。

• 如果元素不存在于集合中,count 返回 0。

 find 方法也可以用来检查元素是否存在,但 count 方法的返回值更直观 ,count 方法的时间复杂度为 O(log n),其中 n 是集合中元素的数量。


    if (s.count(3) > 0) {
        std::cout << "Element 3 exists" << std::endl;
    } else {
        std::cout << "Element 3 does not exist" << std::endl;
    }

集合的限制 

1.  性能开销: ◦ 插入、删除和查找操作虽然时间复杂度为 O(log n),但常数因子较大,因为红黑树的维护操作较为复杂。 ◦ 例如,对于大量数据的频繁插入和删除,std::set 的性能可能不如 std::unordered_set。  

2.  内存开销: ◦ std::set 使用红黑树实现,每个节点除了存储数据外,还需要存储额外的指针信息,因此内存开销较大。 ◦ 例如,存储大量小数据时,std::set 的内存使用效率较低。  

3.  不支持随机访问: ◦ std::set 的迭代器是双向迭代器,不支持随机访问。 ◦ 例如,不能直接通过索引访问元素,只能通过迭代器顺序遍历。  

4.  元素必须是可比较的: ◦ std::set 要求元素类型必须提供有效的比较函数(默认是 std::less)。 ◦ 例如,自定义类型需要重载 < 运算符或提供自定义比较函数。  

5.  不支持重复元素: ◦ std::set 只能存储唯一的元素,如果需要存储重复元素,应使用 std::multiset。 ◦ 例如,统计多个相同元素的出现次数时,std::set 无法直接使用。 

【3】双端队列(deque)

你可能感兴趣的:(编程语言知识点,数据结构,算法)