数据结构与算法(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动态规划


问:背包总称重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--;
        }


    }
}
posted @ 2021-08-26 19:50  橡皮筋儿  阅读(44)  评论(0编辑  收藏  举报