1,栈和队列
栈:后进先出的数据结构;具有的基本操作:压栈(push),弹栈(pop),取栈顶元素(top),判断栈是否为空(empty);
栈的上溢和下溢(对一个已经满的栈执行push操作,称为上溢;对一个已经为空的栈执行pop操作,称为下溢)
队列:后进后出的数据结构;基本操作:入队(enQueqe),出队(deQueqe)
队列的实现方式:环型数组,链表;
2,链表
链表是一种顺序访问结构(意味着要想访问某个位置上的元素,必须从某个当前可访问的位置顺序查找链表;想想磁带的读取就会明白;区别于数组的随机访问)。
| 访问方式 | 长度 | 存储分配 | 内存区 | 插入元素 | 内存使用效率 |
链表 | 顺序访问 | 不固定 | 动态 | 堆区 | 易 | 高,需要额外的内存空间(next域指针) |
数组 | 随机方位 | 固定 | 静态 | 栈区 | 难 | 低,但不需额外的内存空间 |
P.S.数组的存储区和数组长度:
假如使用静态的方式声明一个数组:int a[100];那么该数组保存在栈区;如果使用new运算符或者malloc函数申请数组,如int *a=new int[100],那么数组保存在堆区;
关于数组长度:数组长度并不保存在程序代码区、数据存储区的某处;对于C/C++来说,使用sizeof(array)可以获取数组所占的内存空间的大小,那么sizeof(array)/sizeof(array[0])可以获得数组的长度。
3,树
3.1 二叉树:
二叉树的前中后序遍历:递归方式的实现;
二叉树的层次遍历:使用队列这一辅助数据结构实现;方法:
1,初始化:根节点入队;
2,循环:
如果队列非空
队首元素出队并输出;
队首元素的lchild和rchild(如果有)入队;
使用二叉树的前/后序遍历和中序遍历,可以倒退出二叉树的结构;但是,如果给出二叉树的前序遍历和后序遍历,并不能保证推导出二叉树的结构。给出二叉树的前序遍历和中序遍历,倒退二叉树的方法可表示为:
1,对于前序遍历来说,遍历结果的第一个元素是二叉树的根;在中序遍历结果中,这个根将中序遍历结果分为两部分,前一部分是左子树的中序遍历结果,后一部分是右子树的中序遍历结果;
2,由此可以查前序遍历结果,分别得到左右子树的前序遍历结果;
3,递归求解左右子树的结构。
3.2 分支树无限制的有根树
左孩子右兄弟的表示方式
4,散列表
4.1,直接寻址表
不会出现碰撞的情况;空间浪费较大,实现简单;
4.2,散列表
如何解决碰撞问题?——》链接法;开放寻址法。
开放寻址法中的探查方法:线性探查;二次探查;双重散列。
散列函数的设计方法:除法散列法,乘法散列法,全域散列;
常见的字符串hash函数:SDBM算法,RS算法,ELF算法等;杂凑函数:MD5,SHA1;
4.3,二叉查找树、红黑树和AVL树
二叉查找树的性质:(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;(3)左、右子树也分别为二叉查找树。二叉查找树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的节点时再进行插入。新插入的结点一定是一个新添加的叶子节点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。
红黑树:是一种自平衡的二叉查找树。可以在O(log n)时间内完成查找、插入和删除;红黑树的统计性能要好于AVL树。红黑树的性质,除一般二叉查找树的性质外,还包括:
性质1. 节点是红色或黑色。
性质2. 根是黑色。
性质3 每个叶节点是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些性质保证了,在红黑树中根到叶子节点的最长路径不超过最短路径的两倍。
AVL树:AVL是最先发明的自平衡二叉查找树算法。在AVL中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。