JavaScript数据结构-7-1图广度优先搜索

图用邻接表法表示,其中顶点存储在数组中,边存储在以顶点为键,以其它相邻的顶点的数组为值的字典中;

图的广度优先搜索树其实就是二叉树的层次遍历,遍历结果存放在兄弟节点表示法的树中。

<!DOCTYPE html>
<html>
<head>
	<title>
		邻接表图
	</title>
	<meta charset="utf-8">
	<script type="text/javascript" src="ALGraph.js"></script>
</head>
<body>

</body>
</html>
//*******************辅助队列*******************//
class LinkLnode {
    constructor() {
        this.data = null; //数据
        this.next = null; //指针
    }
}
//链式队列比链表多了队头队尾指针
class LinkQueue {
    constructor() {
        //默认带一个不含数据的头节点
        var HeadNode = new LinkLnode();
        this.front = HeadNode; //头指针初始指向头节点
        this.rear = HeadNode; //尾指针初始指向头节点
    }
    IsEmpty() {
        if (this.front == this.rear) return true;
        else return false;
    }
    //入队
    EnQueue(value) {
        var Lnode = new LinkLnode();
        Lnode.data = value;
        Lnode.next = null;
        this.rear.next = Lnode;
        this.rear = Lnode;
    }
    //出队
    DeQueue() {
        if (this.front == this.rear) {
            return false;
        } //空队不能出队
        var p = this.front.next;
        var value = p.data;
        this.front.next = p.next; //等下换成p=p.next
        if (p == this.rear) {
            this.rear = this.front;
        }
        return value;
    }
}
//*******************辅助队列*******************//
//树节点
//左孩子右兄弟
class Node {
    constructor(key, lchild, rchild) {
        this.key = key;
        this.lchild = lchild;
        this.rchild = rchild;
        this.distance = null; //新增一个属性,用来记录到起始点的距离
    }
}
class MinTree {
    constructor() {
        this.root;
    }
}
class ALGraph {
    constructor() {
        this.vertex = []; //顶点
        this.side = new Map(); //一个字典,值放入数组或链表对象,存储边
    }
    //增加顶点的方法
    addVertex(v) {
        this.vertex.push(v);
        this.side.set(v, []); //增加一个顶点的同时初始化对象
    }
    //增加边
    addSide(v, w) {
        this.side.get(v).push(w);
        this.side.get(w).push(v);
        //比如有两个节点a b ,一条边连接ab,这个边实际上上两个顶点共有的,
        //如果是有向图则只需插入一次
    }
    //打印
    toString() {
        var s = '';
        for (var i = 0; i < this.vertex.length; i++) { //{10} 
            s += this.vertex[i] + ' -> ';
            var neighbors = this.side.get(this.vertex[i]); //{11} 
            for (var j = 0; j < neighbors.length; j++) { //{12} 
                s += neighbors[j] + ' ';
            }
            s += '\n'; //{13} 
        }
        console.log(s);
        return s;
    }
    //广度优先搜索遍历
    //实际上就是二叉树的层次遍历
    //判断顶点是否被访问,是用数组存储ture和false判断
    //把顶点数组的元素作为访问数组的下标标识,则顶点元素字符串不能重复,
    //最好是创建顶点对象,数组的索引是字符串,还有一个问题是不能遍历,好在我们判断该顶点是否被访问,不需要遍历
    //不过以后还是将顶点字符串变成顶点对象
    //可以将访问数组变成访问字典,访问字典的key就是顶点对象,value就是是否访问
    //不过现在还是按照书上的写法,用字符串为索引的数组标识顶点是否被访问
    BFS() {
        var results = [];
        var Queue = new LinkQueue();
        //创建访问数组
        var visit = [];
        //图初始节点入队
        var p = this.vertex[0];
        results.push(p);
        visit[p] = true;
        Queue.EnQueue(p);
        if (p == null || p == undefined) return null;
        while (!Queue.IsEmpty()) {
            //出队
            var q = Queue.DeQueue();
            var sides = this.side.get(q);
            for (var i = 0; i < sides.length; i++) {
                if (!visit[sides[i]]) {
                    //如果未被访问过,则访问并入队
                    results.push(sides[i]);
                    Queue.EnQueue(sides[i]);
                    visit[sides[i]] = true;
                }
            }
        }
        return results;
    }
    //广度优先搜索最短路径
    BFS_Min() {
        //  var results = [];
        var Queue = new LinkQueue();
        //创建访问数组
        var visit = [];
        var d = [];
        //图初始节点入队
        var p = this.vertex[0];
        d[p] = 0;
        //  results.push(p);
        visit[p] = true;
        Queue.EnQueue(p);
        if (p == null || p == undefined) return null;
        while (!Queue.IsEmpty()) {
            //出队
            var q = Queue.DeQueue();
            var sides = this.side.get(q);
            for (var i = 0; i < sides.length; i++) {
                if (!visit[sides[i]]) {
                    //如果未被访问过,则访问并入队
                    d[sides[i]] = d[q] + 1;
                    Queue.EnQueue(sides[i]);
                    visit[sides[i]] = true;
                }
            }
        }
        return d;
    }
    //广度优先搜索树
    //最简单是双亲表示法,现在采用孩子兄弟表示法表示,然后转为二叉树
   
    BFS_Mintree() {
        //  var results = [];
        var Queue = new LinkQueue();
        //创建访问数组
        var visit = [];
        //图初始节点入队
        var p = this.vertex[0];
        if (p == null || p == undefined) return null;
        var node = new Node(p, null, null);
        node.distance = 0;
        var minTree = new MinTree();
        minTree.root = node;
        //  results.push(p);
        visit[p] = true;
        Queue.EnQueue(node);
        while (!Queue.IsEmpty()) {
            //出队
            var qnode = Queue.DeQueue();
            // var qnode = new Node(q, null, null);
            var lastnode = null;
            var sides = this.side.get(qnode.key);
            for (var i = 0; i < sides.length; i++) {
                if (!visit[sides[i]]) {
                    //如果未被访问过,则访问并入队
                    //出队的的都是兄弟
                    var snode = new Node(sides[i], null, null);
                    if (lastnode == null) {
                        qnode.lchild = snode;
                        // lastnode = snode;
                    } else {
                        lastnode.rchild = snode;
                    }
                    // d[sides[i]] = d[q] + 1;
                    snode.distance = qnode.distance + 1;
                    Queue.EnQueue(snode);
                    visit[sides[i]] = true;
                    lastnode = snode;
                }
            }
        }
        return minTree;
    }
    BFS_MintreeToBinarytree(minTree) {
        //上面这个孩子兄弟表示法就是二叉树,就不用转了
    }
}
var graph = new ALGraph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; //{7} 
for (var i = 0; i < myVertices.length; i++) { //{8} 
    graph.addVertex(myVertices[i]);
}
graph.addSide('A', 'B'); //{9} 
graph.addSide('A', 'C');
graph.addSide('A', 'D');
graph.addSide('C', 'D');
graph.addSide('C', 'G');
graph.addSide('D', 'G');
graph.addSide('D', 'H');
graph.addSide('B', 'E');
graph.addSide('B', 'F');
graph.addSide('E', 'I');
console.log(graph.BFS_Mintree());

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值