文章目录
数组算法之排序
衡量排序算法优劣的标准:
-
时间复杂度。
-
空间复杂度。
-
稳定性。若两个记录A和B的关键字值相等,且排序后A、B的先后次序保持不变,则称这种排序算法是稳定的
分类:
- 内部排序:所有排序操作都在内存中完成,不需要外部存储器。
- 外部排序:参加排序的数据量非常大,需要接触外部存储器。常见的是多路归并排序。可认为外部排序是由多次内部排序组成。
十大内部排序算法:
- 选择排序:直接选择排序、堆排序。
- 交换排序:冒泡排序、快速排序。
- 插入排序:直接插入排序、折半插入排序、希尔排序。
- 归并排序。
- 桶式排序。
- 基数排序。
算法五大特征:
- 输入:0个或多个输入,输入必须有清楚的描述和定义。
- 输出:1个或多个输出。
- 有穷性:有限步骤内结束,且每一步在可接受时间内完成。
- 确定性:有明确的含义,无二义性。(此处指确定性算法,但目前诞生很多非确定性算法,比如深度学习相关算法等)
- 可行性:所有步骤清晰可行,用户可人为计算得出。
各大排序算法复杂度、稳定性等对比:
(”希堆快选“——不稳定;其余稳定)
冒泡排序
算法课学习过,不再赘述。实现如下:
public static int[] bubbleSort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
// nums[j] = nums[j] ^ nums[j + 1];
// nums[j + 1] = nums[j] ^ nums[j + 1];
// nums[j] = nums[j] ^ nums[j + 1];
// nums[j + 1] = (nums[j] ^ nums[j + 1]) ^ nums[j + 1];
// nums[j] = (nums[j] ^ nums[j + 1]) ^ nums[j + 1];
}
}
}
return nums;
}
快速排序
思想算法课学习过,不再赘述。实现如下:
注意点:1.递归思想及递归出口;2.必须从基准数的对面(右边)开始;
public static int[] fastSort(int[] nums, int left, int right) {
if (left < right) {
int base = nums[left];
int i = left;
int j = right;
while (i < j) {
while (i < j) {
if (nums[j] >= base) {
j--;
} else break;
}
while (i < j) {
if (nums[i] <= base) {
i++;
} else break;
}
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
}
nums[left] = nums[j];
nums[j] = base;
fastSort(nums, left, j - 1);
fastSort(nums, j + 1, right);
}
return nums;
}
Arrays工具类
java.utils.Arrays类提供操作数组的各种方法(比如排序和搜索等)。
- 判断两个数组是否相等(值):equals(int[] a, int[] b);
- 输出数组信息:toString(int[] a);
- 将指定值填充到数组中(会替换掉所有元素):fill(int[] a, int val);
- 对数组进行排序:sort(int[] a);
- 二分查找指定值:binarySearch(int[] a, int key);
数组常见异常
- 数组角标越界异常:ArrayIndexOutOfBoundsExcetion
- 空指针异常:NullPointerException(这个异常见过无数次了)
面向过程(POP)与面向对象(OOP)
二者都属于编程思想,面向对象是相对于面向过程而言的,“万事万物皆对象”。
-
面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。
-
面向对象,将功能封装到对象中,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
面向对象三大特征:继承、封装、多态。
类和对象
- 类:对一类事物的描述,是抽象的、概念上的定义。
- 对象:是存在的该类事物的每个个体,也称作实例(instance)。
常见的类成员:
- Field = 属性 = 成员变量
- Method = 方法 = 函数 = 成员方法 = 行为
通过“对象.属性”或“对象.方法”调用对象的结构。如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。
对象/对象数组内存解析
- 栈:即虚拟机栈。存储局部变量,方法执行完自动释放。
- 堆:存储对象实例(new出来的)。所有的对象实例以及数组都要在堆上分配。对象的属性及属性值也存储在堆。
- 方法区:存储方法、常量、静态变量、类信息、以及可编译器编译后的代码等数据。
匿名对象
创建的对象没有显式地赋给一个变量名,即为匿名对象。
特征:匿名对象只能调用一次。
使用:
new PhoneFactory().show(new Phone());
class PhoneFactory{
public void show(Phone phone){
phone.sendMail();
phone.playGame();
}
}
class Phone {
double price;
public void sendMail() {
System.out.println("发送邮件");
}
public void playGame() {
System.out.println("玩游戏");
}
}
属性(成员变量)和局部变量
相同点:
- 定义变量的方法相同: 数据类型 变量名 = 变量值;
- 先声明,后使用。
- 都有其对应的作用域。
不同点:
- 在类中声明的位置不同。
- 权限修饰符不同。属性可以使用private、protected、public等,但局部变量不可以使用权限修饰符。
- 默认初始值不同。属性根据其类型有默认初始值。局部变量没有初始化值,所以在调用局部变量之前,一定要显式赋值。特别地,形参在调用时,我们复制即可。
- 在内存中加载的位置不同。属性在堆(非static),局部变量在栈。
属性的赋值顺序:
- 默认初始值;
- 显式赋值;
- 构造器中赋值;
- 通过“对象.方法”或者”对象.属性“赋值。
方法
权限修饰符 返回类型 方法名(形参类型 形参,…){方法体}
注意:
- return关键字后面不可以声明执行语句。
- 方法的使用中,可以调用当前类的属性或方法。
- 方法中不可以定义方法。
重载
在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可。(两同一不同)
特点:与返回值类型、形参变量名、方法体、权限修饰符无关,只看参数列表,且参数列表必须不同。调用时根据方法参数列表的不同来区别。
可变个数形参(Varargs)
允许直接定义能和多个实参相匹配的形参。从而可以用一种更简单的方式来传递个数可变的实参。
可与同类中同名不同形参的方法之间构成重载,但是不能与同类中同名相同参数类型的数组构成重载。
可变形参在方法的形参中必须声明在末尾,且最多只能声明一个可变形参。
传入参数个数可以是0、1、2…个。
public static void show(String ... strs){
...
//传入参数个数:strs.length(当作数组处理)
//取值:strs[i]
}
调用:
//show("hello");
//show("hello","world");
//show();
public static void show(int i, String ... strs){
...
//传入参数个数:strs.length(当作数组处理)
//取值:strs[i]
}
调用:
//show(1,"hello");
//show(1,"hello","world");
//show(1);
值传递
Java中方法的参数传递方式只有一种:值传递。即,传入的是实参值的副本,实参本身不受影响。
基本数据类型传递:传递其“数值”;引用数据类型传递:传递其“地址”。
递归
一个方法体内调用方法它自身。
递归一定要指定正确的递归出口,防止出现无穷递归,类似死循环。
封装与隐藏
隐藏对象内部的复杂性,之对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性,一定程度上满足如下“追求”。
程序设计追求——“高内聚,低耦合”
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
- 低耦合:进对外暴露少量的方法用于使用。
封装性的体现:
1.类属性的封装;
-
private修饰符修饰属性,使其私有化。
-
类的set方法:即类属性的赋值操作,对类属性的数据类型和存储范围等进行制约。
-
类的get方法:即类属性的获取操作。
2.不对外暴露的私有方法;
3.单例模型;
权限修饰符
封装性的体现需要权限修饰符进行配合。Java规定4种权限修饰符:public、缺省、protected、private。
可以用来修饰属性、方法、构造器、内部类。
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | |
缺省 | Yes | Yes | ||
private | Yes |
其中,对于class的权限修饰符只能是public或者缺省。
构造器
作用:1.创建对象;2.初始化对象的属性;
如果类中未定义构造器,则系统默认提供一个空参的构造器。但是要注意,一旦显示定义了类的构造器后,系统就不再提供默认的空参构造器,如仍需空参构造器,则必须自己编写。
一个类的构造器支持重载。
一个类中至少有一个构造器。
JavaBean
JavaBean是一种Java语言写成的可重用组件,对组装环境具有较强的适应能力。
所谓JavaBean,是指符合如下标准的Java类:
- 类是公共的。
- 有一个无参的公共构造器。
- 有属性,且有对应的get、set方法。
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
UML类图
“#”->protected类型、"+"->public类型、"-"->private类型。
有下划线的方法是构造器。