数据结构-图

一、图的概念

相比栈、队列、二叉树、图是一种更复杂的数据结构。图由节点和边组成

二、用java实现图

定义节点

@Setter
@Getter
public class GraphNode<T> {
    private T data;
    private List<GraphNode<T>> neighbourNodeList;
    private boolean visited;

    public GraphNode(T data){
        this.data = data;
        neighbourNodeList = new ArrayList<>();
    }

    @Override
    public String toString() {
        if(data == null){
            return null;
        }
        return data.toString();
    }
}

定义边

边可以使用节点之间的引用关系表示。

public class Graph<T> {
    /**
     * 画不出来图的结构了...
     *                    1
     *                /       \
     *               2         3
     *           /  /   \  /    \   \
     *         4 - 5  -   6       7   8
     *                   /  \
     *                  9  - 10
     */
    private GraphNode<Integer> buildGraph(){
        GraphNode<Integer> node1 = new GraphNode<>(1);
        GraphNode<Integer> node2 = new GraphNode<>(2);
        GraphNode<Integer> node3 = new GraphNode<>(3);
        GraphNode<Integer> node4 = new GraphNode<>(4);
        GraphNode<Integer> node5 = new GraphNode<>(5);
        GraphNode<Integer> node6 = new GraphNode<>(6);
        GraphNode<Integer> node7 = new GraphNode<>(7);
        GraphNode<Integer> node8 = new GraphNode<>(8);
        GraphNode<Integer> node9 = new GraphNode<>(9);
        GraphNode<Integer> node10 = new GraphNode<>(10);

        node1.getNeighbourNodeList().add(node2);
        node1.getNeighbourNodeList().add(node3);

        node2.getNeighbourNodeList().add(node4);
        node2.getNeighbourNodeList().add(node5);
        node2.getNeighbourNodeList().add(node6);

        node3.getNeighbourNodeList().add(node1);
        node3.getNeighbourNodeList().add(node6);
        node3.getNeighbourNodeList().add(node7);
        node3.getNeighbourNodeList().add(node8);

        node4.getNeighbourNodeList().add(node2);
        node4.getNeighbourNodeList().add(node5);

        node5.getNeighbourNodeList().add(node2);
        node5.getNeighbourNodeList().add(node4);
        node5.getNeighbourNodeList().add(node6);

        node6.getNeighbourNodeList().add(node2);
        node6.getNeighbourNodeList().add(node5);
        node6.getNeighbourNodeList().add(node3);
        node6.getNeighbourNodeList().add(node8);
        node6.getNeighbourNodeList().add(node9);
        node6.getNeighbourNodeList().add(node10);

        node7.getNeighbourNodeList().add(node3);

        node8.getNeighbourNodeList().add(node3);
        node8.getNeighbourNodeList().add(node6);
        node8.getNeighbourNodeList().add(node9);

        node9.getNeighbourNodeList().add(node6);
        node9.getNeighbourNodeList().add(node8);
        node9.getNeighbourNodeList().add(node10);

        node10.getNeighbourNodeList().add(node6);
        node10.getNeighbourNodeList().add(node9);

        return node1;
    }
}

三、图的遍历

遍历的类型

图的遍历类似树的遍历分为两种。分别为广度优先遍历和深度优先遍历。

广度优先遍历

广度优先遍历是指从起始节点开始优先遍历离自己近的节点,近的节点遍历完之后,再遍历次近的节点。以此类推,直到所有的节点都被访问到。

基于队列实现广度优先遍历

/**
     * 依赖队列实现广度优先遍历
     */
    public void breadthFirstSearchByQueue(GraphNode<T> node){
        //队列
        Queue<GraphNode<T>> nodeQueue = new ArrayDeque<>();
        nodeQueue.offer(node);

        while (!nodeQueue.isEmpty()){
            GraphNode<T> nodeFromQueue = nodeQueue.poll();
            //如果在这里标记已处理的话,后面入队的元素可能会是已经被访问过得
            //handleNode(nodeFromQueue);

            List<GraphNode<T>> neighbourNodeList = nodeFromQueue.getNeighbourNodeList();
            if(neighbourNodeList != null){
                for(GraphNode<T> neighbourNode : neighbourNodeList){
                    if(!neighbourNode.isVisited()){
                        //处理之后再入队,可以保证每个入队的元素都是已经被处理过的
                        handleNode(neighbourNode);
                        nodeQueue.offer(neighbourNode);
                    }
                }
            }
        }
    }

深度优先遍历

深度优先遍历指从起始节点开始优先遍历路径长的节点,直到节点无邻居节点

基于递归实现深度优先遍历

    /**
     * 深度优先,递归方式实现
     */
    public void deepFirstSearchByRecursive(GraphNode<T> node){

        handleNode(node);
        List<GraphNode<T>> neighbourNodeList = node.getNeighbourNodeList();
        if(neighbourNodeList != null){
            for(GraphNode<T> nodeItem : neighbourNodeList){
                if(!nodeItem.isVisited()){
                    deepFirstSearchByRecursive(nodeItem);
                }
            }
        }

    }

基于栈实现深度优先遍历

    /**
     * 基于栈实现深度优先遍历
     */
    public void deepFirstSearchByStack(GraphNode<T> graphNode){
        Stack<GraphNode<T>> stack = new Stack<>();
        stack.push(graphNode);

        while (!stack.isEmpty()){
            GraphNode<T> node = stack.pop();
            if(node.getNeighbourNodeList() != null){
                for (GraphNode<T> neighbourNode : node.getNeighbourNodeList()){
                    if(!neighbourNode.isVisited()){
                        handleNode(neighbourNode);
                        stack.push(neighbourNode);
                    }
                }
            }
        }
    }

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值