大模型学习-Python-数据结构
大模型学习-Python-数据结构
数据整理
类型 | 说明 |
---|---|
数值类型-整数 | 表示整数值,包括正数、负数和零。没有取值范围,可以无限大。c++ 中区分 char short int long,且每个类型都有取值范围。 |
数值类型-复数 | 表示复数,包含实部和虚部。可以直接用实部+虚部的方式表示,eg:1+2j。c++ 中需要通过 std::complex 定义。 |
数值类型-浮点数 | 表示带有小数部分的实数值。通常是双精度浮点数,占用64位。c++ 中区分单精度与双精度。 |
数值类型-布尔 | 表示真值或假值。是整数的子类型,True 等价于 1,False 等价于 0。取值为True 与 False。c++ 中取值为 true 与 false。 |
字符串 | 有序、不可变的字符序列。序列的一种,支持切片。c++ 中字符串变量可修改,字符串常量不可修改。 |
元组 | 有序、不可变、允许重复的集合。可以存储任何数据类型。c++ 中不存在此类可以存放不同类型数据的容器。 |
列表 | 有序、可变、允许重复的集合。序列的一种,支持切片。可以存储任何数据类型。c++ 中不存在此类可以存放不同类型数据的容器。 |
集合 | 无序、不可重复的唯一元素集合。可以存储任何数据类型。c++ 中不存在此类可以存放不同类型数据的容器。 |
字典 | 无序、可变的键值对集合。键必须是唯一的,值可以是任何数据类型。c++ 中不存在此类可以存放不同类型数据的容器。 |
高阶数据结构-数组 | 存储同类型元素的集合。可取 i、l、f、d 类型。c++ 中的数组类似,但 c++ 中可以存储对象数据。 |
高阶数据结构-双端队列 | 允许从两端高效添加和移除元素的队列。c++ STL容器有类似结构。 |
高阶数据结构-堆 | 一种树形结构,满足堆性质(父节点值小于/大于子节点值)。 |
高阶数据结构-链表 | 通过指针连接的节点序列。 |
高阶数据结构-树 | 由节点和边组成的分层数据结构。 |
高阶数据结构-图 | 由节点和边组成的非层次数据结构。 |
数值类型
数值类型分成 整数、浮点数、复数、布尔
1. 整数(Integers)
表示整数值,包括正数、负数和零。
a = 10
b = -5
print(type(a)) # 输出: <class 'int'>
print(type(b)) # 输出: <class 'int'>
2. 浮点数(Floating Point Numbers)
表示带有小数部分的实数值。
a = 3.1415926535
b = 1.0
print(type(a)) # 输出: <class 'float'>
print(type(b)) # 输出: <class 'float'>
3. 复数(Complex Numbers)
表示复数,包含实部和虚部。
a = 3 + 4j
b = 2j
print(type(a)) # 输出: <class 'complex'>
print(type(b)) # 输出: <class 'complex'>
4. 布尔值(Boolean)
表示真值或假值。
a = True
b = False
print(type(a)) # 输出: <class 'bool'>
print(type(b)) # 输出: <class 'bool'>
print(int(a)) # 输出: 1
print(int(b)) # 输出: 0
bool 转换时,何时取到 False:
Fraction(0,1)表示分子为0分母为1的有理数。
字符串(String)
有序、不可变的字符序列。
时间复杂度:
# 创建字符串
greeting = "Hello, World!"
print(greeting) # 输出: Hello, World!
# 索引访问
print(greeting[0]) # 输出: H
# 切片
print(greeting[1:5]) # 输出: ello
# 拼接
print(greeting + " ") # 输出: Hello, World!
Python 字符串可以用单引号、双引号、三引号处理。区别在于:
- 单引号、双引号可用于处理字符串中包含银行的内容。比如’“i love china”’ 或者 “let’s go”
- 三引号可用于长文本字符串(多行直接编辑,不需要添加\n换行)
Python 字符串可以直接进行 + 与 * 运算
- 字符串+运算为字符串拼接
- 字符串*运算为字符串复制
元组(Tuple)
有序、不可变、允许重复的集合。可以存储任何数据类型。
时间复杂度:
# 创建元组
numbers = (1, 2, 3, 3)
print(numbers) # 输出: (1, 2, 3, 3)
# 索引访问
print(numbers[0]) # 输出: 1
# 切片
print(numbers[1:3]) # 输出: (2, 3)
列表(List)
有序、可变、允许重复的集合。可以存储任何数据类型。
时间复杂度:
# 创建列表
fruits = ["apple", "banana", "cherry"]
print(fruits) # 输出: ['apple', 'banana', 'cherry']
# 索引访问
print(fruits[0]) # 输出: apple
# 切片
print(fruits[1:3]) # 输出: ['banana', 'cherry']
# 修改元素
fruits[0] = "pear"
print(fruits) # 输出: ['pear', 'banana', 'cherry']
集合(Set)
无序、不可重复的唯一元素集合。可以存储任何数据类型。
时间复杂度:
# 创建集合
unique_numbers = {1, 2, 3, 3, 4}
print(unique_numbers) # 输出: {1, 2, 3, 4}
# 添加元素
unique_numbers.add(5)
print(unique_numbers) # 输出: {1, 2, 3, 4, 5}
# 删除元素
unique_numbers.remove(4)
print(unique_numbers) # 输出: {1, 2, 3, 5}
字典(Dictionary)
无序、可变的键值对集合。键必须是唯一的,值可以是任何数据类型。
时间复杂度:
# 创建字典
person = {"name": "Alice", "age": 30, "city": "Beijing"}
print(person) # 输出: {'name': 'Alice', 'age': 30, 'city': 'Beijing'}
# 访问值
print(person["name"]) # 输出: Alice
# 修改值
person["age"] = 31
print(person) # 输出: {'name': 'Alice', 'age': 31, 'city': 'Beijing'}
# 添加键值对
person["country"] = "China"
print(person) # 输出: {'name': 'Alice', 'age': 31, 'city': 'Beijing', 'country': 'China'}
高阶数据结构
需导入外部模块使用
1. 数组(Array)
存储同类型元素的集合。
取值范围: 根据类型不同,取值范围也不同:
时间复杂度:
import array
# 创建整数数组
arr = array.array("i", [1, 2, 3, 4, 5])
print(arr) # 输出: array('i', [1, 2, 3, 4, 5])
# 访问元素
print(arr[0]) # 输出: 1
# 修改元素
arr[0] = 10
print(arr) # 输出: array('i', [10, 2, 3, 4, 5])
2. 双端队列(Deque)
允许从两端高效添加和移除元素的队列。
时间复杂度:
from collections import deque
dq = deque([1, 2, 3])
print(dq) # 输出: deque([1, 2, 3])
# 从左端添加
dq.appendleft(0)
print(dq) # 输出: deque([0, 1, 2, 3])
# 从右端移除
print(dq.pop()) # 输出: 3
print(dq) # 输出: deque([0, 1, 2])
3. 堆(Heap)
一种树形结构,满足堆性质(父节点值小于/大于子节点值)。
时间复杂度:
import heapq
# 创建堆
heap = [3, 1, 2]
heapq.heapify(heap)
print(heap) # 输出: [1, 2, 3]
# 添加元素
heapq.heappush(heap, 4)
print(heap) # 输出: [1, 2, 3, 4]
# 移除最小值
print(heapq.heappop(heap)) # 输出: 1
print(heap) # 输出: [2, 3, 4]
4. 链表(Linked List)
通过指针连接的节点序列。
时间复杂度:
class Node:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, value):
new_node = Node(value)
if not self.head:
self.head = new_node
return
current = self.head
while current.next:
current = current.next
current.next = new_node
def print_list(self):
current = self.head
while current:
print(current.value, end=" ")
current = current.next
print()
# 创建链表
ll = LinkedList()
ll.append(1)
ll.append(2)
ll.append(3)
ll.print_list() # 输出: 1 2 3
5. 树(Tree)
由节点和边组成的分层数据结构。
时间复杂度:
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
class Tree:
def __init__(self):
self.root = None
def insert(self, value):
if not self.root:
self.root = TreeNode(value)
return
current = self.root
while True:
if value < current.value:
if not current.left:
current.left = TreeNode(value)
break
current = current.left
else:
if not current.right:
current.right = TreeNode(value)
break
current = current.right
def print_tree(self, node, level=0):
if node:
self.print_tree(node.right, level + 1)
print(' ' * level + str(node.value))
self.print_tree(node.left, level + 1)
# 创建二叉树
tree = Tree()
tree.insert(5)
tree.insert(3)
tree.insert(7)
tree.insert(2)
tree.insert(4)
tree.insert(6)
tree.insert(8)
tree.print_tree(tree.root)
# 输出:
# 8
# 7
# 6
# 5
# 4
# 3
# 2
6. 图(Graph)
由节点和边组成的非层次数据结构。
时间复杂度:
class Graph:
def __init__(self):
self.adjacency = {}
def add_node(self, node):
if node not in self.adjacency:
self.adjacency[node] = []
def add_edge(self, node1, node2):
if node1 in self.adjacency and node2 in self.adjacency:
self.adjacency[node1].append(node2)
self.adjacency[node2].append(node1)
def print_graph(self):
for node in self.adjacency:
print(f"{node} -> {self.adjacency[node]}")
# 创建图
graph = Graph()
graph.add_node("A")
graph.add_node("B")
graph.add_node("C")
graph.add_edge("A", "B")
graph.add_edge("B", "C")
graph.add_edge("C", "A")
graph.print_graph()
# 输出:
# A -> ['B', 'C']
# B -> ['A', 'C']
# C -> ['B', 'A']
数据运算
算术运算
Python 除了 +、-、*、/、% 外还有 //(地板除)、**(幂运算)
# 加法(+):将两个数值相加。
a = 5
b = 3
print(a + b) # 输出:8
# 减法(-):将两个数值相减,减去右边的数值。
a = 8
b = 3
print(a - b) # 输出:5
# 乘法(*):将两个数值相乘。
a = 4
b = 5
print(a * b) # 输出:20
# 除法(/):将左边的数值除以右边的数值,结果为浮点数。
a = 10
b = 3
print(a / b) # 输出:3.333...
# 幂运算(**):计算左边数值的右边数值次幂。
base = 2
exponent = 3
print(base ** exponent) # 输出:8
# 取模(%):返回除法运算后的余数。
a = 10
b = 3
print(a % b) # 输出:1
# 地板除法(//):进行除法运算,结果向下取整。
a = 10
b = 3
print(a // b) # 输出:3
# 增量运算(+=):将右边的数值加到左边变量上,并赋值给左边变量。
a = 5
a += 3 # 相当于 a = a + 3
print(a) # 输出:8
# 减量运算(-=):将右边的数值减去左边变量上的数值,并赋值给左边变量。
a = 8
a -= 3 # 相当于 a = a - 3
print(a) # 输出:5
# 乘法赋值(*=):将左边变量乘以右边的数值,并赋值给左边变量。
a = 4
a *= 5 # 相当于 a = a * 5
print(a) # 输出:20
# 除法赋值(/=):将左边变量除以右边的数值,并赋值给左边变量。
a = 10
a /= 3
print(a) # 输出:3.333...
# 幂赋值(**=):将左边变量的值进行右边数值次幂运算,并赋值给左边变量。
a = 2
a **= 3 # 相当于 a = a ** 3
print(a) # 输出:8
# 地板除法赋值(//=):进行地板除法运算,并赋值给左边变量。
a = 10
a //= 3
print(a) # 输出:3
# 取模赋值(%=):将左边变量对右边数值取模,并赋值给左边变量。
a = 10
a %= 3
print(a) # 输出:1
还有 BIF 内置函数的算数运算
# abs() - 计算绝对值
print(abs(5)) # 输出:5
print(abs(-5)) # 输出:5
print(abs(-3.5)) # 输出:3.5
# pow() - 计算幂
print(pow(2, 3)) # 输出:8
print(pow(2, -3)) # 输出:0.125
print(pow(5, 3, 7)) # 输出:6
# round() - 四舍五入
print(round(3.14159)) # 输出:3
print(round(3.14159, 2)) # 输出:3.14
print(round(3.5)) # 输出:4
print(round(3.5, 1)) # 输出:4.0
# sum() - 计算和
numbers = [1, 2, 3, 4, 5]
print(sum(numbers)) # 输出:15
# 支持起始值
print(sum(numbers, 10)) # 输出:25
# divmod() - 计算除法和余数
print(divmod(10, 3)) # 输出:(3, 1)
print(divmod(10.5, 3)) # 输出:(3.0, 1.5)
# id() - 获取对象标识符
a = 5
print(id(a)) # 输出:某个内存地址(例如:4488024968)
# hash() - 计算哈希值
print(hash(5)) # 输出:5
print(hash(3.14)) # 输出:某个整数值(例如:-1321801762)
# 数学运算的特殊情况
print(float('inf')) # 输出:inf
print(float('-inf')) # 输出:-inf
print(float('nan')) # 输出:nan
print(1 / 0.0) # 输出:inf
print(-1 / 0.0) # 输出:-inf
print(0.0 / 0.0) # 输出:nan
位运算
用于对整数的二进制表示进行操作,在底层编程中常用。
# 1. 按位与运算符 & : 对两个数的每一位进行“与”操作。只有当两个对应的位都是1时,结果位才是1,否则为0。
a = 3 # 二进制: 011
b = 5 # 二进制: 101
print(a & b) # 输出: 1 # 二进制: 001
# 2. 按位或运算符 | : 对两个数的每一位进行“或”操作。当两个对应的位中至少有一个是1时,结果位为1。
a = 3 # 二进制: 011
b = 5 # 二进制: 101
print(a | b) # 输出: 7 # 二进制: 111
# 3. 按位异或运算符 ^ : 对两个数的每一位进行“异或”操作。当两个对应的位不同时,结果位为1,否则为0。
a = 3 # 二进制: 011
b = 5 # 二进制: 101
print(a ^ b) # 输出: 6 # 二进制: 110
# 4. 按位取反运算符 ~ : 对一个数的每一位进行取反操作(0变1,1变0)。因为Python中整数使用补码表示,~a等于-a - 1。
a = 3 # 二进制: 011
print(~a) # 输出: -4 # 解释: ~3 = -(3 + 1) = -4
# 5. 左移运算符 << : 将一个数的二进制位向左移动指定的位数。左移相当于乘以2的幂次方。
a = 3 # 二进制: 011
print(a << 1) # 输出: 6 # 二进制: 110,相当于3 * 2^1
print(a << 2) # 输出: 12 # 二进制: 1100,相当于3 * 2^2
# 6. 右移运算符 >> : 将一个数的二进制位向右移动指定的位数。右移相当于除以2的幂次方的取整。
a = 6 # 二进制: 110
print(a >> 1) # 输出: 3 # 二进制: 011,相当于6 / 2^1
print(a >> 2) # 输出: 1 # 二进制: 001,相当于6 / 2^2
# 7. 赋值位运算符 : 除了以上基本运算符,Python还提供了对应的赋值运算符,用于简化代码。
a = 5 # 二进制: 101
a &= 3 # 等价于 a = a & 3
print(a) # 输出: 1 # 二进制: 001
比较运算
除了正常的比较运算>、>=、<、<=、==、!= 还有 <>、连续比较、is 、is not 判断
# 1. 等于 (==):判断两个值是否相等。
print(5 == 5) # 输出: True
print(5 == 3) # 输出: False
print('a' == 'a') # 输出: True
print('a' == 'b') # 输出: False
# 2. 不等于 (!= 或 <>): 判断两个值是否不相等。
print(5 != 5) # 输出: False
print(5 != 3) # 输出: True
print('a' != 'b') # 输出: True
# 3. 大于 (>): 判断左边的值是否大于右边的值。
print(5 > 3) # 输出: True
print(5 > 5) # 输出: False
print('b' > 'a') # 输出: True(因为 'b' 在字母表中比 'a'靠后)
# 4. 小于 (<): 判断左边的值是否小于右边的值。
print(5 < 3) # 输出: False
print(3 < 5) # 输出: True
print('a' < 'b') # 输出: True
# 5. 大于等于 (>=): 判断左边的值是否大于或等于右边的值。
print(5 >= 5) # 输出: True
print(5 >= 6) # 输出: False
print('b' >= 'a') # 输出: True
# 6. 小于等于 (<=): 判断左边的值是否小于或等于右边的值。
print(5 <= 5) # 输出: True
print(5 <= 4) # 输出: False
print('a' <= 'b') # 输出: True
# 7. **连续比较( Chain Comparisons **): 可以同时进行多个比较运算,简化代码。
# 等价于 3 < 5 并且 5 < 7
print(3 < 5 < 7) # 输出: True
print(3 < 5 < 4) # 输出: False
# 8. 字符串比较: 根据字母在字母表中的顺序或字符的Unicode值进行比较。
print('apple' < 'banana') # 输出: True(因为 'a' < 'b')
print('Z' < 'a') # 输出: True(因为大写字母的Unicode值小于小写字母)
print('hello' == 'hello') # 输出: True
print('world' != 'World') # 输出: True(因为大小写敏感)
# 9. 列表和元组比较: 逐元素比较,直到找到第一个不等的元素。
print([1, 2] < [1, 3]) # 输出: True
print([1, 2] > [1, 3]) # 输出: False
print([1, 2, 3] == [1, 2, 3]) # 输出: True
print((1, 2) < (1, 3)) # 输出: True
# 10. 特殊比较情况: 处理特殊的比较情形,如None、NaN等。
print(None == None) # 输出: True
print(float('nan') == float('nan')) # 输出: False(因为 NaN不等于自身)
print(1 < None) # 在Python 3中会引发TypeError
# 11. is 运算符: 比较对象的身份(即是否是同一个对象),而不是值是否相等。
a = 5
b = 5
c = 256
print(a is b) # 输出: True(在CPython中,小整数被缓存)
print(a is c) # 输出: False
print(id(a) == id(b)) # 输出: True
print(id(a) == id(c)) # 输出: False
# 12. 比较不同的数据类型: 比较不同类型的数据时,可能会引发TypeError或根据类型特性进行比较。
print(5 == '5') # 输出: False(因为整数和字符串类型不同)
print(True == 1) # 输出: True(因为布尔值是整数的子类,True=1,False=0)
print(True == 1.0) # 输出: False(因为不同类型)
print(5 > 'a') # 在Python 3中会引发TypeError
逻辑运算
and or not 与 c++ 处理方式别无二致。注意短路逻辑,类似于 c++ 的 && || 判断。&& 和 and 运算在左值为假时就停止,|| 和 or 运算在左值为真时就停止。
运算优先级 not > and > or
# 1. 与 (and): 只有当所有条件都为 True 时,结果才为 True,否则为 False。
print(True and True) # 输出: True
print(True and False) # 输出: False
print(5 > 3 and 5 < 10) # 输出: True
x = 5
print(x > 3 and x < 10) # 输出: True
# 2. 或 (or)只要有一个条件为 True,结果就是 True;只有所有条件都为 False 时,结果才为 False。
print(True or False) # 输出: True
print(False or False) # 输出: False
print(5 > 10 or 5 < 3) # 输出: False
print(5 > 3 or 5 < 3) # 输出: True
# 3. 非 (not): 将 True 转换为 False,将 False 转换为 True。
print(not True) # 输出: False
print(not False) # 输出: True
print(not (5 > 3)) # 输出: False
# 4. 逻辑运算的优先级: 在逻辑运算中,not 的优先级最高,接着是 and,最后是 or。在一个表达式中,如果同时使用了多个逻辑运算符,应该按照优先级执行。
print(False or True and False)
# 由于 and 的优先级高于 or,先计算 True and False,结果为 False
# 然后计算 False or False,结果为 False
print(False or (True and False)) # 输出: False
# 5. 短路评估: 在使用 and 和 or 运算时,Python 会进行短路评估
def a():
print("a被调用")
return True
def b():
print("b被调用")
return False
# 在以下表达式中,b() 不会被调用,因为 a() 已经返回 True
print(a() or b())
# 输出:
# a被调用
# True
# 6. 逻辑运算符的链式使用: Python 允许将逻辑运算符链式使用,从而简化代码。
print(1 < 5 and 5 < 10) # 等价于 (1 < 5) and (5 < 10),输出: True
print(1 < 5 or 5 > 10) # 等价于 (1 < 5) or (5 > 10),输出: True
# 7. any() 和 all() 函数: 用于处理多个条件的逻辑运算函数。
print(any([True, False, True])) # 输出: True
print(all([True, False, True])) # 输出: False
print(any([1, 0, []])) # 输出: True(非空对象为真)
print(all(['a', 'b', 'c'])) # 输出: True
作者:1lI