数据结构与算法
数组与矩阵
- 数组测存储地址计算
- 一维数组a[n]: a[i] = a + i * len
- 二维数组a[m][n]:
- 按行存储: a[i][j] = a + (i * n + j) * len
- 按列存储: a[i][j] = a + (j * m + i) * len
- 矩阵计算
- 在矩阵中下标分别为 i 和 j 的元素,对应的一维数组的下标计算公式:代入排除法;
- 上三角计算公式:(2n - i + 1) * i / 2 + j
- 下三角计算公式:(i + 1) * i / 2 + j
线性表
- 顺序表(数组)
- 链表
- 单链表
- 双链表
- 循环链表
- 队列:先进先出(两端可同时操作)
循环队列
对空条件:头 = 尾
队满条件: (尾 + 1)% 总元素 = 头 - 栈:先进先出(只有一端可操作)
广义表
是n个表元素组成的有限序列,是线性表的推广
- 长度:最外层包含的元素个数
- 深度:包含括号的重数
- 表头head:第一个元素
- 表尾tail:除第一个元素以外的所有元素
若有:LS=(a, (b,c), (d, e)),则长度为3,深度为2;
head(LS) = a, tail(LS) = ((b, c), (d, e))
若要将b取出的操作:head(head(tail(LS)))
树与二叉树
二叉树的重要特性
- 在二叉树的第 i 层上最多有 2^(i-1) 个结点(i≥1)
- 深度为 k 的二叉树最多有 2^k - 1 个结点(k≥1)
- 对于任何一颗二叉树,叶子结点数n0 = 度为2的结点数n2 + 1
二叉树遍历
- 前序遍历
- 中序遍历
- 后序遍历
- 层次遍历
树转二叉树
- 第一个孩子结点 --> 左子树结点
- 兄弟节点 --> 右孩子结点
查找二叉树
- 左 < 根 < 右
哈夫曼树(最优二叉树)
- 权:叶子结点的数值
- 带权路径长度:权值 * 路径长度
线索二叉树
记录前继/后继
平衡二叉树
左右子树的高度之差的绝对值 ≤1,并且左右子树都是平衡二叉树
图
- 存储
- 邻接矩阵:图有N个结点就是N x N的矩阵,顶点 i 到顶点 j有连接,则矩阵对应的 Rij = 1,否则 Rij = 0
- 邻接表:顶点与顶点的连接用链表 表示,用一维数组顺序存储每个链表的头指针
- 遍历
- 深度优先dfs:从上往下,一个结点搜索到底
- 广度优先bfs:按层搜索,一层搜索完再开始下一层
- 拓扑排序:用一个序列表达,一个图当中哪些事件可以先执行,哪些应该后执行
- 最小生成树
- Prim普里姆算法:从一个结点出发,找距离最小的结点
- Kruskal克鲁斯卡尔算法:缺点要选几条边,从最小的开始选,注意不要产生环路
重要
循环队列中,rear为队尾位置,其移动方式按rear=(rear+1)mod m进行,length表示当前循环队列中的元素个数,,则循环队列的队首元素的实际位置是
(1 + rear + m - length) mod m