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
- 要复制的数组元素的数量。
public static void main(String[] args) {
int[] src = {3,1,5,8,3,5,8,3,2,8};
int[] dest = new int[20];
System.arraycopy(src,0,dest,0,src.length);
for(int a : dest){
System.out.println(a);
}
}
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的和;
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();
}
}