数据结构与算法weeks05

       10大算法
       在这里插入图片描述

开始~~~



十大算法

1.二分查找算法

1.1基本介绍

       1)二分查找法只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后再进行查找。
       2)二分查找法的运行时间为对数时间O(㏒₂n) ,即查找到需要的目标位置最多只需要㏒₂n步,假设从[0,99]的队列(100个数,即n=100)中寻到目标数30,则需要查找步数为㏒₂100 , 即最多需要查找7次( 2^6 < 100 < 2^7)。

1.2代码

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;
}

2.分治算法

2.1基本介绍

       分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……
       分治算法可以求解的一些经典问题:
       二分搜索、大整数乘法、棋盘覆盖、合并排序、快速排序、线性时间选择、最接近点对问题、循环赛日程表、汉诺塔

2.2分治算法的基本步骤

       分治法在每一层递归上都有三个步骤:

       1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题。
       2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题。
       3)合并:将各个子问题的解合并为原问题的解。

2.3汉诺塔游戏的思路分析

       1)如果是有一个盘, A->C
       2)如果我们有 n >= 2 情况,我们总是可以看做是两个盘 ①最下边的盘 ②上面的盘
              先把 最上面的盘 A->B
              把最下边的盘 A->C
              把B塔的所有盘 从 B->C

在这里插入图片描述

2.4代码

public static void hanoiTower(int num,char a,char b,char c){
	//如果只一个盘
	if(num == 1){
		System.out.println("第1个盘从" + a + "->" + c);
	}else{
		//如果我们n>=2情况,我们总是可以看作是两个盘 1.最下边的一个盘  2.上面的所盘
		//1.先把上面的所盘A->B,移动过程使用到C
		hanoiTower(num - 1, a, c, b);
		//2.把最下面的盘A->C
		System.out.println("第" + num + "个盘从" + a + "->" + c);
		//3.把B塔的所盘从B->C,移动过程中使用到A塔
		hanoiTower(num - 1, b, a, c);
	}
}

3.动态规划算法

3.1应用场景

       背包问题:有一个背包,容量为4磅 , 现有如下物品

在这里插入图片描述
       1)要求达到的目标为装入的背包的总价值最大,并且重量不超出
       2)要求装入的物品不能重复

3.2动态规划算法介绍

       1)动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法。
       2)动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
       3)与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。( 即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解 )。
       4)动态规划可以通过填表的方式来逐步推进,得到最优解。

3.3背包问题的思路分析

在这里插入图片描述

3.4代码

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

    int[][] v = 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;
    }

    for (int i = 1; i < v.length; i++) {
        for (int j = 1; j < v[i].length; j++) {
            if (w[i - 1] > j){
                v[i][j] = v[i - 1][j];
            }else{
                if (v[i - 1][j] > val[i - 1] + v[i - 1][j - w[i - 1]]){
                    v[i][j] = v[i - 1][j];
                }else{
                    v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
                    path[i][j] = 1;
                }
            }
        }
    }
    int i = path.length - 1;
    int j = path[0].length - 1;
    while (i > 0 && j > 0){
        if (path[i][j] == 1){
            System.out.printf("第%d个商品加入背包\n",i);
            j -= w[i - 1];
        }
        i--;
    }
}

4.KMP算法

4.1应用场景

       字符串匹配问题:

       1)有一个字符串 str1= ““硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好””,和一个子串 str2=“尚硅谷你尚硅你”。
       2)现在要判断 str1 是否含有 str2, 如果存在,就返回第一次出现的位置, 如果没有,则返回-1。

4.2暴力匹配算法

       如果用暴力匹配的思路,并假设现在str1匹配到 i 位置,子串str2匹配到 j 位置,则有:

       1)如果当前字符匹配成功(即str1[i] == str2[j]),则i++,j++,继续匹配下一个字符
       2)如果失配(即str1[i] ! = str2[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0
       3)用暴力方法解决的话就会有大量的回溯,每次只移动一位,若是不匹配,移动到下一位接着判断,浪费了大量的时间
       4)暴力匹配算法实现:

public static int violenceMatch(String str1,String str2){
	char[] s1 = str1.toCharArray();
	char[] s2 = str2.toCharArray();
	int s1Len = s1.length;
	int s2Len = s2.length;
	int i = 0;//i索引指向s1
	int j = 0;//i索引指向s2
	while(i < s1Len && j < s2Len){//保证匹配时,不越界
		if(s1[i] == s2[j]){//匹配
			i++;
			j++;
		}else{//没匹配成功
			i = i - (j - 1);
			j = 0;
		}
	}
	//判断是否匹配成功
	if(j == s2Len){
		return i - j;
	}
	return -1;
}

4.3KMP算法介绍

       1)KMP是一个解决模式串在文本串是否出现过,如果出现过,最早出现的位置的经典算法
       2)KMP方法算法就利用之前判断过的信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间。

4.4KMP算法最佳应用-字符串匹配问题

       有一个字符串 str1= “BBC ABCDAB ABCDABCDABDE”,和一个子串 str2="ABCDABD"现在要判断 str1 是否含有 str2, 如果存在,就返回第一次出现的位置, 如果没有,则返回-1
       要求:使用KMP算法完成判断,不能使用简单的暴力匹配算法

       代码:

public static int kmpSearch(String str1,String str2,int[] next){
	//遍历
	for(int i = 0,j = 0;i < str1.length();i++){
		while(j > 0 && str1.charAt(i) != str2.charAt(j)){
			j = next[j - 1];
		}
		if(str1.charAt(i) == str2.charAt(j)){
			j++;
		}
		if(j == str2.length()){
			return i - j + 1;
		}
	}
	return -1;
}
//获取到一个字符串(子串)的部分匹配值表
public static int[] kmpNext(String dest){
	//创建一个next数组保存部分匹配值
	int[] next = new int[dest.length()];
	next[0] = 0;//如果字符串是长度为1部分匹配值就是0
	for(int i = 1,j = 0;i < dest.length();i++){
		//当dest.charAt(i) != dest.charAt(j),需要从next[j - 1]获取新的j
		//直到发现dest.charAt(i) == dest.charAt(j)成立才退出
		while(j > 0 && dest.charAt(i) != dest.charAt(j)){
			j = next[j - 1];
		}
		//当dest.charAt(i) == dest.charAt(j)满足时,部分匹配值就是+1
		if(dest.charAt(i) == dest.charAt(j)){
			j++;
		}
		next[i] = j;
	}
	return next;
}

5.贪心算法

5.1应用场景-集合覆盖问题

       假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号。
在这里插入图片描述

5.2贪心算法介绍

       1)贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。
       2)贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果。

5.3贪心算法最佳应用-集合覆盖

       1)假设存在如下表的需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号

在这里插入图片描述
       2)思路分析
       ①可以使用穷举法来实现,列出每个可能的广播台的集合。假设总的有n个广播台,则广播台的组合总共有2ⁿ -1 个,假设每秒可以计算10个子集

在这里插入图片描述
       ②使用贪婪算法,效率高
       1)遍历所有的广播电台, 找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系)
       2)将这个电台加入到一个集合中(比如ArrayList), 想办法把该电台覆盖的地区在下次比较时去掉。
       3)重复第1步直到覆盖了全部的地区

       4)思路图解:
在这里插入图片描述       3)代码

//创建广播电台,放入到map
HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
HashSet<String> hashSet1 = new HashSet<>();
hashSet1.add("北京");
hashSet1.add("上海");
hashSet1.add("天津");
HashSet<String> hashSet2 = new HashSet<>();
hashSet2.add("广州");
hashSet2.add("北京");
hashSet2.add("深圳");
HashSet<String> hashSet3 = new HashSet<>();
hashSet3.add("成都");
hashSet3.add("上海");
hashSet3.add("杭州");
HashSet<String> hashSet4 = new HashSet<>();
hashSet4.add("上海");
hashSet4.add("天津");
HashSet<String> hashSet5 = new HashSet<>();
hashSet5.add("杭州");
hashSet5.add("大连");

broadcasts.put("K1", hashSet1);
broadcasts.put("K2", hashSet2);
broadcasts.put("K3", hashSet3);
broadcasts.put("K4", hashSet4);
broadcasts.put("K5", hashSet5);

//allAreas存放所的地区
HashSet<String> allAreas = new HashSet<>();
allAreas.add("北京");
allAreas.add("上海");
allAreas.add("天津");
allAreas.add("广州");
allAreas.add("深圳");
allAreas.add("成都");
allAreas.add("杭州");
allAreas.add("大连");

//创建一个ArrayList,存放择的电台集合
ArrayList<String> selects = new ArrayList<>();

//定义一个临时的集合,在遍历的过程中,存放电台覆盖的区域和当前还没覆盖的地区的交集
HashSet<String> tempSet = new HashSet<>();
//定义给maxKey,保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的key
//如果maxKey不为null,则加入到selects中
String maxKey;
int maxSize;
while(allAreas.size() != 0){//如allAreas不为0,则表示还没覆盖到所的地区
	maxKey = null;
	//遍历broadcasts,取出key
	for(String key : broadcasts.keySet()){
		tempSet.clear();
		//当前这个key能够覆盖的地区
		HashSet<String> areas = broadcasts.get(key);
		tempSet.addAll(areas);
		//求出tempSet与allAreas集合的交集,交集会赋给tempSet
		tempSet.retainAll(allAreas);
		if(maxKey == null){
			maxSize = 0;
		}else{
			HashSet<String> maxSet = broadcasts.get(maxKey);
			maxSet.retainAll(allAreas);
			maxSize = maxSet.size();
		}
//				if(tempSet.size() > 0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())){
		if(tempSet.size() > 0 && (maxKey == null || tempSet.size() > maxSize)){
			maxKey = key;
		}
	}
	if(maxKey != null){
		selects.add(maxKey);
		allAreas.removeAll(broadcasts.get(maxKey));
	}
}
System.out.println(selects);

6.普里姆算法

6.1应用场景-修路问题

在这里插入图片描述

       1)胜利乡有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通
       2)各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
       问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短
       正确的思路,就是尽可能的选择少的路线,并且每条路线最小,保证总里程数最少

6.2最小生成树

       修路问题本质就是就是最小生成树问题

       最小生成树:
       1)给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树
       2)N个顶点,一定有N-1条边
       3)包含全部顶点
       4)N-1条边都在图中
       如图:
在这里插入图片描述       5)求最小生成树的算法主要是普里姆算法和克鲁斯卡尔算法

6.3普里姆算法介绍

       1)普利姆(Prim)算法求最小生成树,也就是在包含n个顶点的连通图中,找出只有(n-1)条边包含所有n个顶点的连通子图,也就是所谓的极小连通子图。
       2)普利姆的算法如下:
       ①设G=(V,E)是连通网,T=(U,D)是最小生成树,V,U是顶点集合,E,D是边的集合
       ②若从顶点u开始构造最小生成树,则从集合V中取出顶点u放入集合U中,标记顶点v的visited[u]=1
       ③若集合U中顶点ui与集合V-U中的顶点vj之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点vj加入集合U中
       ④将边(ui,vj)加入集合D中,标记visited[vj]=1
       ⑤重复步骤②,直到U与V相等,即所有顶点都被标记为访问过,此时D中有n-1条边

6.4解决修路问题

在这里插入图片描述       1)有胜利乡有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通
       2)各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
       3)问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?
       4)代码:

public class PrimAlgorithm {
	public static void main(String[] args) {
		char[] data = new char[]{'A','B','C','D','E','F','G'};
		int verxs = data.length;
		//邻接矩阵的关系使用二维数组表示,用10000表示两个点不联通
		int[][] weight = new int[][]{
			{10000,5,7,10000,10000,10000,2},
			{5,10000,10000,9,10000,10000,3},
			{7,10000,10000,10000,8,10000,10000},
			{10000,9,10000,10000,10000,4,10000},
			{10000,10000,8,10000,10000,5,4},
			{10000,10000,10000,4,5,10000,6},
			{2,3,10000,10000,4,6,10000}
		};
		//创建Graph对象
		MGraph graph = new MGraph(verxs);
		MinTree minTree = new MinTree();
		minTree.createGraph(graph, verxs, data, weight);
		//输出
		minTree.showGraph(graph);
		minTree.prim(graph, 0);
	}
}

// 创建最小生成树->村庄的图
class MinTree {
	/**
	 * 
	 * @Description 创建图的邻接矩阵
	 * @author jiatianyu 
	 * @date 2021年3月18日下午2:23:02 
	 * @param graph 图对象
	 * @param verxs 图对应的顶点个数
	 * @param data 图的各个顶点的值
	 * @param weight 图的邻接矩阵
	 */
	public void createGraph(MGraph graph, int verxs, char data[], int[][] weight) {
		int i,j;
		for(i = 0;i < verxs;i++){//顶点
			graph.data[i] = data[i];
			for(j = 0;j < verxs;j++){
				graph.weight[i][j] = weight[i][j];
			}
		}
	}
	//显示图的结构
	public void showGraph(MGraph graph){
		for(int[] link : graph.weight){
			System.out.println(Arrays.toString(link));
		}
	}
	
	public void prim(MGraph graph,int v){
		//visited[] 标记点(顶点)是否被访问过
		int[] visited = new int[graph.verxs];
		//把当前这个结点标记为已访问
		visited[v] = 1;
		//h1和h2记录两个顶点的下标
		int h1 = -1;
		int h2 = -1;
		int minWeight = 10000;//将minWeight初始成一个大数,后面在遍历过程中会被替换
		for(int k = 1;k < graph.verxs;k++){//因为graph.verxs个顶点,总共需要graph.verxs - 1个边
			//每一次生成的子图,和那个结点的距离最近
			for(int i = 0;i < graph.verxs;i++){//i结点表示被访问过的结点
				for(int j = 0;j < graph.verxs;j++){//j结点表示没被访问过的结点
					if(visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight){
						//替换minWeight
						minWeight = graph.weight[i][j];
						h1 = i;
						h2 = j;
					}
				}
			}
			//找到一条边最小
			System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + ">权值:" + minWeight);
			//将当前这个结点标记为已经访问
			visited[h2] = 1;
			//minWeight重新设置成最大值10000
			minWeight = 10000;
		}
	} 
}
class MGraph {
	int verxs;// 表示图的结点个数
	char[] data;// 存放结点数据
	int[][] weight;// 存放边,即邻接矩阵

	public MGraph(int verxs) {
		this.verxs = verxs;
		data = new char[verxs];
		weight = new int[verxs][verxs];
	}
}

7.克鲁斯卡尔算法

7.1应用场景-公交站问题

在这里插入图片描述       1)某城市新增7个站点(A, B, C, D, E, F, G) ,现在需要修路把7个站点连通
       2)各个站点的距离用边线表示(权) ,比如 A – B 距离 12公里
       问:如何修路保证各个站点都能连通,并且总的修建公路总里程最短?

7.2克鲁斯卡尔算法介绍

       1)克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。
       2)基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路
       3)具体做法:首先构造一个只含n个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止

7.3克鲁斯卡尔最佳实践-公交站问题

在这里插入图片描述       1)有北京有新增7个站点(A, B, C, D, E, F, G) ,现在需要修路把7个站点连通
       2)各个站点的距离用边线表示(权) ,比如 A – B 距离 12公里
       3)问:如何修路保证各个站点都能连通,并且总的修建公路总里程最短?
       4)代码:

public class KruskalCase {
	
	private int edgeNum;//边的个数
	private char[] vertexs;//顶点数组
	private int[][] matrix;//邻接矩阵
	//使用INF表示两个顶点不能联通
	private static final int INF = Integer.MAX_VALUE;
	
	public static void main(String[] args) {
		char[] vertexs = {'A','B','C','D','E','F','G'};
		int matrix[][] = {
		{0,12,INF,INF,INF,16,14},
		{12,0,10,INF,INF,7,INF},
		{INF,10,0,3,5,6,INF},
		{INF,INF,3,0,4,INF,INF},
		{INF,INF,5,4,0,2,8},
		{16,7,6,INF,2,0,9},
		{14,INF,INF,INF,8,9,0}
		};
		//创建KruskalCase对象实例
		KruskalCase kruskalCase = new KruskalCase(vertexs, matrix);
		EData[] edges = kruskalCase.getEdges();
		kruskalCase.sortEdges(edges);
		kruskalCase.kruskal();
		
	}
	
	//构造器
	public KruskalCase(char[] vertexs,int[][] matrix){
		//初始化顶点数和边的个数
		int vlen = vertexs.length;
		
		//初始化顶点,复制拷贝的方式
		this.vertexs = new char[vlen];
		for(int i = 0;i < vertexs.length;i++){
			this.vertexs[i] = vertexs[i];
		}
		
		//初始化边,使用的是复制拷贝的方式
		this.matrix = new int[vlen][vlen];
		for(int i = 0;i < vlen;i++){
			for(int j = 0;j < vlen;j++){
				this.matrix[i][j] = matrix[i][j];
			}
		}
		//统计边
		for(int i = 0;i < vlen;i++){
			for(int j = i + 1;j < vlen;j++){
				if(this.matrix[i][j] != INF){
					edgeNum++;
				}
			}
		}
	}
	
	public void kruskal(){
		int index = 0;//表示最后结果数组的索引
		int[] ends = new int[edgeNum];//用于保存"已最小生成树"中的每个顶点在最小生成树中的终点
		//创建结果数组,保存最后的最小生成树
		EData[] rets = new EData[edgeNum];
		
		//获取图中所的边的集合,一共有12边
		EData[] edges = getEdges();
		sortEdges(edges);
		
		//遍历edges数组,将边添加到最小生成树中时,判断准备加入的边是否形成了回路,如果没,就加入rets,否则不能加入
		for(int i = 0;i < edgeNum;i++){
			//获取到第i条边的第一个顶点(起点)
			int p1 = getPosition(edges[i].start);//p1 = 4
			//获取到第i条边的第2个顶点
			int p2 = getPosition(edges[i].end);//p2 = 5
			
			//获取p1这个顶点在已最小生成树中的终点
			int m = getEnd(ends,p1);//m = 4;
			//获取p2这个顶点在已最小生成树中的终点
			int n = getEnd(ends,p2);//n = 5;
			
			//是否构成回路
			if(m != n){//没构成回路
				ends[m] = n;//设置m在"已最小生成树"中的终点
				rets[index++] = edges[i];
			}
			
		}
		
		//打印rets
		System.out.println("最小生成树为:");
		for(int i = 0;i < index;i++){
			System.out.println(rets[i]);
		}
	}
	//打印邻接矩阵
	public void print(){
		System.out.println("邻接矩阵为:\n");
		for(int i = 0;i < vertexs.length;i++){
			for(int j = 0;j < vertexs.length;j++){
				System.out.printf("%12d\t",matrix[i][j]);
			}
			System.out.println();//换行
		}
	}
	//对边进行排序处理,冒泡排序
	private void sortEdges(EData[] edges){
		EData temp = null;
		for(int i = 0;i < edges.length - 1;i++){
			for(int j = 0;j < edges.length - 1 -i;j++){
				if(edges[j].getWeight() > edges[j + 1].getWeight()){
					temp = edges[j];
					edges[j] = edges[j + 1];
					edges[j + 1] = temp;
				}
			}
		}
	}
	
	/**
	 * 
	 * @Description  
	 * @author jiatianyu 
	 * @date 2021年3月18日下午9:44:25 
	 * @param ch ch:顶点值,比如'A','B'
	 * @return 顶点ch对应的下标,如果找不到,返回-1
	 */
	private int getPosition(char ch){
		for(int i = 0;i < vertexs.length;i++){
			if(vertexs[i] == ch){
				return i;
			}
		}
		return -1;
	}
	
	private EData[] getEdges(){
		int index = 0;
		EData[] edges = new EData[edgeNum];
		for(int i = 0;i < vertexs.length;i++){
			for(int j = i + 1;j < vertexs.length;j++){
				if(matrix[i][j] != INF){
					edges[index++] = new EData(vertexs[i], vertexs[j], matrix[i][j]);
				}
			}
		}
		return edges;
	}
	
	/**
	 * 
	 * @Description 获取下标为i的顶点的终点,用于判断两个顶点的终点是否相同
	 * @author jiatianyu 
	 * @date 2021年3月19日上午11:55:43 
	 * @param ends 数组记录了各个顶点的对应的终点是哪个,ends数组是在遍历过程中,逐步形成的
	 * @param i 表示传入的顶点对应的下标
	 * @return 返回下标为i的顶点对应的终点的下标
	 */
	private int getEnd(int[] ends,int i){
		while(ends[i] != 0){
			i = ends[i];
		}
		return i;
	}	
}

//创建一个类EData,它的对象实例表示一条边
class EData{
	char start;//边的一个点
	char end;//边的另一个点
	int weight;//边的权值
	//构造器
	public EData(char start, char end, int weight) {
		super();
		this.start = start;
		this.end = end;
		this.weight = weight;
	}
	//重写toString,便于输出边
	@Override
	public String toString() {
		return "EData [start=" + start + ", end=" + end + ", weight=" + weight + "]";
	}
	public char getStart() {
		return start;
	}
	public void setStart(char start) {
		this.start = start;
	}
	public char getEnd() {
		return end;
	}
	public void setEnd(char end) {
		this.end = end;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}
}

总结

To be continued~~,JavaEE部分

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值