C++ 容器的选择
一、关联式容器与无序关联容器的核心区别关联式容器(如set、map、multiset、multimap)和无序关联式容器(如unordered_set、unordered_map、unordered_multiset、unordered_multimap)是 C++ STL 中两种不同的数据结构,核心区别在于底层实现和特性: 关联式容器:基于红黑树(一种自平衡二叉搜索树)实现,元素按照键(key)的有序性存储,默认通过less比较键的大小。 无序关联式容器:基于哈希表实现,元素存储顺序与键的大小无关,依赖哈希函数计算存储位置,通过键的哈希值快速访问元素。 二、如何选择:关联式容器 vs 无序关联式容器选择需根据具体场景的需求,主要从以下维度判断: 2.1 有序性需求 需要元素有序:优先选择关联式容器。例如: 需遍历元素时按键的大小排序(如set遍历默认升序); 需频繁执行范围查询(如map::lower_bound、map::upper_bound获取键在[a, b]之间的元素)。 无需有序性:优先选择无序关联式容器,其插入、查找、删除的平均效率更高。 2.2 ...
Python异常继承体系深度解析
一、异常继承体系的基本结构Python的内置异常继承体系是一个典型的“基类-派生类”家族结构。这个体系设计得非常精巧,它允许我们在写代码时,既可以抓具体的错,也可以抓“一类”错。 1. 核心继承关系 BaseException:所有异常的基类,包含系统退出相关的异常(如SystemExit) Exception:所有用户代码可处理的异常的基类 常见的派生异常: ArithmeticError:算术错误(如ZeroDivisionError) LookupError:查找错误(如KeyError, IndexError) ValueError:值错误 TypeError:类型错误 ImportError:导入错误 二、多态(Polymorphism)的绝佳体现Python的异常处理机制底层利用了“子类对象可以被视为父类对象”的多态特性。 1. 示例:捕获LookupError12345678data = {"name": "Alice"}try: # 尝试访问不存在的键 print(data["...
Python异常处理深度解析
一、异常的基本概念在Python中,异常是指程序执行过程中发生的错误。当程序遇到错误时,会抛出异常,如果不处理这些异常,程序会终止执行。 二、异常处理的基本语法1. try-except语句123456try: # 可能会抛出异常的代码 result = 10 / 0except ZeroDivisionError: # 处理ZeroDivisionError异常 print("除数不能为零") 2. 捕获多个异常12345678910try: # 可能会抛出异常的代码 result = int(input("请输入一个数字")) print(10 / result)except ZeroDivisionError: # 处理ZeroDivisionError异常 print("除数不能为零")except ValueError: # 处理ValueError异常 print("请输入有效的数字") 3. 捕获所有异常123456t...
STL 容器的成员函数与相关函数
引言C++ 标准模板库(STL)提供了一系列功能丰富的容器,这些容器不仅封装了数据结构,还提供了大量成员函数用于操作数据。此外,STL 还包含许多与容器配合使用的非成员函数,它们扩展了容器的功能,使操作更加灵活。 一、通用成员函数几乎所有 STL 容器都提供了一组基础的通用成员函数,用于获取容器信息、修改容器状态等。 1.1 基本信息函数12345678910111213141516171819202122#include <iostream>#include <vector>#include <list>int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; std::list<std::string> lst = {"apple", "banana", "cherry"}; // 容器大小相关 std::cout <<...
map 存放 pair<Point,string> 的三种解决方案
引言在 C++ 中使用std::map存储自定义类型作为键时,需要确保该类型能够被正确比较大小,因为std::map是一个有序关联容器,其内部通过比较操作来组织元素。本文将介绍三种方法来解决map中存放pair<Point, string>元素的问题,其中Point是一个自定义点类型。 核心概念std::map要求其键类型必须支持比较操作(默认使用<运算符)。对于自定义类型Point,我们需要通过以下三种方式之一提供比较能力: 为Point类重载<运算符 定义一个比较结构体(仿函数) 为Point准备std::less的特化模板 代码示例首先定义基础的Point类: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051#include <math.h>#include <iostream>#include <set>using std::cout;using std::endl;...
Python的“欺骗性”语法:为什么说 obj.name 本质上就是 obj.getter()?
一、引言:一个“错误”的直觉从初学者的视角切入:我们通常认为 self.name = name 就是把数据存进字典,self.name 就是把数据取出来。但在处理复杂对象(如Django模型、Pydantic、@property)时,这种理解是完全错误的。在Python的高级世界里,. 和 = 只是表象,真正的幕后黑手是 Getter 和 Setter。 二、第一层洋葱:@property 的伪装展示一段标准的 @property 代码: 12345678910111213141516class Student: def __init__(self, name): self.name = name @property def name(self): return self._name @name.setter def name(self, value): self._name = value# 看起来像是在访问属性,但实际上是在调用方法s = Student("Alice")print(s...
迭代器与指针
引言在 C++ 中,迭代器 (iterator) 和指针 (pointer) 是两个密切相关但又有所区别的概念。它们都可以用来访问内存中的数据,都支持类似的操作符 (如*和->),但应用场景和功能范围却有显著差异。本文将深入解析迭代器与指针的关系、区别及各自的应用场景。 核心概念指针的本质指针是 C++ 从 C 语言继承而来的概念,是一个变量,其值为另一个变量的内存地址。指针直接指向内存中的某个位置,可以是: 普通变量的地址 数组元素的地址 动态分配内存的地址 函数的地址 迭代器的本质迭代器是 C++ 标准库提供的一种抽象,它模拟了指针的行为,为各种容器提供了统一的访问接口。迭代器可以看作是 "广义指针",它使得算法可以独立于容器类型工作。 两者的核心关系 迭代器在很多方面模仿了指针的行为 指针可以看作是一种特殊的迭代器(用于原生数组) 所有指针都满足随机访问迭代器的要求 迭代器通常通过重载运算符来模拟指针的操作 代码示例指针与迭代器的基本使用对比123456789101112131415161718192021222324252627282930...
Python多进程编程深度解析
一、多进程的基本概念在Python中,进程是程序执行的独立单元。多进程编程允许程序同时执行多个任务,充分利用多核CPU的性能。与多线程不同,多进程不受GIL(全局解释器锁)的限制,可以真正实现并行执行。 二、进程的创建与启动1. 使用multiprocessing模块123456789101112131415161718192021import multiprocessingimport timedef task(name): print(f"Task {name} started") time.sleep(2) print(f"Task {name} completed")# 创建进程process1 = multiprocessing.Process(target=task, args=('A',))process2 = multiprocessing.Process(target=task, args=('B',))# 启动进程proce...
C++ 算法:remove_if 与 partition
一、remove_if 算法原理与实现细节1.1 核心功能与特性remove_if是 C++ 标准库中用于条件过滤的算法,它能移除容器中满足特定条件的元素。需要特别注意的是: 执行的是逻辑删除而非物理删除 不会改变容器的大小(size) 返回指向新的逻辑末尾的迭代器 1.2 底层实现逻辑123456789101112131415// 模拟标准库remove_if实现逻辑template<class ForwardIt, class UnaryPredicate>ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p) { // 跳过不符合删除条件的元素 first = std::find_if(first, last, p); if (first != last) { // 用后面的元素覆盖需要删除的元素 for (ForwardIt i = std::next(first); i != last; ++i) ...
Python多线程编程深度解析
一、多线程的基本概念在Python中,线程是程序执行的最小单位。多线程编程允许程序同时执行多个任务,提高程序的执行效率。 二、线程的创建与启动1. 使用threading模块123456789101112131415161718192021import threadingimport timedef task(name): print(f"Task {name} started") time.sleep(2) print(f"Task {name} completed")# 创建线程thread1 = threading.Thread(target=task, args=('A',))thread2 = threading.Thread(target=task, args=('B',))# 启动线程thread1.start()thread2.start()# 等待线程完成thread1.join()thread2.join()print(&q...
C++ 智能指针与容器组合使用:std::unique_ptr 与 std::vector
一、基础概念与设计原理在 C++ 开发中,std::unique_ptr与std::vector组合是动态内存管理的常用方案,既灵活又安全。unique_ptr独占所有权的特性,使其与容器存储场景天然适配,容器全权负责指针生命周期。 二、完整实现示例1. 定义基础类定义Point类,包含虚析构函数以支持多态: 123456789101112131415161718#include <iostream>#include <vector>#include <memory> class Point {private: int x_; int y_;public: Point(int x = 0, int y = 0) : x_(x), y_(y) { std::cout << "Point构造: (" << x_ << "," << y_ << ")" << std::...
C++ 中使用splice( )函数实现LRU算法
导言LRU(Least Recently Used,最近最少使用)算法是一种常用的缓存淘汰策略,其核心思想是:当缓存空间满时,优先淘汰最近最少使用的元素。在 C++ 中,结合list容器的splice()函数可以高效实现 LRU 算法,因为splice()能以 O (1) 的时间复杂度调整元素位置,非常适合维护元素的访问顺序。 一、LRU 算法的核心需求实现 LRU 算法需要支持以下操作: 访问元素:如果元素存在于缓存中,将其标记为 “最近使用”;如果不存在,需要插入新元素。 插入元素:当缓存未满时直接插入;当缓存已满时,删除 “最近最少使用” 的元素后再插入新元素。 维护顺序:始终保持元素的排列顺序与访问时间相关(最近使用的在前端,最少使用的在末端)。 二、数据结构设计为了高效实现 LRU,我们需要两种数据结构配合: list容器:用于存储缓存元素,最近使用的元素放在链表头部,最少使用的放在尾部。 unordered_map容器:用于快速查找元素在list中的位置(存储元素键与list迭代器的映射),支持 O (1) 时间复杂度的查找。 示例数据结构定义: 1...
Python函数式编程入门:高阶函数与“回调”机制的深度解析
一、引言:从“万物皆对象”切入在Python中,我们常说“万物皆对象”。整数是对象,字符串是对象,那么函数呢?答案是肯定的。既然函数也是对象,它就可以像变量一样被赋值、被传递。这就引出了Python中极具威力的概念——高阶函数。 二、什么是高阶函数?简单来说,如果一个函数满足以下任一条件,它就是高阶函数: 接收一个或多个函数作为输入参数 返回一个函数作为输出结果 今天我们要重点讨论的是第一种情况:把函数当作参数传递。 三、核心疑问:参数到底由谁决定?当你把一个函数(比如my_func)传递给另一个函数(比如executor)时,很多初学者会困惑:my_func需要的参数是谁给的? 答案是:由调用它的高阶函数(executor)决定。 这就好比你在C++中传递一个函数指针。你把“枪”(函数)交给了“士兵”(高阶函数),至于士兵什么时候开枪(调用函数)、朝哪里开枪(传入什么参数),完全由士兵的逻辑决定,而不是由枪自己决定。 在Python中,这被称为“回调”机制的一种体现。被传递的函数处于“被动”地位,它等待着高阶函数在特定的时机,用特定的数据来激活它。 四、实战演练:从内置函数...
Python @property高级应用技巧
一、数据校验与约束这是@property最常见的用途。当你需要确保某个属性的值符合特定规则时(例如,年龄不能为负数),可以使用它: 传统方式:需要显式调用set_age()方法 使用@property:可以像给普通属性赋值一样obj.age = 25,但赋值操作会触发你预设的校验逻辑 1234567891011121314151617181920class Person: def __init__(self, name, age): self.name = name self._age = age # 使用单下划线表示这是一个内部属性 @property def age(self): """获取年龄""" return self._age @age.setter def age(self, value): """设置年龄,并进行校验""" ...
C++ 容器中的 sort () 与 splice ()
一、sort ():容器元素的排序利器sort()是 C++ 标准库中用于排序的函数,其核心功能是对容器中的元素进行升序或自定义规则排序。不过,并非所有容器都支持sort(),它仅适用于随机访问迭代器的容器(如vector、deque、array等),而像list、set等容器则有自己的排序方式。 1. 基本用法sort()的函数原型如下(以vector为例): 1234567#include <algorithm> // 需包含算法库// 升序排序(默认)sort(begin_iterator, end_iterator);// 自定义排序规则sort(begin_iterator, end_iterator, comparator); 其中,begin_iterator和end_iterator指定排序的范围(左闭右开),comparator是一个自定义的比较函数或 lambda 表达式,用于定义排序规则。 2. 实战示例 默认升序排序: 12345678910111213#include <vector>#include <algorith...
技术笔记:Python与C++函数参数传递机制差异
技术笔记:Python与C++函数参数传递机制差异在跨语言开发中,函数参数处理是一个常见的痛点。当函数拥有多个默认参数时,如何优雅地调用它?这是本文要探讨的核心问题。 一、Python的关键字参数机制Python的关键字参数机制允许开发者通过参数名直接指定值,而不必严格按照函数定义的顺序传递参数: 12345678def configure_connection(host="localhost", port=8080, timeout=30, retry=False, ssl=True): print(f"Configuring connection: host={host}, port={port}, timeout={timeout}, retry={retry}, ssl={ssl}")# 只修改timeout参数configure_connection(timeout=60)# 跳跃式修改多个参数configure_connec...
C++ 容器中の erase
一、erase 方法的功能定位vector 的 erase 方法是 STL 中用于从容器中移除元素的核心函数,其主要功能是: 从 vector 中删除单个元素或一段连续范围内的元素 调整容器大小以反映元素数量的变化 维护剩余元素的连续性和内存布局 返回一个迭代器,指向被删除元素的下一个元素 erase 方法是破坏性操作,会改变容器的状态和内部布局,同时可能影响现有迭代器的有效性。 二、迭代器参数的语法特征与使用场景vector 的 erase 方法有两种重载形式,分别适用于不同的删除场景: 2.1 单个元素删除1iterator erase(iterator position); 参数:指向要删除元素的迭代器 返回值:指向被删除元素下一个元素的有效迭代器 使用场景:已知要删除元素的确切位置时 2.2 范围元素删除1iterator erase(iterator first, iterator last); 参数: first:指向要删除范围中第一个元素的迭代器 last:指向要删除范围中最后一个元素之后位置的迭代器 返回值:指向最后一个被删除元素下一个元素...
C++ list
一、内部实现机制 vector:基于动态数组实现,元素存储在连续的内存空间中,通过单一指针管理内存块 list:基于双向链表实现,每个元素包含数据域和两个指针域(前驱和后继),元素分散存储在内存中 二、核心性能差异 操作 vector list 随机访问(按索引访问) O (1),高效支持 O (n),不支持直接索引访问 头部插入 / 删除 O (n),需移动所有元素 O (1),只需调整指针 尾部插入 / 删除 O (1)(平均) O(1) 中间插入 / 删除 O (n),需移动插入点后的所有元素 O (1),只需调整附近元素的指针 内存分配 可能需要整体扩容(复制所有元素) 每次插入新元素单独分配内存 迭代器类型 随机访问迭代器 双向迭代器 缓存利用率 高(连续内存,缓存局部性好) 低(元素分散,容易缓存失效) 三、功能差异 vector: 支持[]运算符和at()方法进行随机访问 提供reserve()方法预分配内存 元素在内存中连续存储,可直接获取数据指针(data()方法) 适合与 C API 交互(...
C++ deque
导言deque(双端队列)是另一种常用的序列容器,与 vector 相比,它在两端的插入删除操作上有独特优势。以下是 deque 高效操作的策略和特性: 一、deque 的特性与优势deque 与 vector 的核心区别在于内存布局: deque 采用分段连续内存结构,由多个固定大小的内存块组成 支持 O (1) 时间复杂度的两端插入和删除操作 不需要像 vector 那样在扩容时复制所有元素 二、高效插入元素 两端插入效率最高deque 在头部和尾部的插入操作都是 O (1) 时间复杂度,这是它相比 vector 的主要优势: 123456789std::deque<int> dq;// 尾部插入dq.push_back(10);dq.emplace_back(20); // 更高效,直接构造// 头部插入(vector不擅长的操作)dq.push_front(5);dq.emplace_front(3); // 直接在头部构造 中间插入的特点与 vector 类似,deque 的中间插入仍需移动元素,时间复杂度为 O (n),但实际性能可能略优于 vect...
Python self与cls的区别深度解析
一、核心区别对比 特性 self (实例方法) cls (类方法 @classmethod) 代表对象 实例对象 (具体的某一个) 类对象 (整个类别/图纸) 第一个参数 接收调用该方法的实例 接收调用该方法的类 访问权限 访问实例属性(self.name) 和类属性 只能访问类属性(cls.count) 主要职责 处理具体业务逻辑,修改个体状态 修改全局状态、工厂模式创建实例 调用方式 通常通过 实例.方法() 调用 通常通过 类.方法() 调用 二、形象类比:汽车工厂为了更直观地理解,我们可以把类想象成一个汽车工厂,把实例想象成造出来的汽车: 1. self (实例方法) — 针对具体的车 场景:给车喷漆、踩油门、换轮胎 逻辑:你必须先有一辆车(实例),才能做这些操作。你不能对着空气踩油门 代码体现:self.color = "Red"(把这一辆车喷红,不影响别的车) 2. cls (类方法) — 针对工厂/图纸 场景:修改出厂默认颜色、统计总共造了多少辆车、决定下一代车型的引擎规格 逻辑:这些操作不需要...
Leetcode 0032.longest-valid-parentheses(python)
32. Longest Valid Parentheses题目Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. Example 1: 123Input: s = "(()"Output: 2Explanation: The longest valid parentheses substring is "()". Example 2: 123Input: s = ")()())"Output: 4Explanation: The longest valid parentheses substring is "()()". Example 3: 12Input: s = ""Output: 0 题目大意给定一个只包含 '(...
Leetcode 0032.longest-valid-parentheses
32. Longest Valid Parentheses题目Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. Example 1: 123Input: s = "(()"Output: 2Explanation: The longest valid parentheses substring is "()". Example 2: 123Input: s = ")()())"Output: 4Explanation: The longest valid parentheses substring is "()()". Example 3: 12Input: s = ""Output: 0 题目大意给定一个只包含 '(...
Leetcode 0031.next-permutation(python)
31. Next Permutation题目A permutation of an array of integers is an arrangement of its members into a sequence or linear order. For example, for arr = [1,2,3], the following are all the permutations of arr: [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]. The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then ...
Leetcode 0031.next-permutation
31. Next Permutation题目A permutation of an array of integers is an arrangement of its members into a sequence or linear order. For example, for arr = [1,2,3], the following are all the permutations of arr: [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]. The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then ...
Leetcode 0030.Substring with Concatenation of All Words(python)
30. Substring with Concatenation of All Words一、问题描述给定一个字符串 s 和一个字符串数组 words,找出 s 中所有恰好由 words 中所有单词串联形成的子串的起始索引。 注意:words 中的单词可以以任意顺序串联。 示例 1: 12输入:s = "barfoothefoobarman", words = ["foo","bar"]输出:[0,9] 示例 2: 12输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]输出:[] 示例 3: 12输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]输出:[6,9,12] 二...

