参考
- b站视频链接:www.bilibili.com/video/BV1x7…
- 参考的github笔记:github.com/XPoet/JS-Da…
字典(dict) | 映射(Map)
- { key:value },以键值对存储元素
- key不可以重复,value可以重复,类似js中的Object
function Dictionary() {
// 字典属性
this.items = {};
// set(key,value):往字典添加键值对
Dictionary.prototype.set = function (key, value) {
this.items[key + ""] = value;
return true;
};
// has(key):判断字典中是否含有某个key
Dictionary.prototype.has = function (key) {
return this.items.hasOwnProperty(key + "");
};
// remove(key):根据key从字典中移除键值对
Dictionary.prototype.remove = function (key) {
if (!this.has(key)) return false;
delete this.items[key + ""];
return true;
};
// get(key):根据key去获取value
Dictionary.prototype.get = function (key) {
if (!this.has(key)) return undefined;
return this.items[key + ""];
};
// keys():以数组的形式返回所有的keys
Dictionary.prototype.keys = function () {
return Object.keys(this.items);
};
}
// 测试代码
var dictionary = new Dictionary();
console.log(dictionary.set("name", "hao"));
console.log(dictionary.set("age", 18));
console.log(dictionary.keys());
console.log(dictionary.get("age"));
console.log(dictionary.remove("name"));
console.log(dictionary.get("name"));
console.log(dictionary.keys());
图(Graph)
-
六度空间理论
- 世界上任何两个互相不认识的人,只需要很少的中间人就可以建立联系
-
适用于复杂的关系网
-
由一组顶点(Vertex)、一组边(Edge)变构成
- 相邻顶点:由一条边连接的两个顶点
- 度:相邻顶点的数量
- 路径:从一个顶点到另一个顶点所经过的顶点序列:V1、V2...
-
邻接矩阵表示法
- 行列数为顶点数,矩阵值代表顶点间的关系
- A、B、C -> 0、1、2
- A、B、C -> 0、1、2
- 行列数为顶点数,矩阵值代表顶点间的关系
[
[0,1,1],
[1,0,0],
[1,0,0]
]
- 邻接表表示法
- 由每个顶点和此顶点的相邻顶点列表组成
- 由每个顶点和此顶点的相邻顶点列表组成
- 图的遍历:每个顶点访问一次,不能重复访问同一顶点
- BFS(Breadth-First Search)
- A、B、C、D、F、E、G、H、I
- DFS(Depth-First Search)
- A、B、E、I、F、C、D、G、H
- BFS(Breadth-First Search)
- Stack
function Stack(){
this.items = [];
// push(Element):将元素压入栈
Stack.prototype.push = function(Element){
this.items.push(Element);
}
// pop():取出栈顶元素
Stack.prototype.pop = function(){
return this.items.pop();
}
// peek():查看栈顶元素
Stack.prototype.peek = function(){
return this.items[this.items.length - 1];
}
// isEmpty():判断栈是否空
Stack.prototype.isEmpty = function(){
return this.items.length === 0;
}
// size():获取栈中元素个数
Stack.prototype.size = function(){
return this.items.length;
}
// toString():将栈结构用字符形式表示
Stack.prototype.toString = function(){
var resultString = '';
for(var i = 0; i < this.items.length; i ++){
resultString += this.items[i] + '';
}
return resultString;
}
}
- Queue
function Queue(){
this.items = [];
// enqueue(element)
Queue.prototype.enqueue = function(element){
this.items.unshift(element);
}
// dequeue()
Queue.prototype.dequeue = function(){
return this.items.pop();
}
// front():返回队头元素
Queue.prototype.front = function(){
return this.items[this.items.length - 1];
}
// isEmpty()
Queue.prototype.isEmpty = function(){
return this.items.length === 0;
}
// size()
Queue.prototype.size = function(){
return this.items.length;
}
// toString()
Queue.prototype.toString = function(){
var result = '';
for(var i = 0; i < this.items.length; i ++){
result += this.items[i];
}
return result;
}
}
- Graph
/*
边用字典结构,key存储顶点,[]存储邻接顶点
{
'A':[],
'B':[],
...
}
*/
function Graph() {
this.vertexes = []; // 顶点
this.edges = new Dictionary(); // 边
// addVertex(v):添加顶点
Graph.prototype.addVertex = function (v) {
this.vertexes.push(v);
this.edges.set(v, []);
};
// addEdge(v1,v2):添加边
Graph.prototype.addEdge = function (v1, v2) {
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
};
// toString():用字符形式表示邻接表
Graph.prototype.toString = function () {
var Rstr = "";
for (var i = 0; i < this.vertexes.length; i++) {
Rstr += this.vertexes[i] + ":";
Rstr += this.edges.get(this.vertexes[i]).join(" ");
Rstr += "\n";
}
return Rstr;
};
// initializeColor():返回顶点颜色状态数组
Graph.prototype.initializeColor = function () {
var colors = [];
for (var i = 0; i < this.vertexes.length; i++) {
colors[this.vertexes[i]] = "white";
}
return colors;
};
// 初始化状态颜色:
// 白色(未入队或栈、未访问此节点)
// 灰色(已入队或栈,未访问)
// 黑色(已入队或栈,已访问)
// bfs():广度优先搜索
Graph.prototype.bfs = function (v) {
var bfsStr = "";
// 1、获取顶点颜色状态数组
var colors = this.initializeColor();
// 2、创建队列,用于存储顶点
var queue = new Queue();
queue.enqueue(v);
colors[v] = "gray";
// 3、遍历非空队列
while (!queue.isEmpty()) {
// 3.1、取出队头元素
var v_head = queue.dequeue();
// 3.2、取出队头元素的邻接顶点,遍历邻接顶点,将是白色状态的数组入队,置为灰
var nearEdges = this.edges.get(v_head);
for (var i = 0; i < nearEdges.length; i++) {
var tempEdges = nearEdges[i];
if (colors[tempEdges] == "white") {
queue.enqueue(tempEdges);
colors[tempEdges] = "gray";
}
}
bfsStr += v_head + "->";
colors[v_head] = "black";
}
return bfsStr;
};
// dfs():深度优先搜索,非递归:用栈存储实现
Graph.prototype.dfs = function (v) {
var bfsStr = "";
// 1、获取顶点颜色状态数组
var colors = this.initializeColor();
// 2、创建栈,用于存储顶点
var stack = new Stack();
stack.push(v);
colors[v] = "gray";
// 3、遍历非空栈
while (!stack.isEmpty()) {
// 3.1、取出栈顶元素
var v_head = stack.pop();
// 3.2、取出栈顶元素的邻接顶点,遍历邻接顶点,将是白色状态的数组入队,置为灰
var nearEdges = this.edges.get(v_head);
for (var i = 0; i < nearEdges.length; i++) {
var tempEdges = nearEdges[i];
if (colors[tempEdges] == "white") {
stack.push(tempEdges);
colors[tempEdges] = "gray";
}
}
bfsStr += v_head + "->";
colors[v_head] = "black";
}
return bfsStr;
};
// 递归实现dfs
Graph.prototype.dfs = function (v, colors) {
// 1、每次递归将顶点置为灰色
colors[v] = "gray";
console.log(v);
// 2、遍历邻接顶点,将白色状态的邻接顶点进行递归调用
var nearEdges = this.edges.get(v);
for (var i = 0; i < nearEdges.length; i++) {
var temp_edges = nearEdges[i];
if (colors[temp_edges] == "white") {
this.dfs(temp_edges, colors);
}
}
colors[v] = "black";
};
}
// 测试代码
var graph = new Graph();
var myVertexes = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (var i = 0; i < myVertexes.length; i++) {
graph.addVertex(myVertexes[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
console.log(graph.toString());
console.log(graph.initializeColor());
console.log(graph.bfs(graph.vertexes[0]));
console.log(graph.dfs(graph.vertexes[0], graph.initializeColor()));
- 队列实现bfs、栈实现的dfs
- bfs把B作为了第一个邻接顶点
- dfs把D作为了第一个邻接顶点
- 递归实现的dfs
- 把B作为了A的第一个邻接顶点
- 把B作为了A的第一个邻接顶点
完整代码
function Dictionary(){
// 字典属性
this.items = {};
// set(key,value):往字典添加键值对
Dictionary.prototype.set = function(key,value){
this.items[key + ''] = value;
return true;
}
// has(key):判断字典中是否含有某个key
Dictionary.prototype.has = function(key){
return this.items.hasOwnProperty(key + '');
}
// remove(key):根据key从字典中移除键值对
Dictionary.prototype.remove = function(key){
if(!this.has(key))
return false;
delete this.items[key + ''];
return true;
}
// get(key):根据key去获取value
Dictionary.prototype.get = function(key){
if(!this.has(key))
return undefined;
return this.items[key + ''];
}
// keys():以数组的形式返回所有的keys
Dictionary.prototype.keys = function(){
return Object.keys(this.items);
}
}
function Queue(){
this.items = [];
// enqueue(element)
Queue.prototype.enqueue = function(element){
this.items.unshift(element);
}
// dequeue()
Queue.prototype.dequeue = function(){
return this.items.pop();
}
// front():返回队头元素
Queue.prototype.front = function(){
return this.items[this.items.length - 1];
}
// isEmpty()
Queue.prototype.isEmpty = function(){
return this.items.length === 0;
}
// size()
Queue.prototype.size = function(){
return this.items.length;
}
// toString()
Queue.prototype.toString = function(){
var result = '';
for(var i = 0; i < this.items.length; i ++){
result += this.items[i];
}
return result;
}
}
function Stack(){
this.items = [];
// push(Element):将元素压入栈
Stack.prototype.push = function(Element){
this.items.push(Element);
}
// pop():取出栈顶元素
Stack.prototype.pop = function(){
return this.items.pop();
}
// peek():查看栈顶元素
Stack.prototype.peek = function(){
return this.items[this.items.length - 1];
}
// isEmpty():判断栈是否空
Stack.prototype.isEmpty = function(){
return this.items.length === 0;
}
// size():获取栈中元素个数
Stack.prototype.size = function(){
return this.items.length;
}
// toString():将栈结构用字符形式表示
Stack.prototype.toString = function(){
var resultString = '';
for(var i = 0; i < this.items.length; i ++){
resultString += this.items[i] + '';
}
return resultString;
}
}
// 通过邻接表实现图的表示
/*
边用字典结构,key存储顶点,[]存储邻接顶点
{
'A':[],
'B':[],
...
}
*/
function Graph(){
this.vertexes = [];// 顶点
this.edges = new Dictionary();// 边
// addVertex(v):添加顶点
Graph.prototype.addVertex = function(v){
this.vertexes.push(v);
this.edges.set(v,[]);
}
// addEdge(v1,v2):添加边
Graph.prototype.addEdge = function(v1,v2){
this.edges.get(v1).push(v2);
this.edges.get(v2).push(v1);
}
// toString():用字符形式表示邻接表
Graph.prototype.toString = function(){
var Rstr = '';
for(var i = 0; i < this.vertexes.length; i ++){
Rstr += this.vertexes[i] + ':';
Rstr += this.edges.get(this.vertexes[i]).join(' ');
Rstr += '\n';
}
return Rstr;
}
// initializeColor():返回顶点颜色状态数组
Graph.prototype.initializeColor = function(){
var colors = [];
for(var i = 0; i < this.vertexes.length; i ++){
colors[this.vertexes[i]] = 'white';
}
return colors;
}
// bfs():广度优先搜索
Graph.prototype.bfs = function(v){
var bfsStr = '';
// 1、获取顶点颜色状态数组
var colors = this.initializeColor();
// 2、创建队列,用于存储顶点
var queue = new Queue();
queue.enqueue(v);
colors[v] = 'gray';
// 3、遍历非空队列
while(!queue.isEmpty()){
// 3.1、取出队头元素
var v_head = queue.dequeue();
// 3.2、取出队头元素的邻接顶点,遍历邻接顶点,将是白色状态的数组入队,置为灰
var nearEdges = this.edges.get(v_head);
for(var i = 0; i < nearEdges.length; i ++){
var tempEdges = nearEdges[i];
if(colors[tempEdges] == 'white'){
queue.enqueue(tempEdges);
colors[tempEdges] = 'gray';
}
}
bfsStr += v_head + '->'
colors[v_head] = 'black';
}
return bfsStr;
}
// dfs():深度优先搜索,非递归:用栈存储实现
/*
Graph.prototype.dfs = function(v){
var bfsStr = '';
// 1、获取顶点颜色状态数组
var colors = this.initializeColor();
// 2、创建栈,用于存储顶点
var stack = new Stack();
stack.push(v);
colors[v] = 'gray';
// 3、遍历非空栈
while(!stack.isEmpty()){
// 3.1、取出栈顶元素
var v_head = stack.pop();
// 3.2、取出栈顶元素的邻接顶点,遍历邻接顶点,将是白色状态的数组入队,置为灰
var nearEdges = this.edges.get(v_head);
for(var i = 0; i < nearEdges.length; i ++){
var tempEdges = nearEdges[i];
if(colors[tempEdges] == 'white'){
stack.push(tempEdges);
colors[tempEdges] = 'gray';
}
}
bfsStr += v_head + '->'
colors[v_head] = 'black';
}
return bfsStr
}
*/
// 递归实现dfs
Graph.prototype.dfs = function(v,colors){
// 1、每次递归将顶点置为灰色
colors[v] = 'gray';
console.log(v);
// 2、遍历邻接顶点,将白色状态的邻接顶点进行递归调用
var nearEdges = this.edges.get(v);
for(var i = 0; i < nearEdges.length; i ++){
var temp_edges = nearEdges[i];
if(colors[temp_edges] == 'white'){
this.dfs(temp_edges,colors);
}
}
colors[v] = 'black';
}
}
// 测试代码
var graph = new Graph();
var myVertexes = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
for (var i = 0; i < myVertexes.length; i++) {
graph.addVertex(myVertexes[i]);
}
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "D");
graph.addEdge("C", "D");
graph.addEdge("C", "G");
graph.addEdge("D", "G");
graph.addEdge("D", "H");
graph.addEdge("B", "E");
graph.addEdge("B", "F");
graph.addEdge("E", "I");
console.log(graph.toString());
console.log(graph.initializeColor());
console.log(graph.bfs(graph.vertexes[0]));
console.log(graph.dfs(graph.vertexes[0], graph.initializeColor()));