数据结构
- 程序=算法+数据结构
- 四类基本数据结构:集合、线性、树形、图形
- 逻辑结构:线性结构、非线性结构(树、图)
- 面向对象特点:封装、继承、多态
- 类的作用:代码复用
- 线性表:除了第一个元素和最后元素,其余每个元素只有一个直接前驱和直接后继。
特点:同一性、有穷性、有序性
存储结构:顺序、链式
- 顺序表:关系线性化、结点顺序存
优点:方便随机存取;无需为表现结点间的逻辑关系增加额外存储空间
缺点:插入删除效率低;预先静态分配存储空间,规模难以确定
- 单链表:只关注逻辑顺序,不关心实际存储位置,结点指针域存储直接后继地址
- 循环链表:首尾相接的链表
- 双向链表:增加前驱指针域,可快速确定某一结点的前驱
- 栈:LIFO线性表(顺序栈、链栈)
- 递归:定义自身的同时又出现了对自身的引用
- 队列:FIFO线性表,链队列、循环队列(判满:标志位或损失一个元素空间)
- 顺序存储和链式存储要点:
- 顺序栈受事先开辟的容量限制可能上溢,进栈和入队需要判满,以免上溢
- 循环队列是一种顺序队列,通过模运算看成首尾相接的环。判空判满用标志位或损失一个元素空间(判满:(rear+1)mod MAXSIZE==front判空:rear==front)
- 链队列实现与单链表相似,链队列需要设置尾指针,封装在结构体
- 消除递归:用循环转换为线性操作;自定义栈模拟系统栈
- 字符串的三种存储方式:
- 定长顺序串:一维数组作为静态存储结构
- 堆串:以动态分配的方式产生地址连续的存储单元,顺序存放字符
- 块链串:以链表为存储结构
- 数组:顺序存储结构,随机存取(依靠下标)
- 广义表:n个元素的有限序列,元素也可以是广义表
- 压缩存储:有规律(对称、带状)的矩阵(建立数学函数做映射);稀疏矩阵(只存储非零元素行号、列号、元素值。三元组、十字链表)
- 二叉树:度不大于2;孩子结点次序不能任意颠倒
二叉树的存储结构:
- 顺序存储:对于一般的二叉树,需要用虚结点补为完全二叉树来存储,会造成空间浪费,最坏情况下,只有右子树的二叉树,k个结点需要2k-1个存储单元。如:
A#B###C#######D
- 链式存储:数据域、左孩子域、右孩子域
- 满二叉树:深度为k且有2k-1个结点的二叉树
完全二叉树:位置序号与满二叉树对应
满二叉树必为完全二叉树,反之不一定
- 二叉树的遍历:n个结点的二叉树,每个结点入栈出栈各执行n次,结点访问n次。递归遍历算法时间复杂度为O(n)。
- 先序遍历:根左右(ABDFGCEH)
- 中序遍历:左根右(BFDGACEH)
- 后序遍历:左右根(FGDBHECA)
- 线索二叉树:LChild | LTag | Data | RTag | RChild
LTag/Rtag=0:LChild/RChild指示结点左/右孩子
LTag/Rtag=1:LChild/RChild指示结点前驱/后继
- 树的存储结构:
- 双亲表示法:Data | Parent (0,A,-1)(1,B,0)(2,C,0)……
- 孩子表示法:Data | Child (0,A,1,2)(1,B,3,4,5)……
- 孩子兄弟表示法:# A # (每个结点两个链域,分别指向第一孩子和右兄弟)
- 哈夫曼树(最优二叉树):n个带权叶子结点构成的二叉树中带权路径最短的二叉树
(权小的结点放在树的最深层,权大的离树根近)哈夫曼编码是最优前缀编码
- 图的存储结构:
- 邻接矩阵表示法:Aij=wij(反之∞)
- 邻接表表示法:(1,A,2,3)(2,B,#)……
- 十字链表
- 邻接多重表
- 图的遍历:
- 深度优先搜索:按深度方向搜索,先根遍历的推广
- 广度优先搜索:按广度方向搜索,层次遍历
- 查找:
- 比较式查找法:
- 基于线性表:主要用于查找,不做插入删除,静态查找表
- 顺序查找:所给关键字与线性表中各个元素的关键字逐个比较
- 折半查找(二分查找,利用中间位置将表分两个子表):要求表必须是顺序存储;必须按关键字有序排列
优点:比较次数少,查找速度快,平均性能好
缺点:要满足两个要求,使得插入删除困难
适用于不经常变动的,查找频繁的有序序列
- 分块查找:将列表分成若干个块,构造索引表,索引表按关键字有序排列
- 基于树:不仅用于查找,还要对表做插入删除,动态查找表
- 二叉排序树:O(log2n),左孩子关键字小于根,右孩子关键字大于根
优点:同折半查找,且插入删除无需移动大量结点,适用于经常变化的动态表
缺点:构造形态与输入顺序有关,各分支高度可能相差悬殊,如有序输入
- 平衡二叉树:O(log2n),左右子树高度差小于等于1,左右子树也是平衡二叉树
优点:插入结点失衡会及时调整,保持平衡因子绝对值小于等于1,解决了二叉排序树各分支高度可能相差悬殊的问题
- B树
- 哈希查找法:既是建表的方法,又是查找的方法,计算式检索
p=H(k),p存储位置,k关键字,H哈希函数,查找k即通过H函数计算存储位置p
哈希函数构造方法:数字分析法、平方取中法、分段叠加法、除留余数法、伪随机数法
处理冲突的方法:开放地址法(线性探测再散列、二次探测再散列、伪随机探测再散列)、再哈希法、链地址法
- 内部排序:
- 插入类排序:
- 直接插入排序:O(n2),稳定
- 折半插入排序:利用折半思想确定有序表中插入位置,O(n2),比较时间复杂度为O(nlogn),稳定
- 希尔排序:利用直接插入的最好情况:n比较小,基本有序,O(n1.5),不稳定
- 交换类排序:
- 冒泡排序:反复扫描记录序列,顺次比较相邻两个元素大小,若逆序就交换,O(n2),稳定
- 快速排序:交换不相邻的两个元素,消除多个逆元,O(nlog2n),不稳定
- 选择类排序:
- 简单选择排序:每趟选择一个最小的与当前首位交换,O(n2),不稳定
- 树形选择排序:排序比较过程中记录元素大小关系,O(nlog2n),稳定
- 堆排序:将存储在向量中的数据元素看成一颗完全二叉树,减少了辅助空间,O(nlog2n),不稳定
- 归并排序:基于合并,把两个或两个以上有序表合并成新有序表,O(nlog2n),稳定