算法学习 图

存储方式:邻接矩阵、邻接表。(十字链表、邻接多重表,省空间但不常用)

类型:有向图、无向图

指定一种适合自己的存储方式,将各种表达方式转成自己熟悉的存储方式。
(如万物转邻接矩阵!)
下面是适用较广的模板

public class Graph{

    public HashMap<Integer, Node>nodes; //点集 编号+实际结构
    public HashSet<Edge> edges; //边集
    
    public Graph(){
        nodes=new HashMap<>();
        edges=new HashSet<>();
    }

}

public class Node{

    public int value;
    public int in; 
    public int out;
    public ArrayList<Node> nexts; //直接邻居 edges连向的结点
    public ArrayList<Edge> edges; //从当前结点出发的边
    
    public Node(int value){
        this.value=value;
        in=0;
        out=0;
        nexts=new ArrayList<>();
        edges=new ArrayList<>();
    }

}

public class Edge{

    public int weight;
    public Node from; 
    public Node to;
       
    public Node(int weight,Node from,Node to){
        this.weight=weight;
        this.from=from;
        this.to=to;
    }

}

BFS


队列+集合,队列实现BFS,集合实现不重复

public void BFS(Node node){
    if(node==null) return ; 
    Queue<Node> queue=new LinkList<>();
    HashSet<Node> set= new HashSet<>();
    queue.add(node);
    set.add(node);
    while(!queue.IsEmpty()){
        Node cur=queue.poll();
        process(cur);
        for(Node next:cur.nexts){
            //直接邻居未被访问过
            if(!set.contains(next)){
                queue.add(next);
                set.add(next);
            }
        }
    }

}

DFS

public void DFS(Node node){
    if(node==null) return ; 
    //路径在栈内,弹出访问下一结点后需要压回
    Stack<Node> stack=new LinkList<>();
    HashSet<Node> set= new HashSet<>();
    stack.push(node);
    set.add(node);
    process(node); //处理头
    while(!stack.IsEmpty()){
        Node cur=stack.pop();
        for(Node next:cur.nexts){
            //直接邻居未被访问过
            if(!set.contains(next)){
                //先压自己再压邻居,注册邻居
                stack.push(cur);
                stack.push(next);
                set.add(next);
                process(next);//处理邻居
                break;
            }
        }
    }

}

拓扑排序

找入度(in)为0的点

public static List<Node> sort(Graph graph){
        //key 某个node value剩余入度
        HashMap<Node, Integer> inMap=new HashMap<>();
        //入度为0进队列
        Queue<Node> zeroInQueue =new LinkedList<>();
        for(Node node:graph.nodes.values()){
            //nodes为ArrayList,values()方法获取值便于遍历
            inMap.put(node,node.in);
            if(node.in==0){
                zeroInQueue.add(node);
            }
        }
        //res 收集排序结果
        List<Node> res=new ArrayList<>();
        while(!zeroInQueue.isEmpty()){
            Node cur=zeroInQueue.poll();
            res.add(cur);
            //消除已排序点的影响
            for(Node next: cur.nexts){
                inMap.put(next,inMap.get(next)-1);
                if(inMap.get(next)==0){
                    zeroInQueue.add(next);
                }
            }
        }
        return res;

    }

k算法

无向图找最小生成树

边的角度出发,排序边,加入新边的时候判断是否成环(一群与一群)。

重点在于怎么判断成环,可用并查集

p算法

无向图找最小生成树

从点的角度出发,维护一个边集合(小根堆 ),每加入一个新结点,将新边加入集合,选出最小且不成环(哈希表即可,只涉及一个与一群)的边,加入再新结点,直至结点全部加入。

迪杰斯特拉

边无负权值 单源最短路径

维护一个数组,表示源点到其他点的最短路径,每次选中其中最短路径的点(选过不再选择),源点经过该选择点到其余未选择点是否存在更短的路径,有则更新。

可用小根堆优化找最短且方便更新堆,需要手写,因为更新路径时结点不一定是堆顶,需要map快速访问到结点在堆的位置。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值