数据结构与算法(3)

数据结构与算法(3)

算法笔记3

一、图

public class Graph {
    /**
     * 顶点的list集合
     */
    private ArrayList<String> vertexList;
    /**
     * 顶点对应的邻接矩阵
     */
    private int [][] adjacencyMatrix;
    /**
     * 边的个数!
     */
    private int edgeCount;

    /**
     * 顶点个数
     */
    private int vertexCount;
    public Graph(int vertexCount) {
        this.vertexCount =vertexCount;
        vertexList = new ArrayList<>(vertexCount);
        adjacencyMatrix = new int[vertexCount][vertexCount];
        edgeCount  = 0;
    }
    /**
     * 添加节点
     */
    public void addVertex(String vertex){
        if (vertexList.size() == vertexCount){
            System.out.println("顶点数已满");
            return;
        }
        vertexList.add(vertex);

    }

    /**
     * 通过字符顶点,获取在临界矩阵中的数字顶点
     * @param vertex
     * @return
     */
    public int getIntByVertex(String vertex){
        int num = 0;
        for (String s : vertexList) {
            if (s == vertex){
                break;
            }
            num++;
        }
        return num;
    }

    /**
     * 添加边
     */
    public void addEdge(String vertex1,String vertex2,int weight){
        int vertexNum1 = getIntByVertex(vertex1);
        int vertexNum2 = getIntByVertex(vertex2);
        adjacencyMatrix[vertexNum1][vertexNum2] = weight;
        adjacencyMatrix[vertexNum2][vertexNum1] = weight;
        edgeCount++;
    }

    /**
     * 展示
     */
    public void showGraph(){
        for (int[] rows : adjacencyMatrix) {
            for (int vertex : rows) {
                System.out.printf(vertex+" ");
            }
            System.out.println("");

        }
    }
    /**
     * 获取邻接节点
     * @return
     */
    public String getAdjacentNode(String s){
        int intByVertex = getIntByVertex(s);
        for (int i = 0; i < vertexCount; i++){
            //如果有边,并且末节点为访问过
            if (adjacencyMatrix[intByVertex][i] != 0&& isVisit[i] == false){
                return getStrByInt(i);
            }
        }
        return null;
    }
}

1.1深度优先


/**
 * DFS搜索
 */
public void DFSSearch(){
    Stack<String> stack = new Stack<>();
    //1.将第一个元素压入栈,并将访问情况至为true
    //访问情况
    isVisit[0] = true;
    //搜索到元素,打印操作
    System.out.printf(vertexList.get(0));
    //压入栈
    stack.push(vertexList.get(0));
    //循环
    while (stack.isEmpty() != true){
        //获取栈顶元素的邻接节点
        String adjacentNode = getAdjacentNode(stack.peek());
        if (adjacentNode == null){
            stack.pop();
        }
        else {
            //访问情况
            isVisit[getIntByVertex(adjacentNode)] = true;
            //搜索到元素,打印操作
            System.out.printf(adjacentNode);
            //压入栈
            stack.push(adjacentNode);

        }
    }
    //还原
    for (int i = 0; i < vertexCount; i++) {
        isVisit[i] = false;
    }
}

1.2广度优先

/**
 * 广度优先搜索
 */
public void BFSSearch(){
    ArrayQueue<String> queue = new ArrayQueue<String>(edgeCount);
    //1.将第一个元素压入栈,并将访问情况至为true
    //访问情况
    isVisit[0] = true;
    //搜索到元素,打印操作
    System.out.printf(vertexList.get(0));
    //压入栈
    queue.add(vertexList.get(0));
    String next;
    while (queue.isEmpty() != true){
        //对头出队列
        String s = queue.remove(0);

        while (( next = getAdjacentNode(s)) != null){
            isVisit[getIntByVertex(next)] = true;
            System.out.printf(next);
            queue.add(next);
        }
    }
    //还原
    for (int i = 0; i < vertexCount; i++) {
        isVisit[i] = false;
    }
}

二、算法

2.1非递归二分查找

/**
 * 非递归二分查找
 * @param arr 查找数组
 * @param target 目标元素
 * @return 目标元素下标
 */
public static int binarySearchNoRecursion(int [] arr, int target){
    int left = 0;
    int right = arr.length - 1;
    int mid = 0;
    //当左边界小于右边界时,一直查找
    while (left <= right){
        //中值
        mid = (left+right) / 2;
        //找到
        if (arr[mid] == target){
            return mid;
        }
        //中值大于目标值
        if (arr[mid] > target){
            //向左寻找
            right = mid - 1;

        }
        else
        {
            //向右
            left = mid + 1;

        }
    }
    //没找到
    return -1;
}

2.2分治算法(汉罗塔问题)

/**
 * 分治算法模仿 汉罗塔问题
 * @param num 罗盘数
 * @param a 第一个柱子
 * @param b 第二个柱子
 * @param c 第三个柱子
 */
public static void divideAndConquer(int num, String a,String b, String c){
    if (num == 1){
        System.out.println("第1个盘从" +a+ "->" +c);
    }
    //此时盘数大于1,将盘看做两个盘:
    //第一个盘为上面所有盘, 第二个盘为最下面的盘
    /*
    分为三步:
    1.把上面所有盘从a->b
    2.把最下面的盘从a->c
    3.把b的盘移到c
     */
    else {
        //1.把上面所有盘从a->b
        divideAndConquer(num-1,a,c,b);
        //2.把最下面的盘从a->c
        System.out.println("第"+num+"个盘从"+a+"->"+c);
        //3.把b的盘移到c
        divideAndConquer(num-1,b,a,c);
    }

}

2.3动态规划

<span>数据结构与算法(3)</span>
问:背包总称重4,物品不重复的前提,如何保证背包装的价格最高

/**
 * @Author: 郜宇博
 * @Date: 2021/8/11 15:31
 * 动态规划问题
 */

public class DynamicProgramming {
    public static void main(String[] args) {
        int []weight = {1,4,3};
        int []value = {1500,3000,2000};
        int knapsackWeight = 4;

        knapsackProblem(weight,value,knapsackWeight);
    }
    public static void knapsackProblem(int[] weight,int[] value, int knapsackWeight){
        //物品数量
        int G,S,L = 0;
        //用于存储各重量背包价值
        int [][] knapsackValue = new int[weight.length+1][knapsackWeight+1];
        int [][] path = new int[weight.length+1][knapsackWeight+1];
        //第一行和第一列设为0
        for (int i =0; i < knapsackValue.length; i++){
            knapsackValue[i][0] = 0;
        }
        for (int i =0; i < knapsackValue[0].length; i++){
            knapsackValue[0][i] = 0;
        }
        //动态规划
        for (int i = 1; i < knapsackValue.length; i++){
            for (int j = 1; j < knapsackValue[i].length; j++){
                if (weight[i-1]>j){
                    //物品大于背包重量
                    knapsackValue[i][j] = knapsackValue[i-1][j];
                }
                else {
                    //如果放入背包
                    if ((value[i-1]+knapsackValue[i-1][j-weight[i-1]]) > knapsackValue[i-1][j]){
                        knapsackValue[i][j] = value[i-1]+knapsackValue[i-1][j-weight[i-1]];
                        //是否到达最后一个点
                        path[i][j] = 1;
                    }
                    //如果不放入背包
                    else {
                        knapsackValue[i][j] = knapsackValue[i-1][j];
                    }
                }
            }
        }

        //展示
        for (int[] ints : knapsackValue) {
            for (int anInt : ints) {
                System.out.printf(anInt+" ");
            }
            System.out.println("");
        }
        int i = path.length - 1;
        int j = path[0].length - 1;
        while (i>0&&j>0){
            if (path[i][j] == 1){
                System.out.println("第"+i+"个商品放到背包");
                j = j- weight[i-1];
            }
            i--;
        }


    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115182.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux(11)配置环境变量「建议收藏」

    linux(11)配置环境变量「建议收藏」前言在自定义安装软件的时候,经常需要配置环境变量,下面进行详细解析&nbsp;环境变量配置文件|用户|配置文件||:|:||系统环境|/ect/profil

    2022年7月29日
    9
  • c++ accept_怎么把汇编语言转化为c语言

    c++ accept_怎么把汇编语言转化为c语言AcceptEx函数的定义如下:BOOLAcceptEx(SOCKETsListenSocket,SOCKETsAcceptSocket,PVOIDlpOutputBuffer,DWORDdwReceiveDataLength,DWORDdwLocalAddressLength,DWORDdwRemoteAddressLength,LPDWORDlpdwBytesReceived,…

    2022年9月29日
    1
  • 解决win10下VM12虚拟机桥接模式不能上网的方法(亲测可行)[通俗易懂]

    解决win10下VM12虚拟机桥接模式不能上网的方法(亲测可行)[通俗易懂]解决win10下VM12虚拟机桥接模式不能上网的方法(亲测可行)本文的方法可解决如下两个问题:局域网中其他机器ping不通本机中的虚拟机本机中的虚拟机采用桥接模式不能上网,甚至主机也不能上网。注意:自己局域网的IP起始地址及路由器地址,可以通过登陆路由器查看,也可以在所有操作之前在CMD中通过命令ipconfig(windows)或ifconfig(linux)查看。一般路由器的地…

    2022年6月10日
    41
  • linux下查看计划任务,linux查看计划任务.docx

    linux下查看计划任务,linux查看计划任务.docxlinux查看计划任务实验案列:管理进程及设置计划任务需求:管理系统中进程  设置计划运行的系统管理任务步骤:  1管理系统中地进程  启动系统中portmap服务,确认服务运行状态,通过ps或pgrep命令查看portmap的进程信息  Ps:查看静态的进程统计信息,a:显示当前终端下的所有进程信息,u:使用以用户为主的格式输出进程信息,x:显示当前用户在所有终端下的进程信息,-e:显示系统内的…

    2022年7月15日
    14
  • linux抓包UDP流量[通俗易懂]

    linux抓包UDP流量[通俗易懂]a)安装工具,命令如下:yuminstall-yngrepb)抓包,命令如下:timeout5ngrep-qWbyline’XXX’-dloport80

    2022年8月31日
    4
  • c语言sizeof()_sizeof函数的用法

    c语言sizeof()_sizeof函数的用法sizeof是C语言中保留关键字,也可以认为是一种运算符,单目运算符。常见的使用方式:inta=10;intarr=[1,2,3];charstr[]="hello";intlen_a=sizeof(a);intlen_arr=sizeof(arr);intlen_str=sizeof(str)printf("len_a=%d,len_arr=%d,le…

    2022年9月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号