算法(二)

10.图

  • 邻接表

  • 邻接矩阵

  • 点集、边集,入读、出度

1.宽度优先遍历
public static void bfs(Node node)
{
    if(node==null)
    {
        return;
    }
    Queue<Node> queue = new Queue<Node>();
    HashSet<Node> set = new HashSet<Node>();
    queue.add(node);
    set.add(node);
    while(!queue.isEmpty)
    {
        Node p = queue.poll();
        System.out.println(p);
        for(Node next:p.nexts){
            if(!set.contains(next))
            {
                set.add(next);
                queue.add(next);
            }
        }
    } 
}
2.深度优先
public static void dfs(Node node)
{
    if(node==null)
    {
        return;
    }
    Stack<Node> stack = new Stack<Node>();
    HashSet<Node> set = new HashSet<Node>();
    stack.add(node);
    set.add(set);
    System.out.println(node.value);
    while(!stack.isEmpty)
    {
        Node p = stack.pop();
        for(Node cur:p.nexts)
        {
            if(!set.contains(cur))
            {
                stack.push(p);
                stack.push(cur);
                set.add(cur);
                break;
            }
        }
        
    }
}
3.拓扑排序

入度为0,放在最前面,然后消除堆剩余点的入度、出度影响

4.最小生成树

k算法:将边从小到大排序,遍历,若加上边后,没有形成环,就加上,否则不要

怎么判断环:将点分成一个个集合,每次加上边时,若from点和to点不在同一个点,则可以加上,然后把两个集合合并,如果在一个集合,则不能加上这个边

public HashMap<Node,List<Node>> setMap;

public MySets(List<Node> nodes){
    for(Node cur:nodes){
        List<Node> set = new List<Node>();
        set.add(cur);
        setMap.put(cur,set);
    }
}

public boolean isSameSet(Node from,Node to){
    List<Node> fromList = setMap.get(from);
    List<Node> toList = setMap.get(to);
    return fromList == toList;
}

public void union(Node from,Node to){
    List<Node> fromList = setMap.get(from);
    List<Node> toList = setMap.get(to);
    for(Node toNode : toList){
        fromList.add(toNode);
        setMap.put(toNode,fromList);
    }
}

p算法:从任意点开始,选择最小的边,如果边的两边都已经加入,将该边舍去,重新找最小的边,如果没有,将边的另一个点加入,并将该点的边都加入可选择的边集合中

priorityQueue优先级队列;
Set<Edge> result = new HashSet<>();
HashSet<Node> set = new HashSet<>();
PriorityQueue<Edge> priorityQueue = new priorityQueue(有一个比较器);
for(Node node:graph.nodes.values()){//
    if(!set.contains(node)){
        set.add(node);
        for(Edge edge:node.edges){
            priority.add(edge);
        }
        while(!priorityQuwuw.isEmpty()){
            Edge edge = priorityQueue.poll();
            Node toNode = edge.toNode;
            if(!set.contains(node)){
                set.add(node);
                result.add(edge);
                for(Edge edge:node.edges){
                    priority.add(edge);
                }
            }
        }
    }
}
5.Dijkstra算法

可以有负数的边,不能有和为负数的环,如果有的话,那么环可以一直循环下去,直到无穷小

HashMap<Node,Integer> distanceMap = new HashMap<>();
distanceMap.put(head,0);
//head点到key点最近距离为value

HashSet<Node> selectNode = new HashSet<>();
//已经更新过的点放在selectNode中

Node minNode = gewMinAndUnselected();

while(midNode!=null){
    int distance = distanceMap.get(minNode);
    for(Edge edge:minNode.Edges){
        Node toNode = edge.toNode;
        if(!distanceMap.containsKey(toNode)){
            distanceMap.put(toNode,edge.value+distance);
        }
        distanceMap.put(toNode,Math.min(edge.value+distance,distanceMap.get(toNode)));
    }
    selectNode.add(midNode);
    minNode = gewMinAndUnselected();
}
return distanceMap;

优化:改写堆,系统给出的堆能弹出最小(最大值),但加入后不能再变,所以要改写

11贪心

1.前缀树
//数据结构
public Trie(){
    root = new TrieNode();
}
public static class TrieNode{
    public int pass;//经过该字符的字符串树
    public int end;//以该字符结束的字符串树
    //可换成HashMap<char,Node>
    //可换成TreeMap<char,Node>有序表
    public TrieNode[] nexts;
    
    public TrieNode(){
        pass=0;
        end=0;
        nexts=new TrieNode[26];
    }
}
//创建前缀树
public void insert(String word)
{
    if(word==null)
    {
        return ;
    }
    char[] str = word.toCharArray();
    TrieNode node = root;
    node.pass++;
    ine index = 0;
    for(int i=0;i<str.length;i++)
    {
        index = str[i]-'a';
        if(node.nexts[index]==null)
        {
            node.nexts[index] = new TrieNode();
        }
        node = node.nexts[index];
        node.pass++;
    }
    node.end++;
}

//word插入过几次
public int search(String word)
{
    if(word==null)
    {
        return 0;
    }
    char[] str = word.toCharArray();
    TrieNode node = root;
    int index = 0;
    for(int i=0;i<str.length;i++)
    {
        index  = char[i]-'a';
        if(node.nexts[index]==null)
        {
            return 0;
        }
        node = node.nexts[index];
    }
    return node.end;
}

//有几个以pre为前缀的字符串
public int preCount(String pre){
    if(pre==null)
    {
        return 0;
    }
    char[] str = pre.toCharArray();
    TrieNode node = root;
    int index=0;
    for(int i=0;i<str.length;i++)
    {
        index=str[i]-'a';
        if(node.nexts[index]==null)
        {
            return 0;
        }
        node = node.nexts[index];
    }
    return node.pass;
}

//删除delete
public void delete(String word){
    id(!search(word)){
        char str = word.toCharArray();
        TrieNode node = root;
        node.pass--;
        int index = 0;
        for(int i=0;i<str.length;i++)
        {
            index = str[i]-'a';
            node.nexts[index].pass--;
            if(node.nexts[index].pass==0)
            {
                node.nexts[index]=null;
            }
            node = node.nexts[index];
        }
        node.end--;
    }
}
2.贪心算法
比较器
//Program是自定义的类
public static class ProgramComparator implements Comparator<Program>{
    public int compare(Program 01,proGram o2){
        return o1.end-o2.end;
    }
}
Arrays.sort(programs,new ProgramComparator());
a.compareto(b);//比较a、b的字典序


字符串组合 结果字典序最小的结果
a.b <= b.a的时候,a放在前面,b放后面

数据流中的中位数

//首先一个数,加入到大跟堆
再来一个数
如果<=大根堆堆顶,放到大根堆,否则放在小根堆,
然后比较大、小根堆元素个数差值==2,就弹出一个到另一个
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值