ADT(Abstract Data Type)
抽象数据结构只定义操作,不定义具体实现。抽象数据类型的定义仅仅取决于它的一组逻辑特性,而与它在计算机中的表示和实现无关。例如,大一C语言里实现过的学生管理系统里,我们就定义了一个抽象数据类型student,它封装了姓名,学号,成绩三个不同类型的变量。
Stack
栈也可以看成是一种抽象数据结构,经典的五个操作init push pop top destroy,可能还有isEmpty之类的。
stack的具体实现:采用链表或可变长数组
GrabBag
四个操作:insert(int x); remove; sample; size(int i)
在remove实现中,明显用数组更快。只需要把要remove的元素和最后一个元素交换,然后把数组的长度减少1即可。如果用链表就要一个一个遍历,浪费时间。
java中的接口并不是绝对抽象的。因为可能包含一些实现的细节,如初始方法。
Map
图在图论中已经进行过深入研究。
Java Libraries
java已经提供了很多内置包。如utils.
Binary Search Trees(二叉搜索树)
链表中搜索一个项目需要很长时间。在二进制搜索中,由于列表是排序的,因此我们只需要二分法搜素就能很快找到元素。但如何对链表进行二进制搜索呢?我们必须一直遍历到中间位置,才能检查那里的元素,而这本身就需要线性时间!
我们可以实现的一种优化方法是对中间节点进行引用,这样二分的时候速度就升高了一些,平均搜索时间减少了一半。
我们可以递归地重复这一步,直到把一个链表变成一个二叉树。
定义
树:两个节点之间只能有一条路。
二叉搜索树里,我们让每个节点的左子节点小于该节点,右节点大于该节点。
不能有大小完全相同的节点。
操作
查找
- 从根节点开始,如果目标等于当前节点,则return;
- 小于当前节点,则左移;
- 大于当前节点,则右移。
本质上等同于二分法,而且操作简单。用时减少到logN。
插入
总是向最下面插入叶子。首先,我们在树中搜索节点。如果找到了,就什么也不用做。如果没有找到,我们就已经在叶子节点上了。此时,我们可以将新元素添加到叶子节点的左侧或右侧,同时保留 BST 属性。
static BST insert(BST T, Key ik) {
if (T == null)
return new BST(ik);
if (ik ≺ T.key)
T.left = insert(T.left, ik);
else if (ik ≻ T.key)
T.right = insert(T.right, ik);
return T;
}
删除
删除操作面临三种不同的情况:没有子节点、有一个子节点、两个子节点。
没有子节点很简单。
一个子结点:让要删除的节点的父节点指向要删除节点的子节点。
二个子节点:这种情况是比较复杂的,为了不破坏二叉查找书的结构,我们可以按照以下操作进行:
- 找出左子树中最大或者右子树中最小的值val
- 将当前节点的值替换为val
- 在左子树或者右子树中找到val删除
11.1 平衡搜索树(Balanced Search Trees)
BST Tree Height
最好的情况(完全树)Θ(log N)
最坏的情况(一条线) Θ(N)
大O代表小于等于,所以大O可能是不精确的。大Θ是精确的。
Height and Depth
节点深度指它离根节点多远。
树的高度指它最深的叶子节点的高度。
平均高度指树的节点的平均深度。