一点小小总结+《啊哈!算法》第八章上

?晚上好?
  在写第八章代码之前,又把2345章的代码又看了一遍,主要针对深度广度优先算法说说注意点吧,其实前面早就提过了,但是反复的过程就是巩固的过程嘛(✔计划通)。
  深度优先算法:属于一条路走到黑,再返回,再换一条路走到黑的过程。因为不知道每一条路是不是走的最近最优的,所以一般用一个min变量存储最短路径。dfs往往是单独写一个dfs函数,记录每一步的走向,采用递归的形式一步一步走完全程,所以他必须有1、确认是否到终点,到的话要return 2、确认是否超边界 3、递归函数过后要把当前坐标的标记去除,便于下一次循环 4、循环过后要return
  广度优先算法:属于开枝散叶型,一层一层往外扩张,由于前面扩张到的点不会再被扩张到了,他无需去除标记,返回的路径为最快扩张到目标点的路径。与dfs不同,bfs不需要单独列函数,只用在main函数中进行就可以了。通常使用队列的形式,用head和tail指代上一步结点和由该结点扩张到的下一步结点(也就是说tail结点会比head结点多走一步,切记),要注意tail和head加一的位置。
  好啦,接下来是第八章的内容!
  在这里插入图片描述
  8.1 最小生成树

import java.util.Scanner;

class Test{
    static class edge{
        int u;
        int v;
        int w;
    }
    static int n,m;
    static int[] f=new int[10];
    static edge[] e=new edge[10];
    public void quicksort(int left,int right){
        edge temp=new edge();
        int i=left;
        int j=right;
        if(left>right)
            return;
        while(i!=j){
            while(j>i&&e[j].w>=e[left].w)
                j--;
            while(i<j&&e[i].w<=e[left].w)
                i++;
            if(i<j){
                temp=e[i];
                e[i]=e[j];
                e[j]=temp;
            }
        }
        temp=e[left];
        e[left]=e[i];
        e[i]=temp;
        quicksort(left,i-1);
        quicksort(i+1,right);
        return;
    }
    public void init(){
        for(int i=1;i<=n;i++)
            f[i]=i;
    }
    public int getf(int x){
        if(f[x]==x)
            return x;
        else{
            f[x]=getf(f[x]);
            return f[x];
        }
    }
    public boolean merge(int x,int y){
        if(getf(x)!=getf(y)){
            f[getf(y)]=x;
            return true;  //可合并
        }
        return false;      //不可合并
    }
    public static void main(String[] args){
        Test t=new Test();
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入点和边的数量");
        n=sc.nextInt();
        m=sc.nextInt();
        System.out.println("请输入各条边的起点、终点和权值");
        for(int i=1;i<=m;i++){
            e[i]=new edge();
            e[i].u=sc.nextInt();
            e[i].v=sc.nextInt();
            e[i].w=sc.nextInt();
        }
        t.quicksort(1,m);
        t.init();
        int sum=0;
        int totallength=0;
        for(int i=1;i<=m;i++){
            if(t.merge(e[i].u,e[i].v)){
                sum++;
                totallength+=e[i].w;
            }
            if(sum==n-1)  //历经n-1个点
                break;
        }
        System.out.println(totallength);

    }

}
/*
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
 */

唉感冒来的太快就像龙卷风,快排之后的return忘掉了调试了好一会。这个的思路是按从小到大顺序排列边,然后把没有连通的最短边加到路径当中,直到n-1条边都被加入,输出路径总和。

8.2 还是最小生成树
  一样的题目,换了一种思路。采用一种寻找最短边的形式,把距离当前生成树最短的边加进来,为了保持准确,需要在每一次有点入树的时候都根据新点尝试松弛边。上代码!

import java.util.Scanner;

class Test{
    public static void main(String[] args) {
        int[][] e = new int[50][50];
        int[] book = new int[10];
        int[] dis = new int[10];
        int n, m, k = 0,inf=99999;
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入点和边的数量");
        n = sc.nextInt();
        m = sc.nextInt();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j)
                    e[i][j]=0;
                else
                    e[i][j]=inf;
            }
        }
        System.out.println("请输入相连的点和权值");
        for (int i = 1; i <= m; i++) {
            int a1 = sc.nextInt();
            int a2 = sc.nextInt();
            int weigh = sc.nextInt();
            e[a1][a2] = weigh;
            e[a2][a1] = weigh;
        }
        book[1] = 1;
        int distance=0;
        for (int i = 1; i <= n; i++)
            dis[i] = e[1][i];
        int sum = 1;
        while (sum < n) {
            int min = 99999;
            for (int i = 1; i <= n; i++) {
                if (dis[i] < min&&book[i]==0) {
                    min = dis[i];
                    k = i;
                }
            }
            book[k]=1;
            sum++;
            distance+=dis[k];
            for (int i = 1; i <= n; i++) {
                if (dis[i] > e[k][i])
                    dis[i] = e[k][i];
            }
        }
        System.out.println(distance);
    }
}
/*
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
 */

今天可能想不出第三道了,先说再见吧!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值