栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java数据结构与算法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java数据结构与算法

目录

递归

递归的概念

递归调用机制

打印问题代码

 运行结果

阶乘问题 

 运行结果

递归调用机制讲解

递归调用规则

递归能解决什么样的问题

递归用于解决什么样的问题

 递归需要遵守的重要规则

迷宫回溯问题分析和实现(1)

迷宫问题

 代码实现

运行结果

 迷宫回溯问题分析和实现(2)

代码实现

运行效果

 递归-八皇后问题(回溯算法)

八皇后问题算法思路分析

代码实现

运行结果

 ​

 排序算法介绍和分类

排序的分类

 算法的时间复杂度

1)事后统计的方法

2)事前估算的方法

时间频度


递归

递归的概念

简单的说,递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

递归调用机制

打印问题代码
package recursion;

public class RecursionTest {

	public static void main(String[] args) {
		//通过打印问题,回顾递归调用机制
		test(4);
	}
	//输出什么?
	public static void test(int n){
	if(n>2){
	test(n-1);
	}
	System.out.println("n="+n);
	}
}

 运行结果

阶乘问题 
//阶乘
public static int factorial(int n){
if(n==1){
return 1;
}else{
return factorial(n-1)*n;
}}
 运行结果

递归调用机制讲解

递归调用规则

1.当程序执行到一个方法时就会开辟一个独立的空间(栈)

2.每个空间的数据(局部变量),是独立的。

递归能解决什么样的问题

递归用于解决什么样的问题

1)各种数学问题:8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(google编程大赛)

2)各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等

3)将用栈解决的问题->递归代码比较简洁

 递归需要遵守的重要规则

1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间)

2)方法的局部变量是独立的,不会相互影响,比如n变量

3)如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据

4)递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError死龟了

5)当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时方法执行完毕或者返回时,该方法也就执行完毕。

迷宫回溯问题分析和实现(1)

迷宫问题

 代码实现
package recursion;

public class MiGong {

	public static void main(String[] args) {
		// 先创建一个二维数组,模拟迷宫
		//地图
		int[][] map=new int[8][7];
		//使用1 表示墙
		//上下全部置为1
		for (int i = 0; i < 7; i++) {
			map[0][i]=1;
			map[7][i]=1;
		}
		
		//左右全部置为1
		for (int i = 0; i < 8; i++) {
			map[i][0]=1;
			map[i][6]=1;
		}
		//设置挡板,1表示
		map[3][1]=1;
		map[3][2]=1;
		map[1][2]=1;
		map[2][2]=1;
		//输出地图
		System.out.println("地图的情况");
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 7; j++) {
				System.out.print(map[i][j]+" ");
			}
			System.out.println();
		}
		//使用递归回溯给小球找路
		setWay( map, 1,1);
		
		//输出新的地图,小球走过,并标识过的地图的情况
		
	}
	//使用递归回溯来给小球找路
	//说明
	//1.map 表示地图
	//2.i,j表示从地图的哪个位置开始出发(1,1)
	//3.如果小球能到map[6][5]位置,则说明通路找到
	//4.约定:当map[i][j]为0表示该点没有走过当为1表示墙,2表示通路可以走,3表示该点已经走过,3表示该点已经走过,但是走不通
	//5.在走迷宫时,需要确定一个策略(方法)下->右->上->左,表示该点走不通,再回溯
	
	
	public static boolean setWay(int[][] map,int i,int j) {
		if (map[6][5]==2) {//通路已经找到ok了
			return true;			
		}else {
			if (map[i][j]==0) {//如果当前这个点还没有走过
				//按照策略 下->右->上->左 走
				map[i][j]=2;//假定该点可以走通
				if (setWay(map, i+1, j)) {//向下走
					return true;
				}else if (setWay(map, i, j+1)) {//向右走
					return true;						
				}else if (setWay(map, i-1, j)) {//向上
					return true;
				}else if (setWay(map, i, j-1)) {//向左走
					return true;
				}else {
					//说明该点走不通,是死路
					map[i][j]=3;
					return false;
				}
			}else {
				//如果map[i][j]!=0,可能是1,2,3
				return false;
			}
		}
	}
}

运行结果

 迷宫回溯问题分析和实现(2)

代码实现
package recursion;

public class MiGong {

	public static void main(String[] args) {
		// 先创建一个二维数组,模拟迷宫
		//地图
		int[][] map=new int[8][7];
		//使用1 表示墙
		//上下全部置为1
		for (int i = 0; i < 7; i++) {
			map[0][i]=1;
			map[7][i]=1;
		}
		
		//左右全部置为1
		for (int i = 0; i < 8; i++) {
			map[i][0]=1;
			map[i][6]=1;
		}
		//设置挡板,1表示
		map[3][1]=1;
		map[3][2]=1;
//		map[1][2]=1;
//		map[2][2]=1;
		
		//输出地图
		System.out.println("地图的情况");
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 7; j++) {
				System.out.print(map[i][j]+" ");
			}
			System.out.println();
		}
		//使用递归回溯给小球找路
		//setWay( map, 1,1);
		setWay2(map, 1, 1);
		
		//输出新的地图,小球走过,并标识过的地图的情况
		System.out.println("小球走过,并标识过的地图的情况");
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 7; j++) {
				System.out.print(map[i][j]+" ");
			}
			System.out.println();
		}
	}
	//使用递归回溯来给小球找路
	//说明
	//1.map 表示地图
	//2.i,j表示从地图的哪个位置开始出发(1,1)
	//3.如果小球能到map[6][5]位置,则说明通路找到
	//4.约定:当map[i][j]为0表示该点没有走过当为1表示墙,2表示通路可以走,3表示该点已经走过,3表示该点已经走过,但是走不通
	//5.在走迷宫时,需要确定一个策略(方法)下->右->上->左,表示该点走不通,再回溯
	
	
	public static boolean setWay(int[][] map,int i,int j) {
		if (map[6][5]==2) {//通路已经找到ok了
			return true;			
		}else {
			if (map[i][j]==0) {//如果当前这个点还没有走过
				//按照策略 下->右->上->左 走
				map[i][j]=2;//假定该点可以走通
				if (setWay(map, i+1, j)) {//向下走
					return true;
				}else if (setWay(map, i, j+1)) {//向右走
					return true;						
				}else if (setWay(map, i-1, j)) {//向上
					return true;
				}else if (setWay(map, i, j-1)) {//向左走
					return true;
				}else {
					//说明该点走不通,是死路
					map[i][j]=3;
					return false;
				}
			}else {
				//如果map[i][j]!=0,可能是1,2,3
				return false;
			}
		}
	}
	
	//修改找路的策略,改成上->右->下->左
	public static boolean setWay2(int[][] map,int i,int j) {
		if (map[6][5]==2) {//通路已经找到ok了
			return true;			
		}else {
			if (map[i][j]==0) {//如果当前这个点还没有走过
				//按照策略 下->右->上->左 走
				map[i][j]=2;//假定该点可以走通
				if (setWay2(map, i-1, j)) {//向上走
					return true;
				}else if (setWay(map, i, j+1)) {//向右走
					return true;						
				}else if (setWay(map, i-1, j)) {//向下
					return true;
				}else if (setWay(map, i, j-1)) {//向左走
					return true;
				}else {
					//说明该点走不通,是死路
					map[i][j]=3;
					return false;
				}
			}else {
				//如果map[i][j]!=0,可能是1,2,3
				return false;
			}
		}
	}
}

运行效果

 递归-八皇后问题(回溯算法)

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例,该问题是国际西洋棋棋手马克斯.贝瑟尔于1848年提出:在8*8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

使用到回溯算法

八皇后问题算法思路分析

1)第一个皇后先放第一行第一列

2)第二个皇后放在第二行第一列、然后判断是否OK,如果不OK,继续放在第二列、第三列、依次把所有列都完,找到一个合适。

3)继续第三个皇后,还是第一列、第二列......直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解

4)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到。

5)然后回头继续第一个皇后放第二列,后面继续循环执行1,2,3,4的步骤

说明:理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题.arr[8]={0,4,7,5,2,6,1,3}//对应arr 下标 表示第几行,即第几个皇后,arr[i]=val表示第i+1个皇后,放在第i+1行的。

代码实现
package recursion;

public class Queue8 {
	
	//定义一个max表示共有多少个皇后
	int max=8;
	//定义数组array,保存皇后放置位置的结果,比如arr={0,4,7,5,2,6,1,3}
	int[] array=new int[max];
	static int count=0;
	static int judgeCount=0;
	public static void main(String[] args) {
		//测试一把,8皇后是否正确
		Queue8 queue8=new Queue8();
		queue8.check(0);
		System.out.printf("一共有%d解法",count);
		System.out.printf("一共判断冲突的次数%d次",judgeCount);//1.5w
	}
	
	//编写一个方法,放置第n个皇后
	//特别注意:check是每一次递归时,进入到check中都有for(int i=0;i 
运行结果 

 

 排序算法介绍和分类

排序也称排序算法,排序是将一组数据,依指定的顺序进行的过程。

排序的分类

1)内部排序:

指将需要处理的所有数据都加载到内部存储器中进行排序

2)外部排序法:

数据量过大,无法全部加载到内存中,需要借助外部存储进行排序

3)常见的排序算法分类

 算法的时间复杂度

度量一个程序(算法)执行时间的两种方法

1)事后统计的方法

这种方法可行,但是有两个问题:一是要想对设计的算法的运行性能进行评测,需要实际运行该程序;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素,这种方式,要在同一台计算机的相同状态下运行,才能比较那个算法速度更快。

2)事前估算的方法

通过分析某个算法的时间复杂度来判断哪个算法更迭

时间频度

一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多,一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)

 结论:1)2n+20和2n随着n变大,执行曲线无限接近,20可以忽略

              2)3n+10和3n随着n变大,执行曲线无限接近,10可以忽略

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/344817.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号