* <第5章> 散列表 </第5章>
* 5.1 散列函数
* (1)它必须是一致的
* (2)它应将不同的输入映射到不同的数字
* (3)总是将同样的输入映射到相同的索引
* (4)将不同的输入映射到不同的索引
* (5)数知道数组有多大,只返回有效的索引
* 5.2 冲突(Hash碰撞)
* (1)给两个键分配的位置相同。如果两个键映射到了同一个位置,就在这个位置存储一个链表
* (2)要避免冲突,需要有较低的填装因子和良好的散列函数
* 5.3 性能
* (1)在平均情况下,散列表执行各种操作的时间都为O(1)
* 5.3.1 填充因子
* (1)填装因子度量的是散列表中有多少位置是空的
* (2)一个不错的经验规则是:一旦填装因子大于0.7,就调整散列表的长度
* <第6章> 广度优先搜索 </第6章>
* 6.1 图
* (1)图由节点和边组成
* (2)用于模拟不同的东西是如何相连的
* 6.2 广度优先搜索
* (1)广度优先搜索是一种用于图的查找算法
* 6.2.1 查找最短路径
* (1)从节点A出发,有前往节点B的路径吗?
* (2)从节点A出发,前往节点B的哪条路径最短?
* 6.2.2 队列
* (1)队列是一种先进先出(First In First Out,FIFO)的数据结构
* (2)栈是一种后进先出(Last In First Out,LIFO)的数据结构
* 6.3 实现图
* (1)有向图(directed graph),其中的关系是单向的
* (2)无向图(undirected graph)没有箭头,直接相连的节点互为邻居
* (3)散列表
* (4)树是一种特殊的图,其中没有往后指的边
* (5)如果任务A依赖于任务B,在列表中任务A就必须在任务B后面。这被称为拓扑排序,使用它可根据图创建一个有序列表
* 6.4 实现算法 示例:{@link BreadthFirst}
* 6.5 运行时间
* (1)O(V+E),V是顶点(vertices)数,E为边数
* 6.6 小结
* (1)广度优先搜索指出是否有从A到B的路径
* (2)如果有,广度优先搜索将找出最短路径
* (3)面临类似于寻找最短路径的问题时,可尝试使用图来建立模型,再使用广度优先搜索来解决问题
* (4)有向图中的边为箭头,箭头的方向指定了关系的方向,例如,rama→adit表示rama欠adit钱
* (5)无向图中的边不带箭头,其中的关系是双向的,例如,ross - rachel表示“ross与rachel约会,而rachel也与ross约会”
* (6)队列是先进先出(FIFO)的,栈是后进先出(LIFO)的
* (7)你需要按加入顺序检查搜索列表中的人,否则找到的就不是最短路径,因此搜索列表必须是队列
* (8)对于检查过的人,务必不要再去检查,否则可能导致无限循环
/**
* 广度优先算法
*/
public class BreadthFirst {
// 用来表示图的数据结构
private static final Map<String, String[]> graphMap = new HashMap<>();
// 搜索队列
private static final Queue<String> searchQueue = new LinkedBlockingQueue<>();
// 用于记录被搜索过的人
private static final List<String> searched = new ArrayList<>();
/**
* 查询传入的人名是否满足条件
*
* @param name
* @return
*/
private static boolean search(String name) {
searchQueue.clear();
searched.clear();
// 获取一度关系
String[] firstNames = graphMap.get(name);
// 入队
Collections.addAll(searchQueue, firstNames);
// 只要队列还有元素就继续搜索
while (searchQueue.size() > 0) {
// 出队
String person = searchQueue.poll();
// 如果没有被搜索过
if (!searched.contains(person)) {
// 如果满足条件
if (isSeller(person)) {
System.out.println(person + " is a mango seller!");
return false;
} else {
// 获取二度或多度关系
String[] deepNames = graphMap.get(person);
if (deepNames != null) {
// 入队
Collections.addAll(searchQueue, deepNames);
searched.add(person);
}
}
}
}
return true;
}
private static boolean isSeller(String person) {
return person.contains("x");
}
public static void main(String[] args) {
graphMap.put("a", new String[]{"b", "c", "d"});
graphMap.put("b", new String[]{"b1", "b2"});
graphMap.put("c", new String[]{"c1", "c2"});
graphMap.put("d", new String[]{"x"});
graphMap.put("c1", new String[]{"x"});
if (search("a")) {
System.out.println("no mango seller!");
}
if (search("b")) {
System.out.println("no mango seller!");
}
}
}