排序

排序

基于比较的排序算法:

BUB - 冒泡排序

算法原理

1.比较相邻的元素,如果第一个比第二个大,就交换他们两个;

2.对每一对相邻的元素做同样的工作,从开始第一对到结尾的最后一对,比较完一轮,最大的元素就放到了最后一位;

3.针对所有元素重复以上步骤,除了最后一个;

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较;

算法分析

时间复杂度

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值:$C{min}=n-1$,$M{min}=0$

所以,冒泡排序最好的时间复杂度为O(n)。

若初始文件是反序的,需要进行$n-1$趟排序。每趟排序要进行$n-i$次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

$$
C_{max}=\frac{n(n-1)}{2}=O(n^2)
$$

$$
M_{max}=\frac{3n(n-1)}{2}=O(n^2)
$$

冒泡排序的最坏时间复杂度为:$O(n^2)$.

因此冒泡排序的总的平均时间复杂度为$O(n^2)$.

算法描述

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void bubbleSort(int arr[]){
for(int i=0;i<aar.length;i++){
boolean isSwap = false;
//从第一位和第二位开始比较,每一轮最大的数都排到了最后
for(int j=0; j<aar.length-i-1;j++){
//如果前面的元素大于后面的元素,交换位置
if(arr[j]>arr{j+1}){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1]=temp;
isSwap = true;
}
}
//如果没有换位,说明排序完成了
if(!isSwap){
break;
}
}
}

SEL - 选择排序

算法原理

算法分析

时间复杂度
算法描述

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void selectionSort(int[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;
for (int j = i+1; j < a.length; j++) {
if (a[min] > a[j]) {
min=j;
}
}
if (min != i) {
int temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
}

INS - 插入排序

算法原理

将第一个元素标记为已排序

遍历每个没有排序过的元素

“提取” 元素 X

i = 最后排序过元素的指数 到 0 的遍历

如果现在排序过的元素 > 提取的元素

将排序过的元素向右移一格

否则:插入提取的元素

算法分析

时间复杂度
算法描述

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void insertionSort(int[] a) {
for (int i = 1; i < a.length ; i++) {
//第一个元素为一个有序部分,故而,从数组第二个元素提取
int value = a[i];
//依次和有序部分从后往前比较,
for (int j = i - 1; j >0; j--) {
//如果取出的元素小于有序部分的元素,
if (a[j] > value) {
//那么有序部分的元素往后移动一位 即有序部分下标+1
a[j+1] = a[j];
//否则结束比较,提取元素插入最后移动的哪个元素的位置
} else {
a[j+1] = value;
break;
}
}
}
}

MER - 归并排序 (递归实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
*
* @param 排序数组
* @param 数组开头下标
* @param 数组长度
* @return
*/
private static int[] mergeSort(int[] a, int l, int h) {
if (l == h) {
return new int[]{a[l]};
}
int middle = l+(h-l)/2;
int[] leftArray = mergeSort(a, l, middle);
int[] rightArray = mergeSort(a, middle+1, h);
//新有序数组
int[] newNum = new int[leftArray.length + rightArray.length];
int leftIndex=0,rightIndex=0,newIndex=0;
while (leftIndex < leftArray.length && rightIndex < rightArray.length) {
newNum[newIndex++]= leftArray[leftIndex]<rightArray[rightIndex]?leftArray[leftIndex++]:rightArray[rightIndex++];
}
while (leftIndex < leftArray.length) {
newNum[newIndex++] = leftArray[leftIndex++];
}
while (rightIndex < rightArray.length) {
newNum[newIndex++] = rightArray[rightIndex++];
}
return newNum;
}

QUI - 快速排序 (递归实现)

R-Q - 随机快速排序 (递归实现)

不基于比较的排序算法:

COU - 计数排序

RAD - 基数排序

类装载

类装载

graph LR

A(loading)-->B(verifying)-->C(preparing)-->D(resolving)-->E(initializing)-->F(using)-->G(unload)
  • 在任何时刻,第一次访问某类,都会执行类装载
  • 访问包括三种情况:
    • 使用某类的static方法
    • 访问某类的static属性
    • 构造某类的对象
  • 声明没有初始化的引用Administrator admin;,并不会导致类装载(This is lazy load)
  • 一个类的装载只会执行一次

类装载的工作清单:

  1. 加载.class字节码文件:根据包语法决定的路径找到.class文件并加载
  2. 为static属性分配存储空间并全部置为默认值(Q:默认值是多少)
  3. 装载父类:如果这个类有父类,且父类还没有被装载过,则先装载它的父类;否则继续
  4. 进行类初始化:按照类定义中的顺序,从上到下初始化static属性和执行static块中的语句
  • 如果使用赋值运算符显示赋值,就执行赋值操作

    1
    private static int count=0;
    • 如果等号右边的值所述的类尚未被装载,那么先装载等号右边的类再赋值
  • 如果没有用赋值运算符显示赋值,则什么也不干(保留默认值)

    1
    private static Leader leader;
    • 即使这个属性所属的类尚未被装载,也不会去装载这个类lazy load
  • 如果static块中的语句会使用未装载的类,则先装载这个类,再执行这条语句

    1
    static{...}
    • 即使本类的所有方法(包括构造器)都会使用未装载的类,也不会导致类加载;直到这些方法真正被执行的时候,才会判断使用到的类是否已被装载lazy load
  • static块的执行和static属性的初始化是用一个过程,执行的先后顺序只取决于他们在类中定义的顺序

  • 父类的初始化在父类的装载过程中完成

对象构造

  1. 如果要构造的对象所属的类尚未被装载,先装载类
  2. 为非static属性分配存储空间并全部置默认值
  3. 调用父类constructor:如果这个类有父类,则先构造它的父类;否则继续
    • 如果显示通过super初始化父类,那么super必须是constructor的第一行代码
    • 根据类装载的顺序,此时父类一定被装载过了
  4. 初始化实例属性:按照类定义中的顺序,从上到下初始化非static属性
  5. 执行构造器中的其他代码,即super之外的所有代码

使用快速生成GoF设计模式的类图与代码

用StartUML生成GoF设计模式类图与代码

打开startuml,建立类图,File->new project by approach->选择Empty project
选择Model->Add->Model
选择Model->Add->Diagram->ClassDiagram
Tools->Options->选Java,勾选生成代码选项
右键画图区,弹出下图对话框,选择applay pattern,选Gof->然后 23中模式任你选~
Tools->Java->Generate Code 生成代码
File->Export Diagram 生成类图图片