一、数组元素的赋值
练习题1:
杨辉三角,是二项式系数在三角形中的一种几何排列。在欧洲,这个表叫做帕斯卡三角形。帕斯卡是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年。杨辉三角是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合 。
使用二维数组打印一个 10 行杨辉三角。
【提示】
1. 第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
public class YangHuiTest {
public static void main(String[] args) {
// 1、声明并初始化二维数组
int[][] yangHui = new int[10][];
// 2、给数组的元素赋值
for(int i = 0;i < yangHui.length;i++){
yangHui[i] = new int[i + 1];
// 给首末元素赋值
yangHui[i][0] = yangHui[i][i] = 1;
// 给每行的非首末元素赋值
if(i > 1){
for(int j = 1;j < yangHui[i].length - 1;j++){
yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
}
}
}
// 3、遍历二维数组
for(int i = 0;i < yangHui.length;i++){
for(int j = 0;j < yangHui[i].length;j++){
System.out.print(yangHui[i][j] + " ");
}
System.out.println();
}
}
}
练习题2:
创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同
public class ArrayRandom {
public static void main(String[] args) {
int[] arr = new int[6];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 30) + 1;
for (int j = 0; j < i; j++) {
if (arr[i] == arr[j]) {
i--;
break;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
二、数组元素的最大/最小值、平均数、总和
定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。
要求:所有随机数都是两位数。
import java.util.Scanner;
public class ArrayOperation {
public static void main(String[] args) {
int[] arr = new int[10];
// 随机10 - 99的整数
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * (100 - 10) + 10);
}
// 遍历
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println();
// 求数组元素的最大值
int maxValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (maxValue < arr[i]) {
maxValue = arr[i];
}
}
System.out.println("最大值为:" + maxValue);
// 求数组元素的最小值
int minValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (minValue > arr[i]) {
minValue = arr[i];
}
}
System.out.println("最小值为:" + minValue);
// 求数组元素的总和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println("总和为:" + sum);
// 求数组元素的平均数
int avgValue = sum / arr.length;
System.out.println("平均数为:" + avgValue);
}
}
三、数组复制
使用简单数组
(1)创建一个名为ArrayCopy的类,在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是什么关系?
public class ArrayCopy {
public static void main(String[] args) { //alt + /
int[] array1, array2;
array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};
//显示array1的内容
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
//赋值array2变量等于array1
//不能称作数组的复制。
array2 = array1;
//修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
for (int i = 0; i < array2.length; i++) {
if (i % 2 == 0) {
array2[i] = i;
}
}
System.out.println();
//打印出array1
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
// array1和array2是什么关系?array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体。
}
}
解析:
拓展:修改题目,实现array2对array1数组的复制
public class ArrayCopy {
public static void main(String[] args) { //alt + /
int[] array1, array2;
array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};
//显示array1的内容
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
//数组的复制:
array2 = new int[array1.length];
for (int i = 0; i < array2.length; i++) {
array2[i] = array1[i];
}
//修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
for (int i = 0; i < array2.length; i++) {
if (i % 2 == 0) {
array2[i] = i;
}
}
System.out.println();
//打印出array1
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
}
}
四、数组反转
把如下数组进行反转:
String arr[] = new String[]{"AA","BB","CC","DD","EE","FF","GG"};
public class ArrayReverse01 {
public static void main(String[] args) {
String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};
for (int i = 0; i < arr.length / 2; i++) {
String temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
//遍历
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
public class ArrayReverse02 {
public static void main(String[] args) {
String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//遍历
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
五、数组查找
5.1 线性查找
线性查找又叫顺序查找,就是遍历整个列表,逐个元素与给定值比较,若某个元素和给定值相等,则查找成功。如果直到最后一个元素和给定值比较都不相等,则查找失败。
public class ArraySequentialSearch {
public static void main(String[] args) {
String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};
String findStr = "BB";
findStr = "QQ";
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
if(findStr.equals(arr[i])){
System.out.println("找到了指定的元素,位置为:" + i);
isFlag = false;
break;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到你要查询的元素!");
}
}
}
5.2 二分查找
什么是二分查找呢?二分查找的基本思想是:在有序表中,取中间元素作为比较对象,若给定值与中间元素相等,则查找成功;若给定值小于中间元素,则在中间元素的左半区继续查找;若给定值大于中间元素,则在中间元素的右半区继续查找。不断重复上述过程,直到找到为止。
从二分查找的定义我们可以看出,使用二分查找有两个前提条件:
(1)待查找的列表必须有序。
(2)必须使用线性表的顺序存储结构来存储数据。
接下来我们来介绍一下折半查找的原理,并自己用代码实现折半查找。
在查找前对数组进行折半操作 (初始化指针位置)
折半公式 = (最大索引+最小索引)/ 2
首先我们可以利用指针思想,假设有一个指针指向最大值(MAX),有一个指针指向最小值(MIN),还有一个指针指向的是最大值和最小值之间的索引(MID)。我把这个过程称为初始化指针位置.
折半后的指针索引和被查找元素比较
若被查找元素的值(12)大于中间索引上的值(10),我们就把最小值指针(MIN)移动到中间指针(MID)索引的下一个索引位置,如下图:
若没有匹配到就继续折半后的指针索引和被查找元素比较。
若被查找元素的值(12)小于中间索引上的值(15),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:
若没有匹配到就继续折半后的指针索引和被查找元素比较
若被查找元素的值(12)小于中间索引上的值(13),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:
若没有匹配到就继续折半后的指针索引和被查找元素比较。
当小指针(MIN)的索引(4)超过了大指针(MAX)的索引(3)时,就需要停止查找了,如果真有这种情况发生,说明没有查到被查找元素的值(12),此时会返回一个负数(-1),当然如果查找到了就返回其在数组中的索引即可。
数组的折半查找代码实现
public class ArrayBinarySearch {
public static void main(String[] args) {
int[] arr = new int[]{1, 4, 7, 10, 13, 15, 21, 25};
int findNum = 21;
// 初始的最小索引
int min = 0;
// 初始的末索引
int max = arr.length - 1;
boolean isFlag = true;
while (min <= max) {
int mid = (min + max) / 2;
if (findNum == arr[mid]) {
System.out.println("找到了指定的元素,位置为:" + mid);
isFlag = false;
break;
} else if (arr[mid] > findNum) {
max = mid - 1;
} else {//arr[middle] < findNum
min = mid + 1;
}
}
if (isFlag) {
System.out.println("很遗憾,没有找到你要查询的元素!");
}
}
}
六、数组排序
6.1 冒泡排序
冒泡概述
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
实现原理
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
实现思路
(1)第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。
(2)比较第2和第3个数,将小数 放在前面,大数放在后面。
......
(3)如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成
(4)在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。
(5)在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。
(6)依次类推,每一趟比较次数减少依次
实例解析
排序数组:[10,1,35,61,89,36,55]
冒泡代码
/*
* 使用冒泡排序实现升序排列
* 冒泡排序(升序)的原理:
* 两两比较,如果前面的值比后面的值大,则交换位置
* 外层i 0 1 2 3 4
* 原数组 第一轮 第二轮 第三轮 第四轮 第五轮 外层循环5次 arr.length-1 6 - 1
* 98 78 56 44 23 6
* 78 56 44 23 6 23
* 56 44 23 6 44 44
* 44 23 6 56 56 56
* 23 6 78 78 78 78
* 6 98 98 98 98 98
*
* 次数 5 4 3 2 1
* 内层 arr.length-1-i
* 第一轮得到一个最大值,这个最大值
* 1.外层循环初始变量i为0,判断依据 i < arr.length - 1
* 2.内存循环初始边框j为0,判断依据 j < arr.length - i - 1
* 3.判断谁大或谁小,然后交换位置
*/
int arr[] = {32,5,100,9,78,1};
for(int i = 0;i < arr.length - 1;i++) { //用来决定轮数 5
for(int j = 0; j < arr.length - i -1;j++) { //用来决定每轮比较的次数
if(arr[j] > arr[j+1]) {
//temp保存哪个值无所谓,但是保存哪个值,就要先给哪个值赋值
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("冒泡升序排列之后:"+Arrays.toString(arr));
6.2 选择排序
选择排序(Selection sort)是一种简单直观的排序算法。
它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
实例解析
第1趟比较:拿第1个元素依次和它后面的每个元素进行比较,如果第1个元素大于后面某个元素,交换它们,经过第1趟比较,数组中最小的元素被选出,它被排在第一位
第2趟比较:拿第2个元素依次和它后面的每个元素进行比较,如果第2个元素大于后面某个元素,交换它们,经过第2趟比较,数组中第2小的元素被选出,它被排在第二位
......
第n-1趟比较:第n-1个元素和第n个元素作比较,如果第n-1个元素大于第n个元素,交换它们.
选择代码
/*
* 选择排序 - 升序排列:
* 使用指定位置的值,跟所有的值进行比较;如果前面的值大于后面的值,则交换位置
*
* 外层循环变量 0 1 2 3
* 原数组 第一轮 第二轮 第三轮 第四轮 比较了四次,外层循环 arr.length - 1
* 120 10 10 10 10
* 89 120 18 18 18
* 32 89 120 32 32
* 18 32 89 120 89
* 10 18 32 89 120
*
* 次数 4 3 2 1 看似: arr.length - i - 1
*
* 1. 外层循环初始变量i为0,小于arr.length - 1
* 2. 内层循环初始变量j为i,小于arr.length - 1
* j = 0 < 4
* j = 1 < 4
* j = 2 < 4
*/
int arr[] = {32,2,78,6,44,100};
for(int i = 0;i < arr.length - 1;i++) {
for(int j = i; j < arr.length - 1;j++) {
/*
* i = 0 arr[i] = 2
* j = 0 32 2 --> 2 arr[j+1] = 32
*/
if(arr[i] > arr[j+1]) {
int temp = arr[j+1];
arr[j+1] = arr[i];
arr[i] = temp;
}
}
}
System.out.println("选择排序之后的数组:"+Arrays.toString(arr));