当前位置: 首页 > news >正文

c++程序设计速学笔记2基础数据结构

基础数据结构

数组(Array)

数组是一种线性数据结构,它存储相同类型的元素的连续内存块。数组的每个元素都有一个索引,用于快速访问和操作数据。
特点:

  • 随机访问:数组支持通过索引快速访问元素。
  • 固定大小:静态数组的大小在声明时确定,动态数组(如C++中的std::vector)可以在运行时调整大小。
  • 内存连续:数组元素在内存中存储是连续的,这使得访问速度快,但可能导致内存碎片。

vector 是一种动态数组容器,它封装了数组的功能,并允许在运行时动态地调整大小

#include <vector>
using namespace std;
vector<int> vec; // 创建一个存储整数的 vector
vector<std::string> strVec; // 创建一个存储字符串的 vector
//使用花括号 {} 来初始化 vector
vector<int> vec = {1, 2, 3, 4, 5};
vector<string> strVec = {"hello", "world"};
//使用 push_back() 方法向 vector 添加元素:
vec.push_back(6);
strVec.push_back("C++");
//使用下标 [] 访问 vector 中的元素:
int firstElement = vec[0]; // 获取第一个元素
string secondElement = strVec[1]; // 获取第二个元素bool isEmpty = vec.empty(); // 检查是否为空
int size = vec.size(); // 获取元素数量
int first = vec.front(); // 获取第一个元素
int last = vec.back(); // 获取最后一个元素for (int num : vec) {cout << num << " ";
}
cout << endl;vec[0] = 100; // 修改第一个元素vec.insert(vec.begin() + 1, 50); // 在第二个位置插入数字 50vec.erase(vec.begin() + 1); // 删除第二个位置的元素

string 是一个模板类,专门设计用来处理字符序列

  1. 构造函数:可以创建空字符串或初始化为特定内容的字符串。
  2. 赋值和修改:可以赋值、连接、插入和删除字符串中的字符。
  3. 访问元素:可以使用下标操作符 [] 访问字符串中的单个字符。
  4. 长度和容量:提供 size() 和 length() 来获取字符串的长度,以及 capacity() 来获取分配的存储空间。
  5. 比较:提供比较操作符来比较两个字符串。
  6. 查找和替换:提供方法在字符串中查找子串,并替换匹配的子串。
  7. 子串:提供 substr() 方法来获取字符串的子串。
  8. 迭代器:支持迭代器,可以遍历字符串中的每个字符。
#include <iostream>
#include <string>
using namespace std;
int main() {// 创建字符串string greeting = "Hello, World!";string name = "Kimi";// 输出字符串cout << greeting << std::endl;// 连接字符串string message = "My name is " + name + ".";cout << message << endl;// 访问特定字符char firstChar = message[0]; // 'M'cout << "The first character is: " << firstChar << endl;// 获取字符串长度cout << "The length of the message is: " << message.length() << endl;// 修改字符串message[0] = 'H'; // 修改第一个字符为 'H'cout << "Modified message: " << message << endl;return 0;
}

链表(Linked List)

链表是一种线性数据结构,由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。
特点:

  • 动态大小:链表的大小可以在运行时动态变化,适合不确定数量元素的情况。
  • 非连续内存:链表的元素不需要在内存中连续存储,这使得它们在处理大量数据时更加灵活。
  • 插入和删除:链表的插入和删除操作通常比数组更高效,因为不需要移动大量元素。

常见类型:

  • 单链表:每个节点指向下一个节点。
  • 双链表:每个节点指向前一个和后一个节点。
  • 循环链表:最后一个节点指向第一个节点,形成一个循环。
    单链表
#include <iostream>
#include <forward_list>forward_list<int> fl;fl.push_front(1);fl.push_back(4);auto it = fl.before_begin(); // 获取逆向迭代器
std::advance(it, 2); // 移动到第三个元素之前
fl.insert_after(it, 5);fl.remove(3);//删除所有匹配的元素auto it = fl.begin();
std::advance(it, 2); // 移动到第三个元素
fl.erase_after(it); // 删除第三个元素//遍历 
for (int elem : fl) {std::cout << elem << " ";
}
std::cout << std::endl;//获取链表大小
std::cout << "Size of forward_list: " << fl.size() << std::endl;//清空
fl.clear();排序
std::sort(fl.begin(), fl.end());//反转
std::forward_list<int> reversed_fl;
for (auto it = fl.before_begin(); it != fl.end(); ++it) {reversed_fl.push_front(*it);
}
fl = std::move(reversed_fl);//查找元素
auto it = std::find(fl.begin(), fl.end(), 2);
if (it != fl.end()) {std::cout << "Found element 2 at position: " << std::distance(fl.begin(), it) << std::endl;
}

双向链表
需要频繁插入和删除元素的场景中非常有用。然而,由于它不支持随机访问,所以不适合需要频繁访问中间元素的场景。

#include <list>
std::list<int> lst;lst.push_front(1);
lst.push_back(2);auto it = std::find(lst.begin(), lst.end(), 1); // 找到元素1的位置
lst.insert(it, 3); // 在元素1之前插入3lst.remove(2);it = std::find(lst.begin(), lst.end(), 3); // 找到元素3的位置
lst.erase(it); // 删除元素3//遍历
for (const auto& elem : lst) {std::cout << elem << " ";
}
std::cout << std::endl;//排序
lst.sort(); // 默认使用 `<` 比较元素
//反转
lst.reverse();//查找元素
it = std::find(lst.begin(), lst.end(), 2); // 查找元素2
if (it != lst.end()) {std::cout << "Found element 2" << std::endl;
}//合并和分割列表
std::list<int> anotherList = {4, 5, 6};
lst.merge(anotherList); // 合并两个列表
anotherList.splice(anotherList.begin(), lst); // 将anotherList的元素移动到lst//插入范围
int arr[] = {7, 8, 9};
lst.insert(lst.end(), std::begin(arr), std::end(arr));

循环链表

#include <iostream>
#include <list>int main() {std::list<int>循环链表 = {1, 2, 3, 4, 5};// 遍历循环链表for (auto it = 循环链表.begin(); it != 循环链表.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 将迭代器移动到末尾,并获取下一个元素,实现循环auto it = 循环链表.end();--it; // 移动到最后一个元素std::cout << "最后一个元素: " << *it << std::endl;// 模拟循环链表的下一个元素std::cout << "下一个元素: " << *(it++) << std::endl;return 0;
}
#include <iostream>class Node {
public:int data;Node* next;Node(int val) : data(val), next(nullptr) {}
};class CircularLinkedList {
private:Node* head;Node* tail;public:CircularLinkedList() : head(nullptr), tail(nullptr) {}~CircularLinkedList() {while (head) {Node* temp = head;head = head->next;delete temp;}}void append(int value) {Node* newNode = new Node(value);if (!head) {head = tail = newNode;head->next = head; // 使链表循环} else {tail->next = newNode;tail = newNode;tail->next = head; // 使链表循环}}void display() {if (!head) return;Node* current = head;do {std::cout << current->data << " ";current = current->next;} while (current != head);std::cout << std::endl;}
};int main() {CircularLinkedList cll;cll.append(1);cll.append(2);cll.append(3);cll.display(); // 输出: 1 2 3return 0;
}

栈(Stack)

栈(Stack)是一种后进先出(LIFO,Last In First Out)的数据结构。

  • 压栈(Push):在栈顶添加一个元素。
  • 弹栈(Pop):从栈顶移除一个元素。
  • 查看栈顶(Top):获取栈顶的元素,但不移除它。

栈常用于处理需要回溯的场景,如函数调用栈、撤销操作、括号匹配等
stack 容器适配器和 array 或 vector 作为底层容器的栈。

#include <iostream>
#include <stack>
using namespace std;int main() {// 创建一个整数类型的栈stack<int> s;// 向栈中压入元素s.push(1);s.push(2);s.push(3);// 查看栈是否为空cout << "Stack is empty: " << (s.empty() ? "Yes" : "No") << std::endl;// 查看栈顶元素std::cout << "Top element: " << s.top() << std::endl;// 弹出栈顶元素std::cout << "Popping top element..." << std::endl;s.pop();// 再次查看栈是否为空std::cout << "Stack is empty after pop: " << (s.empty() ? "Yes" : "No") << std::endl;// 再次查看栈顶元素std::cout << "Top element after pop: " << s.top() << std::endl;return 0;
}

队列

先进先出(FIFO, First-In-First-Out)

  • 入队(Enqueue):在队列的末尾添加一个元素。
  • 出队(Dequeue):从队列的开头移除一个元素。
  • 查看队首(Front):获取队列开头的元素,但不移除它。
  • 查看队尾(Back/Rear):获取队列末尾的元素。

队列常用于处理需要保持元素顺序的场景,如打印任务队列、消息队列等。

#include <iostream>
#include <queue>
using namespace std;int main() {// 创建一个整数类型的队列queue<int> q;// 向队列中添加元素q.push(1);q.push(2);q.push(3);// 检查队列是否为空cout << "Queue is empty: " << (q.empty() ? "Yes" : "No") << endl;// 获取队列的大小cout << "Queue size: " << q.size() << endl;// 获取队列的第一个元素(队首)cout << "Front element: " << q.front() << endl;// 移除队列的第一个元素q.pop();// 再次检查队列是否为空和大小cout << "Queue is empty after one pop: " << (q.empty() ? "Yes" : "No") << endl;cout << "Queue size after one pop: " << q.size() << endl;// 再次获取队列的第一个元素cout << "Front element after one pop: " << q.front() << endl;return 0;
}

哈希表(Hash Table)

unordered_map来实现,它是基于哈希表的关联容器
注意线程安全问题

#include <iostream>
#include <unordered_map>
#include <string>int main() {// 创建一个 unordered_mapstd::unordered_map<std::string, int> ageMap;// 插入元素ageMap.insert({"Alice", 30});ageMap.insert(std::make_pair("Bob", 25));ageMap["Charlie"] = 35;// 查找元素auto it = ageMap.find("Alice");if (it != ageMap.end()) {std::cout << "Alice's age is " << it->second << std::endl;} else {std::cout << "Alice not found" << std::endl;}try {std::cout << "Alice's age is " << ageMap.at("Alice") << std::endl;} catch (const std::out_of_range& e) {std::cout << "Alice not found" << std::endl;}// 删除元素ageMap.erase("Bob");// 清空容器ageMap.clear();// 获取容器大小std::cout << "Number of elements: " << ageMap.size() << std::endl;// 检查容器是否为空if (ageMap.empty()) {std::cout << "The map is empty" << std::endl;} else {std::cout << "The map is not empty" << std::endl;}// 重新插入元素ageMap.insert({"Alice", 30});ageMap.insert({"Bob", 25});ageMap.insert({"Charlie", 35});// 遍历所有元素for (const auto& pair : ageMap) {std::cout << pair.first << " is " << pair.second << " years old." << std::endl;}// 桶相关操作std::cout << "Number of buckets: " << ageMap.bucket_count() << std::endl;std::cout << "Maximum number of buckets: " << ageMap.max_bucket_count() << std::endl;for (size_t i = 0; i < ageMap.bucket_count(); ++i) {std::cout << "Bucket " << i << " contains " << ageMap.bucket_size(i) << " elements." << std::endl;}std::string key = "Alice";std::cout << "Key " << key << " is in bucket " << ageMap.bucket(key) << std::endl;return 0;
}

相关文章:

c++程序设计速学笔记2基础数据结构

基础数据结构 数组&#xff08;Array&#xff09; 数组是一种线性数据结构&#xff0c;它存储相同类型的元素的连续内存块。数组的每个元素都有一个索引&#xff0c;用于快速访问和操作数据。 特点&#xff1a; 随机访问&#xff1a;数组支持通过索引快速访问元素。固定大小…...

搜维尔科技:SenseGlove案例-利用VR触觉技术培训机组人员

SenseGlove案例-利用VR触觉技术培训机组人员 搜维尔科技&#xff1a;SenseGlove案例-利用VR触觉技术培训机组人员...

OpenCV视觉分析之目标跟踪(10)估计两个点集之间的刚性变换函数estimateRigidTransform的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算两个2D点集之间的最优仿射变换 estimateRigidTransform 是 OpenCV 中的一个函数&#xff0c;用于估计两个点集之间的刚性变换&#xff08;即…...

Python 虚拟环境创建

1. 创建python虚拟环境 conda create -n env_name pythonversionex:conda create -n train_ticket_venv python3.112. 查看安装包信息 pip show package_nameex: pip show numpy3. 用清华源安装软件包 pip install package_name -i https://mirrors.tuna.tsinghua.edu.cn/pyp…...

STL-list容器的使用

在C标准库中&#xff0c;std::list 是一个双向链表容器&#xff0c;提供高效的插入和删除操作&#xff0c;尤其适用于需要频繁在容器中间进行插入和删除元素的场景。与其他序列容器&#xff08;如 std::vector 和 std::deque&#xff09;相比&#xff0c;std::list 有其独特的优…...

java中线程与集合的面试题

在 Java 面试中&#xff0c;线程和集合相关的知识是非常常见的考察点。以下是几个典型的问题及答案&#xff1a; 线程相关面试题 什么是线程&#xff1f; 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一个进程可以有多…...

第十五章 IRIS 进程之间的通信

文章目录 第十五章 IRIS 进程之间的通信介绍指定作业间通信设备的内存缓冲区禁用作业间通信缓冲区 作业间通信设备编号设备编号 IJC 设备的 I/O 命令OPEN命令device 设备timeout 暂停 第十五章 IRIS 进程之间的通信 本页介绍如何在两个或多个 IRIS 数据平台进程之间建立通信。…...

设计者模式之策略模式

前言 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多样&#xff0c;经常改变&#xff0c;如果将这些算法都写在对象中&#xff0c;将会使对象变得异常复杂&#xff1b;而且有时候支持不频繁使用的算法也是一个性能负担。 如何在运行时根据需要透明地更改对象的算…...

STM32H750 COMP模拟比较器

STM32H750 COMP模拟比较器 &#x1f516;STM32H750内置两个超低功耗比较器通道&#xff08;COMP1 和 COMP2&#xff09;. &#x1f4c4;功能应用&#xff1a; 在模拟信号的触发下从低功耗模式唤醒模拟信号调理与定时器的 PWM 输出结合使用时&#xff0c;构成逐周期电流控制环路…...

openresty入门教程:rewrite_by_lua_block

在OpenResty中&#xff0c;rewrite_by_lua_block 是一个强大的工具&#xff0c;它允许你在Nginx的rewrite阶段执行Lua脚本。这个阶段在Nginx处理请求的早期发生&#xff0c;通常用于修改请求URI、请求参数、请求头等&#xff0c;或者根据某些条件执行重定向、返回特定响应等。 …...

Java 并发编程学习笔记

参考资料&#xff1a; JAVA并发专题 - 终有救赎的专栏 - 掘金 Java并发编程学习路线&#xff08;建议收藏&#xfffd;&#xfffd;&#xff09; | Java程序员进阶之路x沉默王二 面试题目&#xff1a; JUC第一讲&#xff1a;Java并发知识体系详解 面试题汇总(P6熟练 P7精通…...

【SpringMVC】——Cookie和Session机制

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;实践 1&#xff1a;获取URL中的参数 &#xff08;1&#xff09;PathVariable 2&…...

[产品管理-60]:产品的情感化设计与常用工具:感性工学、情感分析、神经网络法、微软反应卡、突发情绪法

目录 一、概述 1、情感化设计的三个层次 2、情感化设计在产品中的应用 3、情感化设计的案例 4、情感化设计的意义 二、常见工具 1、感性工学 &#xff08;情商&#xff09; 2、情感分析 3、神经网络法 4、微软反应卡 5、突发情绪法 一、概述 产品的情感化设计是一种…...

uniapp 小程序 周选择器

这里贴出来的是子组件的代码&#xff0c;父组件只是打开了一下popup // 打开了一下popup $refs.popup.open(bottom)如果不想用子组件的话&#xff0c;直接打开popup就可以用<template><uni-popup ref"popup" type"bottom" background-color&quo…...

Android笔记(三十二):封装一个毫秒级别倒计时View

效果 倒计时View视频 背景 业务场景需要显示带有毫秒级别的倒计时&#xff0c;于是自己封装一个通用的倒计时组件 源码分析 核心倒计时逻辑&#xff0c;主要是每隔100毫秒计算一次从开始倒计时到现在的剩余时间&#xff0c;并通过process接口返回出去Handler每次设置100毫秒…...

[产品管理-60]:马斯洛需求层次与产品的情感化设计

目录 一、概述 1、马斯洛需求层次理论概述 2、产品情感化设计与马斯洛需求层次的关系 3、产品情感化设计的实践案例 二、马斯洛需求层次与用户情感程度&#xff08;本能、行为、反思&#xff09;的关系 1、马斯洛需求层次与用户情感程度概述 2、马斯洛需求层次与用户情感…...

Python接口自动化测试自学指南(项目实战)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 接口自动化测试是指通过编写程序来模拟用户的行为&#xff0c;对接口进行自动化测试。Python是一种流行的编程语言&#xff0c;它在接口自动化测试中得到了广…...

ESLint 使用教程(三):12个ESLint 配置项功能与使用方式详解

前言 在现代前端开发中&#xff0c;代码质量与一致性是至关重要的&#xff0c;ESLint 正是为此而生的一款强大工具&#xff0c;本文将带您详细了解 ESLint 的配置文件&#xff0c;并通过通俗易懂的方式讲解其主要配置项及其配置方法。此外&#xff0c;我们还将探讨一些高级配置…...

如何将 EDB 文件导入 Ansys HFSS 和 Ansys Q3D

EDB 文件包含有关印刷电路板 &#xff08;PCB&#xff09; 的基本数据&#xff0c;包括其布局、组件、连接性和电磁属性。将 EDB 文件导入 Ansys 工具是利用仿真和分析功能设计高效、可靠和高性能电子系统的关键步骤。在这里&#xff0c;我将向您展示如何将 EDB 文件导入 Ansys…...

HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac

寻找模拟器 背景&#xff1a; 运行的是h5&#xff0c;模拟器是网易MuMu。 首先检查一下是否配置dab环境&#xff0c;adb version 配置一下hbuilderX的adb&#xff1a; 将命令输出的路径配置到hbuilderx里面去&#xff0c;然后重启下HbuilderX。 开始安装基座…一直安装不…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...