1.API的初始
public static void arraycopy(int[] src,
int srcPos,
int[] dest,
int destPos,
int length)
将指定源数组中的数组从指定位置复制到目标数组的指定位置。阵列组件的一个子序列被从通过引用的源阵列复制src
被引用的目标阵列dest
。复制的组件数量等于length
参数。源阵列中位置srcPos
至srcPos+length-1
的组件分别复制到目标阵列的位置destPos
至destPos+length-1
。
如果src
个dest
参数指代相同的数组对象,则被处理是否在位置上的部件进行复印srcPos
通过srcPos+length-1
首先被复制到一个临时的阵列length
组分,然后将临时数组的内容被复制到的位置destPos
通过destPos+length-1
目标数组的。
如果dest
是null
,那么会抛出一个NullPointerException
。
如果src
是null
,则抛出一个NullPointerException
并且目标数组不被修改。
否则,如果以下任一为真,一个ArrayStoreException
抛出和不修改目标:
-
src
参数是指不是数组的对象。 -
dest
参数是指不是数组的对象。 -
src
参数和dest
参数是指组件类型是不同的基本类型的数组。 -
src
参数是指具有原始组件类型的数组,dest
参数是指具有引用组件类型的数组。 -
src
参数是指具有引用组件类型的数组,dest
参数是指具有原始组件类型的数组。
否则,如果以下任一为真,一个IndexOutOfBoundsException
抛出和不修改目标:
-
srcPos
论点是否定的。 -
destPos
论点是否定的。 -
length
论点是否定的。 -
srcPos+length
大于src.length
,源数组的长度。 -
destPos+length
大于dest.length
,目标数组的长度。
否则,如果来自位置srcPos
至srcPos+length-1
的源数组的任何实际组件无法通过转换转换为目标数组的组件类型,则抛出ArrayStoreException
。 在这种情况下,令*k*为比长度小于最小的非负整数,使得src[srcPos+
ķ ]
不能转换到组件类型目标数组的; 当抛出异常时,位置srcPos
至srcPos+
k -1
源阵列组件将已经被复制到目标阵列位置destPos
至destPos+
k -1
,并且目标阵列的其他位置将不会被修改。 (由于限制已经列出,本段仅适用于两个数组都具有引用类型的组件类型的情况。)
-
参数
src
- 源数组。srcPos
- 源数组中的起始位置。dest
- 目标数组。destPos
- 目的地数据中的起始位置。length
- 要复制的数组元素的数量。2 常见算法
-
算法:是指解决问题方法的准确而完整的描述,是一系列解决问题的清晰的指令,算法代表着用系统的方法描述解决问题的策略机制。
-
2.1 递归算法
递归: 在数学和计算科学中,指的是的定义中使用方法自身的方式。递归算法是一种直接或间接调用自身函数或者方法的算法。
需求: 求一个数的阶乘! 5! = 5 * 4 * 3 *2 * 1
5! = 5 * 4!; 4! = 4 * 3!; 3 ! = 3 * 2!; 2! = 2 * 1! ; 1! = 1;
2! = 2 *1
定义一个方法 方法可以计算任意数的阶乘!
递归的基本原理:
1 每一级的函数调用都有自己的变量;
2 每一次的函数的调用都会有一次返回;
3 递归函数中,位于递归调用前的语句和各级被调用的函数具有相同的执行顺序
4 递归函数中,位于递归调用后的语句的执行和各个调用函数的执行顺序是相反。
5 虽然在每一级递归都有自己的变量,但是函数的代码并不会得到复制。
递归的三大要素:
1 明确函数的功能
2 明确递归的结束条件
3 找出函数的等价关系式
public class JieCheng { public static void main(String[] args) { int res = func(5); System.out.println(res); } public static int func(int n){ if(n == 1){//结束条件 return 1; }else{ int res = n * func(n - 1);// 5! = 5 * 4!; 4! = 4 * 3!; 3 ! = 3 * 2!; 2! = 2 * 1! ; 1! = 1; return res; } } }
练习:使用递归算法 实现一个求1---n的和;
import java.util.Scanner; public class Sum{ public static void main(String[]args){ Scanner input=new Scanner(System.in); int n=input.nextInt(); int sum=add(n); System.out.print(sum); } public static int add(int n){ if(n==1){ return 1; } else { int sum=n+add(n-1); return sum; } }
2.2 排序算法
选择排序: 直接选择排序 堆排序
交换排序:冒泡排序 快速排序
插入排序:直接插入 折半插入排序 shell 排序
归并排序
桶式排序
基数排序
2.2.1 冒泡排序
冒泡排序的思想:
1 比较相邻元素 如果第一个比第二个大 就交换连个的位置
2 对每一对相邻的元素做同样的比较,从开始第一对到结尾最后一对 最后的元素应该是最大的数
3 针对所有元素排序需要重复以上的比较的步骤 但是要排除已经排序的元素
4 持续每次对越来越少的元素重复上面的步骤,知道没有任何一堆数字需要比较
public class BubbleSort { public static void main(String[] args) { int[] arr ={3,15,2,6,4,7,9,8}; for(int j = arr.length -1;j > 0 ; j--){//控制比较的次数 for(int i = 0 ; i < j;i++){ if(arr[i] > arr[i+1]){//如果前边的元素大于后边的元素 则交换连个元素的位置 int temp = arr[i]; arr[i]= arr[i +1]; arr[i + 1] = temp; } } } for(int a : arr){ System.out.println(a); } } }
代码的重构:
1 让代码的结构更加清晰 便于阅读和维护
2 让代码能够复用 减少代码的冗余
public class BubbleSort { public static void main(String[] args) { int[] arr ={3,15,2,6,4,7,9,8}; sort(arr); print(arr); } // 使用冒泡算法 对整数数组进行排序 public static void sort(int[] arr){ for(int j = arr.length -1;j > 0 ; j--){//控制比较的次数 for(int i = 0 ; i < j;i++){ if(arr[i] > arr[i+1]){//如果前边的元素大于后边的元素 则交换连个元素的位置 swap(arr,i,i+1); } } } } // 交换数组中两个的位置 public static void swap(int[] arr, int index1, int index2){ int temp = arr[index1]; arr[index1]= arr[index2]; arr[index2] = temp; } //数组的遍历 public static void print(int[] arr){ for(int a : arr){ System.out.println(a); } } }
对数组的遍历 :按照以下的形式输出:[2,3,1,5,6]
2.2.2 快速排序
快速排序采用的是一种分治思想 快速排序可以看作是冒泡排序的升级版
思想:
1 从数组中挑出一个元素 称为”基准元素“
2 重新排序数组,所有元素比基准元素小的 放在基准元素的前面,所有比基准元素大的 放在基准的 后面。在这个分区结束之后,该基准元素就处于数组的中间位置。称为分区操作。
3 递归的把小于基准元素的子数组和大于基准元素的子数列排序
4 递归的最底部的情形 是数列的大小是零或 1 也就是永远都已经被排序好了 虽然这样一直递归下去,但是这个算法总会要结束,因为在每次的迭代中,他至少会把一个元素摆在他最后的位置。
public class QuciSort { public static void main(String[] args) { int[] arr ={3,15,2,6,4,7,9,8}; quickSort(arr); print(arr); } public static void quickSort(int[] arr){ if(arr == null || arr.length == 0 ){ return; } sort(arr,0,arr.length - 1); } // 核心算法 public static void sort(int[] arr,int left,int right){ if(left > right){//递归的结束条件 return; } // 选择基准元素 int base = arr[left]; int i = left; int j = right; while( i != j){ while(arr[j] >= base && i < j){//从右边开始寻找比基准元素大的元素 如果比基准元素大 则继续向前寻找 j--; } // 从左往右找 找比基准元素小的 如果比基准元素小 则继续往后找 while(arr[i] <= base && i < j){ i++; } if(i < j ){// 如果从右往左找打比基准元素小的 从左往右找到比基准元素大的 则交换两个元素的位置 让大区右边 让小的 去左边 int temp = arr[i]; arr[i] =arr[j]; arr[j] = temp; } } // 将基准元素放到中间位置(基准归位) arr[left] = arr[i]; arr[i]= base; // 递归 继续进行左右两边的快速排序 sort(arr,left,i -1); sort(arr,i+1,right); } //数组的遍历 public static void print(int[] arr){ for(int a : arr){ System.out.println(a); } } }
2.2.3 选择排序
选择排序 是一种简单直观的排序算法。原理:在没有排序的数组中找出最小的(最大的)与第一个位置的元素进行交换
选择排序和冒泡排序的区别:
冒泡排序通过一次交换相邻两个元素的位置,从而将当前最大的元素放置到最后的位置。选择排序 ,每遍历一次 都记住当前最小的元素的位置,最后仅需交换一次即可将元素放到合适的位置。
思想:
1 数组排序 ,数组是无序的
2 第一次排序:从n-1个元素中找出最大的元素与第一个元素进行交换
3 后边就以此类推
public class SelectSort { public static void main(String[] args) { int[] arr ={3,15,2,6,4,7,9,8}; for(int i = 0 ; i < arr.length;i++){ int minIndex= i;// 假设第一个元素是最小 同时使用minIndex记录最小元素所在的位置 for(int j = i + 1; j < arr.length;j++){ if(arr[j] < arr[minIndex]){//找到比假设的最小元素小的的元素 minIndex = j;// 记录最小元素的位置 } } // 找到其中的最小的元素 将最小的元素和第一个元素交换位置 if(minIndex != i){ int temp = arr[i]; arr[i]= arr[minIndex]; arr[minIndex] = temp; } } // 遍历数组 for(int a : arr){ System.out.println(a); } } }
2.3 二分查找算法
二分检索法(折半检索)。二分检索法的基本思想是:假设数组中的元素是有序存放(排序)。首先确定我们要查找的值(key)。将key与数组中的中间位置的元素进行比较,如果key< 中间值,则说明要查找的元素位于左半部分,如果key > 中间值,则说明要查找的元素 位于右半部份。如果key=中间值,则说明中间的元素就是我们要找的元素。
二分检索法是一种效率较高的检索方法。
public class SearchKey { public static void main(String[] args) { int[] arr = {12,32, 34,45, 54,65,71,82}; boolean flag = search(arr,32); System.out.println(flag); } /** * * @param arr 是目标数组 * @param key 是目标值 * @return */ public static boolean search(int[] arr, int key){ int start = 0;//查找的开始位置 int end = arr.length -1;//查找的结束为止 while(start <= end){ int mid = (start + end ) /2; if(key == arr[mid]){ return true; }else if(key < arr[mid]){ end = mid -1; }else if(key > arr[mid]){ start = mid + 1; } } return false; } }
public class SearchKey { public static void main(String[] args) { int[] arr = {12,32, 34,45, 54,65,71,82}; int flag = search(arr,30); System.out.println(flag); } /** * * @param arr 是目标数组 * @param key 是目标值 * @return 表示目标元素所在的位置 如果返回-1 则表示目标元素不存在 */ public static int search(int[] arr, int key){ int start = 0;//查找的开始位置 int end = arr.length -1;//查找的结束为止 int index= -1; while(start <= end){ int mid = (start + end ) /2; if(key == arr[mid]){ index = mid; return index; }else if(key < arr[mid]){ end = mid -1; }else if(key > arr[mid]){ start = mid + 1; } } return index; } }
2.4 Arrays 工具类
public static void main(String[] args) { int[] arr ={2,24,4,43,222,456,64,32,211,2,3}; //使用Arrays提供的方法 对数组进行排序 Arrays.sort(arr); //遍历数组 for(int a : arr){ System.out.println(a); } }
public static void main(String[] args) { int[] arr ={2,24,4,43,222,456,64,32,211,2,3}; //使用Arrays提供的方法 对数组进行排序 Arrays.sort(arr);//必须先排序 int res = Arrays.binarySearch(arr,2); System.out.println(res);
import java.util.Arrays; public class ArraysDemo { public static void main(String[] args) { int[] arr ={2,24,4,43,222,456,64,32,211,2,3}; //填充数组 /* public static void fill(int[] a, int fromIndex, int toIndex, int val) */ Arrays.fill(arr,3,6,100); //遍历数组 // for(int a : arr){ // System.out.println(a); // } System.out.println(Arrays.toString(arr)); } }
3 面向对象
3.1何谓“面向对象”的编程思想
思想:原则
渐悟 ? or 顿悟?
3.2 表格结构和类结构
表格思维 就是一种典型的面向对象的思维
学号 姓名 专业 年龄 100010 张三 数学 18 100011 李四 计算机 20 100012 王五 软件工程 21 100013 赵六 物理学 18 3.3 面向过程和面向对象
面向过程和面向对象都是对软件分析 设计 开发的一种思想。
面向对象开发的阶段:面向对象的分析阶段(OOA) 面向对象的设计(OOD) 面向对象的编程(OOP)
C 语言是一种典型的面向过程的语言,java是典型的面向对象的语言。
面向过程是一种执行者的思维
面向对象是一种指挥者的思维
面向过程和面向对象两者是不可分割的:
宏观上:通过面向对象进行整体的设计
微观上:执行和数据的处理 仍然是面向过程。
3.4 面向对象
了解事物的详细信息,并关注他,这个过程称为面向对象。
面向一个具体的事物进行操作,称为面向对象编程
面向对象的两大核心:
-
类:是对现实生活中一类具有共同属性的行为的事物的抽象
-
类的特点:
-
类是对象的数据类型
-
类是具有相同属性和行为的一组对象的集合
-
-
-
对象 类的具体化
-
属性 对象具有的各种特种,每个对象的每个属性拥有特定的值
-
行为 对象能够执行的操作
类和对象的关系:
类 是对现实生活中一类具有共同属性的行为的事物的抽象
对象 就是该类下的一个真实存在的实体
3.5 类的定义
类的重要性:是java程序的基本组成单元
类可以看作是一类对象的模板,对象可以看作是该类的一个具体实例
类是用于描述同一类型的对象的抽象概念,类中定义了这一类对象所具有的共同属性和方法。
类的组成是由属性和行为两部分组成:
属性:在类中通过成员变量来体现
成员变量: 定义在类的内部,方法的外部的变量
行为:在类中是通过成员方法来体现的。
成员方法:和前边讲过的方法相同 只是去掉方法上的static
类的定义步骤:
1 定义一个类
2 编写类的成员变量
3 编写类的成员方法
/* 手机类: 类名: 手机(phone) 属性(成员变量): 品牌:brand 价格:price 行为:成员方法 打电话:call 发信息:sendMessage */ public class Phone { //成员变量 String brand; double price; //成员方法: public void call(){ System.out.println("打电话"); } public void sendMessage(){ System.out.println("发信息"); } }
3.6 对象的创建和使用
创建对象:类名(类型) 对象名(变量) = new 类名();
Phone p = new Phone();
使用对象:
1 使用成员变量:
格式: 对象名.属性名;//获取属性
对象名.属性名 = 对应类型的值; //给属性赋值
2 使用成员方法
格式 对象名.方法名(实参列表)
/* 手机类: 类名: 手机(phone) 属性(成员变量): 品牌:brand 价格:price 行为:成员方法 打电话:call 发信息:sendMessage */ public class Phone { //成员变量 String brand; double price; //成员方法: public void call(){ System.out.println("打电话"); } public void sendMessage(){ System.out.println("发信息"); } public static void main(String[] args) { Phone p = new Phone();//创建对象 //属性赋值 p.brand = "华为"; p.price = 3999.99; System.out.println(p.brand +"----"+p.price); p.call(); p.sendMessage(); } }
练习:
创建一个学生类:自行分析学生属性和行为 并完成对象的创建和属性的赋值 和信息的输出。
public class Student { String name; String sex; int age; public void study(){ System.out.println("学习英语"); } public void eat(){ System.out.println("吃刀削面"); } public static void main(String[]args){ Student i=new Student(); i.name="毕业生"; i.sex="男"; i.age=18; System.out.print(i.name+"\n"+i.sex+"\n"+i.age+"\n"); i.study(); i.eat(); } }
-