文章目录

 

数组的概述

  • 数组(Array)
    是多个相同类型数据一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
  • 数组的常见概念
    • 数组名
    • 下标(或索引)
    • 元素
    • 数组的长度
  • 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括 基本数据类型和引用数据类型。
  • 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是 这块连续空间的首地址。
  • 数组的长度一旦确定,就不能修改
  • 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
  • 数组的分类:
    按照维度:一维数组、二维数组、三维数组、…
    按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)

一维数组的使用

一维数组的使用:声明

  • 一维数组的声明方式
    type var[] 或 type[] var;

    例如:
int a[];
int[] a1;
double    b[];
String[] c; //引用类型变量数组
  • Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法

一维数组的使用:初始化

  • 动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行
    int[] arr = new int[3];
    arr[0] = 3;
    arr[1] = 9;
    arr[2] = 8;
    String names[];
    names = new String[3];  names[0] = “钱学森”;
    names[1] = “邓稼先”;
    names[2] = “袁隆平”;    
  • 静态初始化:在定义数组的同时就为数组元素分配空间并赋值。
int arr[] = new int[]{ 3, 9, 8};
int[] arr = {3,9,8};
    String names[] = {
    “李四光”,“茅以升”,“华罗庚”
    }

一维数组的使用:数组元素的引用

  • 定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;

  • 数组元素的引用方式:数组名[数组元素下标]

    • 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];

    • 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]a[1]a[2]

  • 每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)

    • 数组一旦初始化,其长度是不可变的

一维数组的使用:数组元素的默认初始化值

  • 数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式 初始化。例如:
public class Test {
        public static void main(String argv[]){  
            int a[]= new int[5];
            System.out.println(a[3]);    //a[3]的默认值为0
        }
    }
  • 对于基本数据类型而言,默认初始化值各有不同
  • 对于引用数据类型而言,默认初始化值为null(注意与0不同!)
数组元素类型 元素默认初始值
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0
char 0或写为:’\u0000’(表现为空)
   
boolean false
引用类型 null

创建基本数据类型数组

  • Java中使用关键字new来创建数组
  • 如下是创建基本数据类型元素的一维数组
public class Test{
        public static void main(String args[]){
            int[] s;//图示1
            s = new int[10];
            for ( int i=0; i<10; i++ ) {  
                s[i] =2*i+1;
                System.out.println(s[i]);
            }
        }
    }

图示1处内存状态:
Java基础之数组_i++

public class Test{
        public static void main(String args[]){
            int[] s;
            s = new int[10];//图示2
            //int[] s=new int[10];
            //基本数据类型数组在显式赋值之前,
            //Java会自动给他们赋默认值。
            for ( int i=0; i<10; i++ ) {  
                s[i] =2*i+1;
                System.out.println(s[i]);
            }
        }
    }

图示2处内存状态:
Java基础之数组_java_02

public class Test{
        public static void main(String args[]){
            int[] s;
            s = new int[10];
            for ( int i=0; i<10; i++ ) {
                s[i] =2*i+1;//图示3  
                System.out.println(s[i]);
            }
        }
    }

图示3处内存状态:
Java基础之数组_i++_03

内存的简化结构

Java基础之数组_数组元素_04

一维数组的内存解析

Java基础之数组_一维数组_05

Java基础之数组_一维数组_06
Java基础之数组_数组元素_07

练习1

升景坊单间短期出租4个月,550元/月(水电煤公摊,网费35元/月),空调、卫生间、厨房齐全。 屋内均是IT行业人士,喜欢安静。所以要求来租者最好是同行或者刚毕业的年轻人,爱干净、安静。

public class ArrayTest {
        public static void main(String[] args) {  
            int[] arr = new int[]{8,2,1,0,3};
            int[] index = new int[]{2,0,3,2,4,0,1,3,2,3,3};  
            String tel = "";
            for(int i = 0;i < index.length;i++){  
                tel += arr[index[i]];
            }
            System.out.println("联系方式:" + tel);
        }
    }

 

Java基础之数组_java_08

练习2.

从键盘读入学生成绩,找出最高分, 并输出学生成绩等级。

成绩>=最高分-10 ------- 等级为’A’
成绩>=最高分-20 ------- 等级为’B’
成绩>=最高分-30 ------- 等级为’C’
其 余 ------- 等级为’D’

提示:先读入学生人数,根据人数创建int数组, 存放学生成绩。

 1 package com.ak.java;
 2 
 3 import java.util.Scanner;
 4 
 5 /*
 6  * 2. 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
 7         成绩>=最高分-10    等级为’A’   
 8         成绩>=最高分-20    等级为’B’
 9         成绩>=最高分-30    等级为’C’   
10         其余                               等级为’D’
11         
12         提示:先读入学生人数,根据人数创建int数组,存放学生成绩。
13 
14  * 
15  */
16 public class ArrayDemo1 {
17     public static void main(String[] args) {
18         //1.使用Scanner,读取学生个数
19         Scanner scanner = new Scanner(System.in);
20         System.out.println("请输入学生人数:");
21         int number = scanner.nextInt();
22         
23         //2.创建数组,存储学生成绩:动态初始化
24         int[] scores = new int[number];
25         //3.给数组中的元素赋值
26         System.out.println("请输入" + number + "个学生成绩:");
27         int maxScore = 0;
28         for(int i = 0;i < scores.length;i++){
29             scores[i] = scanner.nextInt();
30             //4.获取数组中的元素的最大值:最高分
31             if(maxScore < scores[i]){
32                 maxScore = scores[i];
33             }
34         }
35 //        for(int i = 0;i < scores.length;i++){
36 //            if(maxScore < scores[i]){
37 //                maxScore = scores[i];
38 //            }
39 //        }
40         
41         //5.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩
42         char level;
43         for(int i = 0;i < scores.length;i++){
44             if(maxScore - scores[i] <= 10){
45                 level = 'A';
46             }else if(maxScore - scores[i] <= 20){
47                 level = 'B';
48             }else if(maxScore - scores[i] <= 30){
49                 level = 'C';
50             }else{
51                 level = 'D';
52             }
53             
54             System.out.println("student " + i + 
55                     " score is " + scores[i] + ",grade is " + level);
56         }
57         
58     }
59 }

 

Java基础之数组_一维数组_09

二维数组的使用

  • Java 语言里提供了支持多维数组的语法。
  • 如果说可以把一维数组当成几何中的线性图形, 那么二维数组就相当于是一个表格
  • 对于二维数组的理解,我们可以看成是一维数组 array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。

二维数组[ ][ ]:数组中的数组

  • 格式1(动态初始化): int[][] arr = new int[3][2]; 

    • 定义了名称为 arr 的二维数组

    • 二维数组中有3个一维数组

    • 每一个一维数组中有2个元素

    • 一维数组的名称分别为 arr[0], arr[1], arr[2] 

    • 给第一个一维数组1脚标位赋值为78写法是: arr[0][1] = 78; 

  • 格式2(动态初始化): int[][] arr = new int[3][]; 

    • 二维数组中有3个一维数组。

    • 每个一维数组都是默认初始化值null (注意:区别于格式1)

    • 可以对这个三个一维数组分别进行初始化

     arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2]; 
    
    • 注:
      int[][]arr = new int[][3]; //非法
  • 格式3(静态初始化): int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}}; 

    • 定义一个名称为arr的二维数组,二维数组中有三个一维数组 每一个一维数组中具体元素也都已初始化。

    • 第一个一维数组  arr[0] = {3,8,2}; 

    • 第二个一维数组  arr[1] = {2,7}; 

    • 第三个一维数组  arr[2] = {9,0,1,6}; 

    • 第三个一维数组的长度表示方式: arr[2].length; 

    • 注意特殊写法情况: int[] x,y[];  x是一维数组,y是二维数组。

    • Java中多维数组必都是规则矩阵形式。

例子:

	 int[][] arr = new int[3][2]; 

或者

  int[][] arr = new int[3][];  
   arr[0] = new int[2];  
   arr[1] = new int[2];  
   arr[2] = new int[2];

Java基础之数组_一维数组_10

   int[][] arr = new int[3][];  
    arr[0] = new int[2];  
    arr[1] = new int[3];  
    arr[2] = new int[4];

Java基础之数组_一维数组_11

二维数组的内存解析

Java基础之数组_数组元素_12
Java基础之数组_数组_13

Java基础之数组_一维数组_14
Java基础之数组_数组_15

练习3

获取arr数组中所有元素的和。 提示:使用for的嵌套循环即可。


Java基础之数组_数组元素_16

 1 package com.ak.java;
 2 
 3 public class ArrayExer1 {
 4     
 5     public static void main(String[] args) {
 6         int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
 7         
 8         int sum = 0;//记录总和
 9         for(int i = 0;i < arr.length;i++){
10             for(int j = 0;j < arr[i].length;j++){
11                 sum += arr[i][j];
12             }
13         }
14         
15         System.out.println("总和为:" + sum);
16     }
17     
18 }

 

Java基础之数组_数组元素_17

练习4

声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:

提示:
一维数组:int[] x 或者int x[]
二维数组:int[][] y 或者 int[] y[] 或 者 int y[][]

a ) x[0] = y;no
b) y[0] = x;yes
c) y[0][0] = x;no
d) x[0][0] = y; no
e) y[0][0] = x[0]; yes
f) x = y; no

数组中涉及的常见算法

1.数组元素的赋值(杨辉三角、回形数等)

2.求数值型数组中元素的最大值、最小值、平均数、总和等

3.数组的复制、反转、查找(线性查找、二分法查找)

4.数组元素的排序算法

练习5

使用二维数组打印一个 10 行杨辉三角。

【提示】

  • 第一行有 1 个元素, 第 n 行有 n 个元素
  • 每一行的第一个元素和最后一个元素都是 1
  • 从第三行开始, 对于非第一个元素和最后一个元素的元素。即: yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

Java基础之数组_java_18

 1 package com.ak.java;
 2 /*
 3  * 使用二维数组打印一个 10 行杨辉三角。
 4 
 5 【提示】
 6  1. 第一行有 1 个元素, 第 n 行有 n 个元素
 7  2. 每一行的第一个元素和最后一个元素都是 1
 8  3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
 9 yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
10  * 
11  */
12 public class YangHuiTest {
13     
14     public static void main(String[] args) {
15         //1.声明并初始化二维数组
16         int[][] yangHui = new int[10][];
17         
18         //2.给数组的元素赋值
19         for(int i = 0;i < yangHui.length;i++){
20             yangHui[i] = new int[i + 1];
21             
22             //2.1 给首末元素赋值
23             yangHui[i][0] = yangHui[i][i] = 1;
24             //2.2 给每行的非首末元素赋值
25             //if(i > 1){
26             for(int j = 1;j < yangHui[i].length - 1;j++){
27                 yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
28             }
29             //}
30         }    
31         
32         //3.遍历二维数组
33         for(int i = 0;i < yangHui.length;i++){
34             for(int j = 0;j < yangHui[i].length;j++){
35                 System.out.print(yangHui[i][j] + "  ");
36             }
37             System.out.println();
38         }        
39     }    
40 }

 

Java基础之数组_一维数组_19

练习6

定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,
然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。

要求:所有随机数都是两位数。

提示:

[0,1) * 90 --->[0,90)	+ 10	---> [10,100) --->[10,99]
(int)(Math.random() * 90 + 10)
 1 package com.ak.java;
 2 /*
 3  * 算法的考查:求数值型数组中元素的最大值、最小值、平均数、总和等
 4  * 
 5  * 定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,
 6  * 然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。    
 7  * 要求:所有随机数都是两位数。
 8  * 
 9  * [10,99]
10  * 公式:(int)(Math.random() * (99 - 10 + 1) + 10)
11  * 
12  */
13 public class ArrayTest1 {
14     public static void main(String[] args) {
15         int[] arr = new int[10];
16         
17         for(int i = 0;i < arr.length;i++){
18             arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
19         }
20         
21         //遍历
22         for(int i = 0;i < arr.length;i++){
23             System.out.print(arr[i] + "\t");
24         }
25         System.out.println();
26         
27         //求数组元素的最大值
28         int maxValue = arr[0];
29         for(int i = 1;i < arr.length;i++){
30             if(maxValue < arr[i]){
31                 maxValue = arr[i];
32             }
33         }
34         System.out.println("最大值为:" + maxValue);
35         
36         //求数组元素的最小值
37         int minValue = arr[0];
38         for(int i = 1;i < arr.length;i++){
39             if(minValue > arr[i]){
40                 minValue = arr[i];
41             }
42         }
43         System.out.println("最小值为:" + minValue);
44         //求数组元素的总和
45         int sum = 0;
46         for(int i = 0;i < arr.length;i++){
47             sum += arr[i];
48         }
49         System.out.println("总和为:" + sum);
50         //求数组元素的平均数
51         int avgValue = sum / arr.length;
52         System.out.println("平均数为:" + avgValue);
53     }
54 }

 

Java基础之数组_一维数组_20

练习7

使用简单数组

(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量, 他们是int[]类型的数组。

(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。

(3)显示array1的内容。

(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1。

思考:array1和array2是什么关系?
拓展:修改题目,实现array2对array1数组的复制

Java基础之数组_i++_21
Java基础之数组_数组_22

 1 package com.ak.java;
 2 /*
 3  * 使用简单数组
 4 (1)创建一个名为ArrayExer2的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
 5 (2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
 6 (3)显示array1的内容。
 7 (4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1。
 8  * 
 9  * 思考:array1和array2是什么关系?array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体。
10  * 拓展:修改题目,实现array2对array1数组的复制
11  */
12 public class ArrayExer2 {
13     public static void main(String[] args) {  //alt + /
14         int[] array1,array2;
15         
16         array1 = new int[]{2,3,5,7,11,13,17,19};
17         
18         //显示array1的内容
19         for(int i = 0;i < array1.length;i++){
20             System.out.print(array1[i] + "\t");
21         }
22         
23         //赋值array2变量等于array1
24         //不能称作数组的复制。
25         array2 = array1;
26         
27         //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
28         for(int i = 0;i < array2.length;i++){
29             if(i % 2 == 0){
30                 array2[i] = i;
31             }
32             
33         }
34         System.out.println();
35         //打印出array1
36         for(int i = 0;i < array1.length;i++){
37             System.out.print(array1[i] + "\t");
38         }
39     }
40 }

 

Java基础之数组_数组元素_23

 1 package com.ak.java;
 2 /*
 3  * 使用简单数组
 4  * 拓展:修改题目,实现array2对array1数组的复制
 5  */
 6 public class ArrayExer3 {
 7     public static void main(String[] args) {  //alt + /
 8         int[] array1,array2;
 9         
10         array1 = new int[]{2,3,5,7,11,13,17,19};
11         
12         //显示array1的内容
13         for(int i = 0;i < array1.length;i++){
14             System.out.print(array1[i] + "\t");
15         }
16         
17         //数组的复制:
18         array2 = new int[array1.length];
19         for(int i = 0;i < array2.length;i++){
20             array2[i] = array1[i];
21         }
22 
23         
24         //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
25         for(int i = 0;i < array2.length;i++){
26             if(i % 2 == 0){
27                 array2[i] = i;
28             }
29             
30         }
31         System.out.println();
32         //打印出array1
33         for(int i = 0;i < array1.length;i++){
34             System.out.print(array1[i] + "\t");
35         }
36     }
37 }

 

Java基础之数组_数组元素_24

二分法查找算法

Java基础之数组_一维数组_25

 1 package com.ak.java;
 2 /*
 3  * 算法的考查:数组的复制、反转、查找(线性查找、二分法查找)
 4  * 
 5  * 
 6  */
 7 public class ArrayTest2 {
 8     
 9     public static void main(String[] args) {
10         
11         String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
12         
13         
14         //数组的复制(区别于数组变量的赋值:arr1 = arr)
15         String[] arr1 = new String[arr.length];
16         for(int i = 0;i < arr1.length;i++){
17             arr1[i] = arr[i];
18         }
19         
20         //数组的反转
21         //方法一:
22 //        for(int i = 0;i < arr.length / 2;i++){
23 //            String temp = arr[i];
24 //            arr[i] = arr[arr.length - i -1];
25 //            arr[arr.length - i -1] = temp;
26 //        }
27         
28         //方法二:
29 //        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
30 //            String temp = arr[i];
31 //            arr[i] = arr[j];
32 //            arr[j] = temp;
33 //        }
34         
35         //遍历
36         for(int i = 0;i < arr.length;i++){
37             System.out.print(arr[i] + "\t");
38         }
39         
40         System.out.println();
41         //查找(或搜索)
42         //线性查找:
43         String dest = "BB";
44         //dest = "CC";
45         
46         boolean isFlag = true;
47         
48         for(int i = 0;i < arr.length;i++){
49             
50             if(dest.equals(arr[i])){
51                 System.out.println("找到了指定的元素,位置为:" + i);
52                 isFlag = false;
53                 break;
54             }
55             
56         }
57         if(isFlag){
58             System.out.println("很遗憾,没有找到的啦!");
59             
60         }
61         //二分法查找:(熟悉)
62         //前提:所要查找的数组必须有序。
63         int[] arr2 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
64         
65         int dest1 = 34;
66         //dest1 = 35;
67         int head = 0;//初始的首索引
68         int end = arr2.length - 1;//初始的末索引
69         boolean isFlag1 = true;
70         while(head <= end){
71             
72             int middle = (head + end)/2;
73             
74             if(dest1 == arr2[middle]){
75                 System.out.println("找到了指定的元素,位置为:" + middle);
76                 isFlag1 = false;
77                 break;
78             }else if(arr2[middle] > dest1){
79                 end = middle - 1;
80             }else{//arr2[middle] < dest1
81                 head = middle + 1;
82             }
83 
84             
85         }
86         
87         if(isFlag1){
88             System.out.println("很遗憾,没有找到的啦!");
89         }
90         
91         
92     }
93 }

 

Java基础之数组_数组_26

排序算法:

  • 排序:假设含有n个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为{K1,K2,…,Kn}。将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键字值满足条Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。

    通常来说,排序的目的是快速查找

  • 衡量排序算法的优劣:

    • 时间复杂度:分析关键字的比较次数和记录的移动次数
    • 空间复杂度:分析排序算法中需要多少辅助内存
    • 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

排序算法分类:内部排序外部排序

  • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排 序操作都在内存中完成。

  • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排 序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最 常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

十大内部排序算法

  • 选择排序
    • 直接选择排序

    • 堆排序(讲解过程)

  • 交换排序
    • 冒泡排序
    • 快速排序(要能够手写源码)
  • 插入排序
    • 直接插入排序
    • 折半插入排序
    • Shell(希尔)排序
  • 归并排序(讲解过程)
  • 桶式排序
  • 基数排序
(简单)选择排序.gif

Java基础之数组_java_27

(直接)插入排序.gif

Java基础之数组_i++_28

堆排序.gif

Java基础之数组_数组_29

归并排序.gif

Java基础之数组_i++_30

基数排序.gif

Java基础之数组_数组元素_31

计数排序.gif

Java基础之数组_数组元素_32

快速排序.gif

Java基础之数组_数组元素_33

冒泡排序.gif

Java基础之数组_i++_34

桶排序.png

Java基础之数组_java_35

希尔排序.gif

Java基础之数组_i++_36

算法的5大特征

特征 说明
输入(Input) 有0个或多个输入数据,这些输入必须有清楚的描述和定义
输出(Output) 至少有1个或多个输出结果,不可以没有输出结果
有穷性(有限性,Finiteness) 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤 可以在可接受的时间内完成
确定性(明确性,Definiteness) 算法中的每一步都有确定的含义,不会出现二义性
可行性(有效性,Effectiveness) 算法的每一步都是清楚且可行的,能让用户用纸笔计算而求出答案

说明:满足确定性的算法也称为:确定性算法。现在人们也关注更广泛的概念,例如 考虑各种非确定性的算法,如并行算法、概率算法等。另外,人们也关注并不要求终 止的计算描述,这种描述有时被称为过程(procedure)。

冒泡排序

  • 介绍:
    冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元 素,如果他们的顺序错误就把他们交换过来。

  • 排序思想:

    • 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
    • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步 做完后,最后的元素会是最大的数。
    • 针对所有的元素重复以上的步骤,除了最后一个。
    • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要 比较为止。
 1 package com.ak.java;
 2 /*
 3  * 数组的冒泡排序的实现
 4  * 
 5  */
 6 public class BubbleSortTest {
 7     public static void main(String[] args) {
 8         
 9         int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};
10         
11         //冒泡排序
12         for(int i = 0;i < arr.length - 1;i++){
13             
14             for(int j = 0;j < arr.length - 1 - i;j++){
15                 
16                 if(arr[j] > arr[j + 1]){
17                     int temp = arr[j];
18                     arr[j] = arr[j + 1];
19                     arr[j + 1] = temp;
20                 }
21                 
22             }
23             
24         }
25         
26         
27         
28         
29         for(int i = 0;i < arr.length;i++){
30             System.out.print(arr[i] + "\t");
31         }
32         
33     }
34 }

 

Java基础之数组_java_37

快速排序

  • 介绍:

    • 快速排序通常明显比同为O(nlogn)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。可 见掌握快排的重要性。

    • 快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升 级版,交换排序的一种。快速排序的时间复杂度为O(nlog(n))。

  • 排序思想:

    • 从数列中挑出一个元素,称为"基准"(pivot),
    • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准 值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后, 该基准就处于数列的中间位置。这个称为分区(partition)操作。
    • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数 列排序。
    • 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

Java基础之数组_i++_38

Java基础之数组_一维数组_39

 1 package com.ak.java;
 2 
 3 /**
 4  * 快速排序
 5  * 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,
 6  * 则分别对这两部分继续进行排序,直到整个序列有序。
 7  */
 8 public class QuickSort {
 9     private static void swap(int[] data, int i, int j) {
10         int temp = data[i];
11         data[i] = data[j];
12         data[j] = temp;
13     }
14 
15     private static void subSort(int[] data, int start, int end) {
16         if (start < end) {
17             int base = data[start];
18             int low = start;
19             int high = end + 1;
20             while (true) {
21                 while (low < end && data[++low] - base <= 0)
22                     ;
23                 while (high > start && data[--high] - base >= 0)
24                     ;
25                 if (low < high) {
26                     swap(data, low, high);
27                 } else {
28                     break;
29                 }
30             }
31             swap(data, start, high);
32             
33             subSort(data, start, high - 1);//递归调用
34             subSort(data, high + 1, end);
35         }
36     }
37     public static void quickSort(int[] data){
38         subSort(data,0,data.length-1);
39     }
40     
41     
42     public static void main(String[] args) {
43         int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
44         System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
45         quickSort(data);
46         System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
47     }
48 }

 

Java基础之数组_i++_40

排序算法性能对比

Java基础之数组_数组_41

各种内部排序方法性能比较

  • 从平均时间而言快速排序最佳。但在最坏情况下时间性能不如堆排序和归 并排序。
  • 从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于Shell排序、堆排序、快速排序和归并排序 算法,其算法比较复杂,认为是复杂排序。
  • 从稳定性看:直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排 序、快速排序、 Shell排序和堆排序是不稳定排序
  • 从待排序的记录数n的大小看,n较小时,宜采用简单排序;而n较大时宜采 用改进排序。

排序算法的选择

  • 若n较小(如n≤50),可采用直接插入直接选择排序
  • 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直 接插入,应选直接选择排序为宜。
  • 若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;
  • 若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序归并排序

Arrays工具类的使用

  • java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比 如排序和搜索)的各种方法。

    方法 说明
    boolean equals(int[] a,int[] b) 判断两个数组是否相等。
    tring toString(int[] a) 输出数组信息。
    oid fill(int[] a,int val) 将指定值填充到数组之中。
    oid sort(int[] a) 对数组进行排序。
    int binarySearch(int[] a,int key) 对排序后的数组进行二分法检索指定的值。
  • java.util.Arrays类的sort()方法提供了数组元素排序功能:

     1 import java.util.Arrays;  
     2 
     3 public class SortTest {
     4     public static void main(String[] args) {
     5         int [] numbers = {5,900,1,5,77,30,64,700};
     6         Arrays.sort(numbers);
     7         for(int i = 0; i < numbers.length; i++){          
     8                 System.out.println(numbers[i]);
     9         }
    10     }
    11 }

     

 1 package com.ak.java;
 2 
 3 import java.util.Arrays;
 4 
 5 /*
 6  * java.util.Arrays:操作数组的工具类,里面定义了很多操作数组的方法
 7  * 
 8  * 
 9  */
10 public class AraysDemo {
11     public static void main(String[] args) {
12         
13         //1.boolean equals(int[] a,int[] b):判断两个数组是否相等。
14         int[] arr1 = new int[]{1,2,3,4};
15         int[] arr2 = new int[]{1,3,2,4};
16         boolean isEquals = Arrays.equals(arr1, arr2);
17         System.out.println(isEquals);
18         
19         //2.String toString(int[] a):输出数组信息。
20         System.out.println(Arrays.toString(arr1));
21         
22             
23         //3.void fill(int[] a,int val):将指定值填充到数组之中。
24         Arrays.fill(arr1,10);
25         System.out.println(Arrays.toString(arr1));
26         
27 
28         //4.void sort(int[] a):对数组进行排序。
29         Arrays.sort(arr2);
30         System.out.println(Arrays.toString(arr2));
31         
32         //5.int binarySearch(int[] a,int key)
33         int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
34         int index = Arrays.binarySearch(arr3, 210);
35         if(index >= 0){
36             System.out.println(index);
37         }else{
38             System.out.println("未找到");
39         }
40         
41         
42     }
43 }

 

Java基础之数组_数组_42

数组使用中的常见异常

  • 数组脚标越界异常(ArrayIndexOutOfBoundsException)

    int[] arr = new int[2];
    System.out.println(arr[2]);
    System.out.println(arr[-1]);
    访问到了数组中的不存在的脚标时发生。

  • 空指针异常(NullPointerException)

    int[] arr = null;
    System.out.println(arr[0]);
    arr引用没有指向实体,却在操作实体中的元素时。

 1 package com.ak.java;
 2 /*
 3  * 数组中的常见异常:
 4  * 1. 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
 5  * 
 6  * 2. 空指针异常:NullPointerException
 7  * 
 8  */
 9 public class ArrayExceptionTest {
10     public static void main(String[] args) {
11         
12         //1. 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
13         int[] arr = new int[]{1,2,3,4,5};
14         
15 //        for(int i = 0;i <= arr.length;i++){
16 //            System.out.println(arr[i]);
17 //        }
18         
19 //        System.out.println(arr[-2]);
20         
21 //        System.out.println("hello");
22         
23         //2.2. 空指针异常:NullPointerException
24         //情况一:
25 //        int[] arr1 = new int[]{1,2,3};
26 //        arr1 = null;
27 //        System.out.println(arr1[0]);
28         
29         //情况二:
30 //        int[][] arr2 = new int[4][];
31 //        System.out.println(arr2[0][0]);
32         
33         //情况三:
34         String[] arr3 = new String[]{"AA","BB","CC"};
35         arr3[0] = null;
36         System.out.println(arr3[0].toString());
37     }
38 }

 

Java基础之数组_java_43

Java基础之数组_一维数组_44