穷举算法:子集遍历、全排列、广度优先搜索、深度优先搜索(Java实现)

因为这学期上算法课,因为要准备蓝桥杯国赛,所以复习记录一下几个经典的算法 (T_T)。。。

1.子集遍历

子集遍历的算法思想:
使用深度优先搜索,用堆栈记录路径。
子集树:
在这里插入图片描述
1.访问根节点。
2.若当前访问为非叶节点:
(a)将0压栈;
(b)递归访问左子树;
(c)将0弹出,将1压栈;
(d)递归访问右子树;
(e)将1弹出。
3.若当前访问为叶节点,就根据栈中的内容打印。

import java.util.ArrayList;
import java.util.Scanner;

/**
 *  @author: cuttle
 *  @Date: 2020/9/16 16:32
 *  @Description: 子集遍历算法
 */
public class SubsetsEnumeration {
    static ArrayList<Object> arr = new ArrayList<>();//作为栈
    static Object[] obj;
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入集合的元素数目n为:");
        int n = sc.nextInt();
        System.out.println("请输入" + n + "个集合元素:");
        obj = new Object[n];
        for(int i = 0;i < n;i++){
            obj[i] = sc.next();
        }
        long begin = System.currentTimeMillis();
        subsetting(n);
        long end = System.currentTimeMillis();
        System.out.println("集合元素数目n为" + n +"时,花费的时间为:" + (end - begin) + "ms");
    }
    public static void subsetting(int n){
        if(n > 0){
            arr.add(0);//将0压栈
            subsetting(n -1);//递归访问左子树
            arr.set(arr.size() - 1,1);//将0弹出,将1压栈
            subsetting(n -1 );//递归访问右子树
            arr.remove(arr.size() -1 );//将1弹出
        }else{
            System.out.print("{ ");
            for (int i = 0;i < arr.size();i++) {
                if(arr.get(i).equals(1)){
                    System.out.print(obj[i] + " ");
                }
            }
            System.out.print("}");
            System.out.println();
        }
    }
}

时间复杂度:T(n) = n × 2 n

2.全排列

全排列的算法思想:
使用深度优先搜索排列树。
排列树:
在这里插入图片描述

import java.util.Scanner;

/**
 *  @author: cuttle
 *  @Date: 2020/9/16 20:12
 *  @Description: 全排列遍历
 */
public class PermutationsEnumeration {
    static Object[] obj;
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入全排列的规模n:");
        int n = sc.nextInt();
        obj = new Object[n];
        System.out.println("请顺序输入结点号列表:");
        for(int i = 0;i < n;i++){
            obj[i] = sc.next();
        }
        long begin = System.currentTimeMillis();
        permuting(0);
        long end = System.currentTimeMillis();
        System.out.println("全排列的规模n为" + n + "时,花费的时间为" + (end - begin) + "ms" );
    }
    public static void permuting(int i){
        if(i < obj.length - 1){
            for(int j = i;j < obj.length;j++){
                swap(obj,i,j);
                permuting(i + 1);
                swap(obj,i,j);
            }
        }else{
            for (Object o:obj) {
                System.out.print(o+" ");
            }
            System.out.println();
        }
    }
    public static void swap(Object[] x,int i,int j){
        Object temp = x[i];
        x[i] = x[j];
        x[j] = temp;
    }
}

时间复杂度:T(n) = n × n!

3.图的广度优先搜索

图的广度搜索BFS的算法思想:
1.置所有顶点为未访问;
2.从第一个顶点开始循环访问未访问的顶点:
(a)将当前顶点v置为访问;
(b)将v推入队列Q;
(c)若队列Q不为空:
弹出队首顶点u;访问u的所有邻居顶点;若某邻居结点w未被访问过,则将其置为未访问并推入Q;

import java.util.ArrayList;
import java.util.Scanner;

/**
 *  @author: cuttle
 *  @Date: 2020/9/24 19:03
 *  @Description: 图的广度优先搜索算法
 */
public class BFS {
    static ArrayList<Object> queue = new ArrayList<>();//作为队列
    static int n;//记录图的顶点个数
    static int[][] matrix;//存储图的邻接矩阵
    static Object[] nodeName;//存储图的顶点名称
    static boolean[] visited;//记录顶点是否访问
    static int start;//起始顶点序号
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入图的顶点个数:");
        n = sc.nextInt();
        matrix = new int[n][n];
        nodeName = new Object[n];
        visited = new boolean[n];
        System.out.println("请输入" + n + "个顶点的名称:");
        for(int i = 0;i < n;i++){
            nodeName[i] = sc.next();
            visited[i] = false;
        }
        System.out.println("请输入图的邻接矩阵:");
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                matrix[i][j] = sc.nextInt();
            }
        }
        System.out.println("请输入起始顶点[1,"+ n +"]:");
        start = sc.nextInt();
        graphBFS(start);
    }
    public static void graphBFS(int start){
        visited[start -1] = true;
        queue.add(start -1);
        System.out.print(nodeName[start - 1] + " ");
        while(queue.size() != 0){
            int j = (Integer) queue.get(0);
            queue.remove(0);
            for(int i = 0;i < matrix.length;i++){
                if(matrix[j][i] == 1 && visited[i] == false){
                    visited[i] = true;
                    queue.add(i);
                    System.out.print(nodeName[i] + " ");
                }
            }
        }
        //检查是否还存在未被访问过的
        for(int i = 0;i < visited.length;i++){
            if(visited[i] == false){
                graphBFS(i + 1);
            }
        }
    }
}

4.图的深度优先搜索

图的深度搜索DFS的算法思想:
1.置所有顶点为未访问;选取一个顶点v作为起始顶点;
2.访问顶点v,将顶点v置为访问;
3.选择v的一个邻居顶点u:
(a)若u访问过,则转3;
(b)若u未访问过,则将u作为新的v对第2步进行递归;

import java.util.Scanner;

/**
 *  @author: cuttle
 *  @Date: 2020/9/24 20:16
 *  @Description: 图的深度优先搜索算法
 */
public class DFS {
    static int n;//记录图的顶点个数
    static int[][] matrix;//存储图的邻接矩阵
    static Object[] nodeName;//存储图的顶点名称
    static boolean[] visited;//记录顶点是否访问
    static int start;//起始顶点序号
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入图的顶点个数:");
        n = sc.nextInt();
        matrix = new int[n][n];
        nodeName = new Object[n];
        visited = new boolean[n];
        System.out.println("请输入" + n + "个顶点的名称:");
        for(int i = 0;i < n;i++){
            nodeName[i] = sc.next();
            visited[i] = false;
        }
        System.out.println("请输入图的邻接矩阵:");
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                matrix[i][j] = sc.nextInt();
            }
        }
        System.out.println("请输入起始顶点[1,"+ n +"]:");
        start = sc.nextInt();
        graphDFS(start - 1);
        //检查是否还存在未被访问过的,因为有递归,不能放在graphDFS里面
        for(int i = 0;i < visited.length;i++){
            if(visited[i] == false){
                graphDFS(i);
            }
        }
    }
    public static void graphDFS(int start){
        visited[start] = true;
        System.out.print(nodeName[start] + " ");
        for(int i = 0;i < matrix.length;i++){
            if(matrix[start][i] == 1 && visited[i] == false){
                visited[i] = true;
                graphDFS(i);
            }
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值