逻辑结构
- 线性结构:元素关系是一对一
- 树结构:一对多
- 图结构:多对多
物理结构
- 顺序存储:连续的内存
- 数组(c++)
- 数组元素类型要一样
- 数据长度固定
- 列表(Python)
- 列表元素可以不一样,但存储元素地址(32位机器:一个地址4个字节)
- 查询列表元素时,实际上是通过地址查找具体元素
- 插入和删除都是O(n)操作
- 栈
- 是一个数据集合,只能在一端进行插入或删除的列表
- 特点:LIFO(last-in, first-out)
- 操作:进栈li.append(),出栈 li.pop(),取栈顶 li[-1]
- 栈的应用:括号匹配
-
class Stack: def __init__(self): self.stack = [] def push(self, n): self.stack.append(n) def pop(self): return self.stack.pop() def gettop(self): if self.stack: return self.stack[-1] else: return None
-
队列
-
数据集合,仅允许一端插入,另一端删除
-
插入端为队尾(rear),插入称为进队或入队
-
删除端为队头(front),删除称为出队
-
队列特点:先进先出(First-in,First-out)
-
队列的实现方式:环形队列
-
当指针front (或rear) == Maxsize + 1时,再进一位,自动指向0
-
队首指针前进1:front = (front + 1) % MaxSize
-
队尾指针前进1:rear = (rear + 1) % MaxSize
-
队空条件:rear == front
-
队满条件:(rear + 1) % MaxSize == front
-
-
Python的内置队列模块
-
import queue 单向队列
-
from collections import deque 双向队列
-
q = deque(li, size) ## li 初始化队列元素,size最大长度
-
正向进队:append() 出队:popleft()
-
反向进队:appendleft() 出队:pop()
-
-
-
-
哈希表
-
由一个直接寻址表和一个哈希函数组成。
-
哈希函数h(k)将元素关键字作为自变量,返回元素的存储下标。
-
哈希冲突:哈希表大小有限,存储的数量无限,因此总有两个元素映射到同一个位置上。
-
开放寻址法:
-
拉链法:
-
哈希表应用:字典和集合、MD5算法/SHA2算法(密码)
-
- 数组(c++)
-
链式存储
-
链表
-
一系列节点组成的元素集合。
-
两部分:数据域和指针next
-
-
创建链表
-
头插法:head = Node(1); node.next = head; head = node
-
尾插法:head = Node(1); tail = head; tail.next = node; tail = node
-
插入
-
删除
-
-
双链表
-
三部分:前节点指针prior,item,后节点指针next
-
-
链表总结
-
优点:插入和删除操作O(1);内存分配灵活;链式存储对数和图结构有很大启发
-
-
树
-
n个节点的集合
-
二叉树:每个节点的度为2(2个分叉)
-
class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild = None
-
二叉树遍历方式
-
前序遍历:“根左右”
-
def preorder(root): if root: print(root.data, end=',') preorder(root.lchild) preorder(root.rchild)
-
中序遍历:“左根右”
-
后序遍历:“左右根”
-
层次遍历:一层一层
-
from collections import deque def level_order(root): q = deque() q.append(root) while len(q) > 0: node = q.popleft() print(node.data, end=',') if node.lchild: q.append(q.lchild) if node.rchild: q.append(q.rchild)
-
-
二叉搜索树bst
-
性质:lchild.key <= root.key, rchild.key >= root.key
-
查询、删除、插入
-
class BitreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild = None self.parent = None class BST: def __init__(self, li=None): self.root = None if li: for val in li: self.insert_no_rec(val) def insert(self, node, val): if not node: node = BiTreeNode(val) if val < node.data: node.lchild = self.insert(node.lchild, val) node.lchild.parent = node elif val > node.data: node.rchild = self.insert(node.rchild, val) node.rchild.parent = node return node def insert_no_rec(self, val): p = self.root if not p: self.root = BiTreeNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild else: p.lchild = BiTreeNode(val) p.lchild.parent = p return elif val > p.data: if p.rchild: p = p.rchild else: p.rchild= BiTreeNode(val) p.rchild.parent = p return else: return def pre_order(self, root): if root: print(root.data, end=',') self.pre_order(root.lchild) self.pre_order(root.rlchild) def in_order(self, root): if root: self.pre_order(root.lchild) print(root.data, end=',') self.pre_order(root.rlchild) def post_order(self, root): if root: self.pre_order(root.lchild) self.pre_order(root.rlchild) print(root.data, end=',') if __name__ == "__main__": bst = BST([4,6,2,3,1,8,7,9,5]) bst.pre_order(bst.root) print() bst.in_order(bst.root) print() bst.post_order(bst.root)
-
-
AVL树
-
自平衡的二叉搜索树
-
性质:
-
根的左右子树高度差绝对值不能超过1(平衡要求苛刻);
-
左右子树都是平衡二叉树
-
-
插入O(logn):可能导致不平衡,四种情况
-
右孩子的右子树插入:左旋
-
左孩子的左子树插入:右旋
-
左孩子的右子树插入:左旋 + 右旋
-
右孩子的左子树插入:右旋 + 左旋
-
-
-
红黑树
-
一种特殊的自平衡二叉搜索树
-
查找和插入O(logn)
-
四条性质:(平衡要求宽松(相对AVL树而言))
-
-
-