第三章 表 (栈还有队列的定义.)
这一章开始就是介绍一些经典的数据结构 .
1.表.
如果用数据实现的表,在删除还有插入中最坏 的情况是O(N) , 查找操作就是可以用常数的时间即 O(1) 能够快速的随机访问.
如果用链表来实现, 这里刚好是相反的.查找的操作 最坏的情况就是O(N),但是插入或者删除就是O(1)
2.iterator
------如果要用加强for循环 for(xx : xxx) xx 必须实现iterator 接口.
public interface Iterator<E> {
//如果是用增强for 循环的话 先调用next 和 hashNext
//这个方法能够判断后面能不能继续访问.
boolean hasNext();
// 在数组相当于后移了一格. 在链表中就是跳到下一个地址.
E next();
//相对于collection中的remove 方法.这个remove方法是在遍历中直接删除的.并且不容易引起 COoncurrentModificationException异常的出现
void remove();
}
public interface ListIterator<E> extends Iterator<E> {
//继承回来的.
boolean hasNext();
E next();
void remove ();
//拓展能够从后向前的遍历.boolean hasPrevious();
E previous();
int nextIndex ();int previousIndex ();
void set(E e);
void add(E e);
}
Iterator与ListIterator有什么区别?
- Iterator是ListIterator的父接口。
- Iterator是单列集合(Collection)公共取出容器中元素的方式。
- 对于List,Set都通用。
- 而ListIterator是List集合的特有取出元素方式。
- Iterator中具备的功能只有hashNext(),next(),remove();
- ListIterator中具备着对被遍历的元素进行增删改查的方法,可以对元素进行逆向遍历。
- 之所以如此,是因为ListIterator遍历的元素所在的容器都有索引。
栈
栈的定义
栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
- 通常称插入、删除的这一端为栈顶 (Top),另一端称为栈底 (Bottom)。
- 当表中没有元素时称为空栈。
- 栈为后进先出(Last In First Out)的线性表,简称为 LIFO 表。
- 栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"
栈的应用
- 平衡符号
- 后缀表达式.
- 中缀到后缀的转换
- 方法的调用(这个是重点.)
第四章 树
只能说简单的看懂了.但是没有做过几题题目什么的.只能空想主义了.!
- 二叉查找树(二叉排序树)
- 平衡二叉树(AVL树)
- 红黑树
- B-树
- B+树
- 字典树(trie树)
- 后缀树
- 广义后缀树
第五章 散列
数组能够提供快速随机访问,但是难以拓展. 链表容易做增加删除,但是在查找的时候开销很大.
散列表提供了达到此目标的一种方法。
简单的术语:
- 关键字:元素的存储部分,数据库的元素通过它进行存储,查找等操作(也称作散列关键字)
- 散列表元:散列数组的某个位置,其后跟着另外一个包含其元素的结构
- 散列函数:对关键字和散列表元提供映射的函数
- 完全散列函数:对关键字和整数提供一一映射的函数
散列函数:
下面是一个最原始的散列 函数
但是最后散列的结果并不均匀. 书本上还提供了另外两种,但是我更想看看java 底层的hash 方法.
public static int hash(String key,int tableSize){
int hashVal = 0;
/**
* 这里对字符串key 中的每个字母进行相加,得到一个 hasVal;
*/
//模运算,看看这个值最后落到那个桶里面
return hashVal % tableSize ;
}
//计算hash值的方法 通过键的hashCode来计算
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
当hash函数出现相同值的时候 就会发现冲突.
解决冲突的方法有下列几种
1.开放定址法
开放定址法的一般形式为: hi=(h(key)+di)%m 1≤i≤m-1
di为增量序列 有三种增量 线性,平方,随机
2.再哈希法:即重新计算哈希函数地址. 知道冲突不再发生.
3.链地址法: 将所有关键字为同义词的结点链接在同一个单链表中 ,这个也是hashmap所实现的方法.
4.建立一个公共溢出区.
链地址法与开放定址法相比,拉链法有如下几个优点:
- (1)链地址法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
- (2)由于链地址法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
- (3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
- (4)在用链地址法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将 被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。 因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。
链地址法的缺点
链地址法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。
链地址法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。
hashmap源码解读
http://www.cnblogs.com/ITtangtang/p/3948406.html