数据结构与算法(十一)(常用的十大算法)

本文深入解析十大常用算法,包括二分查找、分治法、动态规划、暴力匹配与KMP算法、贪心算法、普利姆算法、Kruskal算法、Dijkstra算法、弗洛伊德算法以及骑士周游问题的解决方案,涵盖了数据结构与算法的核心概念和应用。
摘要由CSDN通过智能技术生成

二分查找(非递归)

package binarysearchnorecursion;

public class BinarySearchNoRecur {
   
    public static void main(String[] args) {
   
        int[] arr = {
   1,3,8,10,11,67,100};
        System.out.println(binarySearch(arr,-8));
    }

    public static int binarySearch(int[] arr,int target){
   
        int left = 0;
        int right = arr.length-1;
        while(left <= right){
   
            int mid = (left + right)/2;
            if(arr[mid] == target){
   
                return  mid;
            }else if(arr[mid] > target){
   
                right = mid -1;
            }else{
   
                left = mid +1;
            }
        }
        return -1;
    }
}

分治算法

1.思想介绍:
a.分解,将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
b.解决,如果若干个小问题比较好解决,就直接解决,否则递归解决
c.合并,将若干个小问题的解合起来就是原问题的解
2.能解决的问题
二分搜索,归并排序,快速排序,汉诺塔
3.汉诺塔问题分析
a.如果只有一个盘,就直接将盘从A移动到C
b.如果盘数大于等于2,将所有盘分为两部分,最后一个盘自己一部分,剩下的盘一部分
c.先将剩下的盘移动到B,再将最后一个盘移动到C,最后将剩下的盘从B移动到C
4.代码实现

package dac;

public class Hanoitower {
   
    public static void main(String[] args) {
   
        hanoitower(3,'A','B','C');
    }

    public static void hanoitower(int num,char a,char b,char c){
   
        if(num == 1){
   
            System.out.println("将第1个盘从"+a+"移动到"+c);
        }else{
   
            hanoitower(num-1,a,c,b);
            System.out.println("将第"+num+"个盘从"+a+"移动到"+c);
            hanoitower(num-1,b,a,c);
        }
    }
}

动态规划算法

1.算法思想:与分治算法类似,也是将大问题转换成小问题,再解决小问题,区别在于动态规划算法,下一个子阶段的求解是建立在上一个子阶段的基础上,而分治算法,每个子阶段都是独立的
2.背包问题问题描述:
在这里插入图片描述
3.问题分析
a.分析动态规划算法可以使用画图的方式
在这里插入图片描述
b.从上面的表格我们可以总结出规律:v[i][j]表示前i个物品能装入容量为j的容器的最大价值,val[i]表示第i个物品的价值,w[i]表示第i个物品的重量
v[i][0] = j[0][j] = 0表示第一行第一列全部为空
如果w[i]>j,代表当前物品的容量大于背包能承受的容量,所以直接延续上一个v[i][j] = v[i-1][j]
如果w[i]<=j,v[i][j] = max{v[i-1][j],val[i]+v[i-1][j-w[i]]},此时背包容量可以装下当前物品,所以就先装入当前物品,再去找剩下的容量可以装下的物品(最大价值)与上一个做对比,找到二者中最大的
4.代码实现

package dynamic;

public class KnapsackProblem {
   
    public static void main(String[] args) {
   
        int[] w = {
   1,4,3};//物品重量
        int[] vals = {
   1500,3000,2000};//物品价值
        int m = 4 ;//背包容量
        int n = w.length;//物品个数

        //表示前i个物品能装入容量为j的容器的最大价值
        int[][] v = new int[n+1][m+1];
        //标记可能出现的最大值
        int[][] path = new int[n+1][m+1];
        //将第一行第一列设置为空
        for(int i=0;i<v.length;i++){
   
            v[i][0] = 0;
        }
        for(int i=0;i<v[0].length;i++){
   
            v[0][i] = 0;
        }
        //比较w[i-1]与j的大小关系,分别填入数据
        for(int i=1;i<v.length;i++){
   
            for(int j=1;j<v[0].length;j++){
   
                if(w[i-1]>j){
   
                    v[i][j] = v[i-1][j];
                }else{
   
                    if(v[i-1][j]<vals[i-1]+v[i-1][j-w[i-1]]){
   
                        v[i][j] = vals[i-1]+v[i-1][j-w[i-1]];
                        path[i][j] = 1;
                    }else{
   
                        v[i][j] = v[i-1][j];
                    }
                }
            }
        }

        for(int i=0;i<v.length;i++){
   
            for(int j=0;j<v[i].length;j++){
   
                System.out.print(v[i][j]+" ");
            }
            System.out.println();
        }

        for(int i=0;i<v.length;i++){
   
            for(int j=0;j<v[i].length;j++){
   
                System.out.print(path[i][j]+" ");
            }
            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 -= w[i-1];
            }
            i--;
        }
    }
}

暴力匹配和KMP算法

1.暴力匹配(字符串)思路分析:
假设有字符串S1,S2,我们用S2(指针j)去S1(指针i)里面匹配,从0开始一个字符一个字符对比,如果相同就同时后移,如果发现不同S2指针直接移动到0,S1移动到i-j+1,再次匹配,此时效率很低
2.代码实现

package kmp;

public class ViolenceMatch {
   
    public static void main(String[] args) {
   
        String str1 = "AABCEDERQWWE";
        String str2 = "RQq";
        System.out.println(violenceMatch(str1,str2));
    }

    public static int violenceMatch(String str1,String str2){
   
        char[] chars1 = str1.toCharArray();
        char[] chars2 = str2.toCharArray();
        int length1 = str1.length();
        int length2 = str2.length();

        int i=0;
        int j=0;
        while(i<length1 && j<length2){
   
            if(chars1[i] == chars2[j]){
   
                i++;
                j++;
            }else{
   
            	i = i-j+1;
                j=0;
            }
        }
        if(j == length2){
   
            return i-j;
        }
        return -1;
    }
}

3.KMP算法思路分析
KMP和暴力匹配最大的不同在于,发现不同时,KMP并非是移动1位,而是通过算法移动n位,这样提高效率,在使用KMP时首先需要创造出部分匹配表,在使用部分匹配表完成移位,提高效率
4.代码实现

package kmp;

import java.util.Arrays;

public class KMPAlgorithm {
   
    public static void main(String[] args) {
   
        String str1 = "BBC ABCDAB ABCDABCDABDE";
        String str2 = "ABCDABD";
        int[] next = kmpNext(str2);
        System.out.println(Arrays.toString(kmpNext(str2)));
        System.out.println(kmp(str1,str2,next));
    }

    public static int kmp(String str1,String str2,int[] next){
   
        for(int i=0,j=0;i<str1.length();i++){
   
            while(j>0 && str1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值