数组的使用:
数据一多,就要想到使用数组.
如果数据出现对应关系,而且对应关系的一方是有序的数字编号,并可以做为角标来使用,这是就要想到使用数组.
查表法:可以将这些数据存储到数组中,根据运算的结果做为角标之直接去查数组中对应的元素.
数组的静态定义方法: int[] arr = {3,45,12,6,88,34};
数组的操作:分为基本操作和一些常见的功能性操作.基本操作动作就是存和取(对角标的操作).常见的功能性操作如下.
1.数组的遍历(使用循环结构),可以正向遍历,也可以反向遍历.其中常用到数组的一个属性length来获取数组的长度.
/*
演示数组的遍历操作
思路:使用循环结构,通过对数组角标的操作逐个取出数组中每一个元素进行打印.
*/
class ArrDemo
{
public static void main(String[] args)
{
int[] arr = new int[]{2,34,53,24,16,78,23,56,2};
arrErgodic(arr);
}
/*定义一个功能函数,用来遍历int数组,并将数组的每个元素打印到控制台
1.返回值类型:直接打印,无返回值 void
2.参数列表:需要参与遍历运算的数组,由用户提供. int[]
*/
public static void arrErgodic(int[] arr)
{
for (int x=0;x<arr.length ;x++ )//使用数组的length属性.数组角标最大为length-1,所以此处是小于而不能是小于等于
{
System.out.println("arr["+x+"] = "+arr[x]+";");
}
}
}2.获取最值(最大值,最小值).思路就是元素之间的比较,使用循环来对数组中的元素进行比较,同时通过来定义一个变量来记录比较的结果,从而得出最值.
需要注意的是,进行记录用的变量初始化为数组中的元素内容或角标都可以,因为元素中数据和角标是有着对应关系的.但是不要初始化为例如0之类的习惯性初始值,数组外的数据对于元素比较而言没有参考价值.
/*
演示获取一个数组的最大值
*/
class ArrGetMax
{
public static void main(String[] args)
{
int[] arr = new int[]{2,34,53,24,16,78,23,56,2};
{
int max = getMax(arr);
System.out.println("max = "+max);
}
System.out.println("-------------------------华丽丽的分割线-------------------------------");
{
int max = getMax_2(arr);
System.out.println("max = "+max);
}
}
/*
定义一个功能函数,用于获取int数组的最大值
1.返回值类型:获取到的最大值 int
2.参数列表:参与运算的数组 int[]
思路1:定义一个变量记录比较后较大的元素的值,初始化为0角标元素的值
*/
public static int getMax(int[] arr)
{
int max=arr[0];
for (int x=1;x<arr.length;x++ )//0角标已被记录不需要参与比较,因此从1角标开始
{
if(arr[x]>max)
max = arr[x];
}
return max;
}
/*
定义一个功能函数,用于获取int数组的最大值
1.返回值类型:获取到的最大值 int
2.参数列表:参与运算的数组 int[]
思路2:定义一个变量记录比较后较大的元素的角标,初始化为0角标.
*/
public static int getMax_2(int[] arr)
{
int index=0;
for (int x=1;x<arr.length;x++ )
{
if(arr[x]>arr[index])
index = x;
}
return arr[index];
}
}
3.数组的排序:
(1)选择排序
思路: 1.排序的过程是大圈套小圈的过程,使用for循环的嵌套.
2.位置交换(考虑效率问题,使用变量来记录要交换的数值每轮最后只进行一次交互,效率较高)
3.排序的函数完成后无需提供返回值,因为数组是引用类型指向,排序前后操作的是同一个数组.

常规选择排序

使用变量提高选择排序的效率
/*
演示选择排序
*/
class SelectSortDemo
{
public static void main(String[] args)
{
{
int[] arr = new int[]{2,34,53,24,15,16,78,15,23,56,2};
selectSort(arr);
arrErgodic(arr);
}
System.out.println("--------------华丽丽的分割线-------------------");
{
int[] arr = new int[]{2,34,53,24,15,16,78,15,23,56,2};
selectSort_2(arr);
arrErgodic(arr);
}
}
//定义一个功能函数来遍历数组并打印到控制台
public static void arrErgodic(int[] arr)
{
for (int x=0;x<arr.length;x++ )
{
System.out.println("arr["+x+"]\t= "+arr[x]+";");
}
return;
}
/*
定义一个功能函数用来对int数组进行选择排序
1.返回值类型 void
2.参数列表:参与排序的数组 int[]
*/
public static void selectSort(int[] arr)
{
for (int x=0;x<arr.length-1;x++)//从0角标元素开始选择排序,当选择到最后一个元素时,它并不需要自己跟自己比较,所以-1.
{
for (int y=x+1;y<arr.length;y++)//取出当前参照元素的下一个元素进行比较,直到最后一个元素.
{
if(arr[x] > arr[y])
{
changeNum(arr,x,y);
}
}
}
return;//无返回值,可以省略
}
/*
定义一个功能函数用来对int数组进行选择排序,采用第三方变量记录比较后的结果值,以减少交换次数
1.返回值类型 void
2.参数列表:参与排序的数组 int[]
*/
public static void selectSort_2(int[] arr)
{
for (int x=0;x<arr.length-1;x++)
{
//定义两个变量来记录每次比较后比较小的值,初始化为第一个元素
int num = arr[x];//生命周期在外循环结束后释放,下一次循环重新加载.
int index = x;//我考虑把这两个变量声明到外循环之外,虽然生命周期会变长,但是不用再内存中每次循环开始后都重新声明,是不是效率会更好?
for (int y=x+1;y<arr.length;y++ )
{
if(num>arr[y])
{
num = arr[y];//记录较小元素的值
index = y;//记录较小元素的角标
}
/*
千万注意,刚才不小心写成了:
if(num>arr[y])
num = arr[y];
index = y;
这是错误的,if如果不加{}只是控制其之后的第一条语句,结果使得index=y失去了判断语句的控制,始终执行.语法没有错误,但是运行结果错误
*/
}
//如果当前元素就是当前循环比较中最小的值则不需要交换,不同才交换.只在内循环完成后最多交换一次.效率较高
if(x!=index)
changeNum(arr,x,index);
}
return;
}
/*
定义一个功能函数将数组两元素交换位置的功能提取出来单独封装方便调用.
1.返回值类型void,对数组操作,前后指向的都是同一个数组,无需返回值.
2.参数列表:需要进行元素交换的数组 int[].需要交换的两个元素的角标 int.
*/
public static void changeNum(int[] arr, int x, int y)
{
//位置交换 位运算法
arr[x]=arr[x]^arr[y];
arr[y]=arr[x]^arr[y];
arr[x]=arr[x]^arr[y];
/*位置交换 第三方变量法(常规用法)
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
*/
return;
}
}
(2)冒泡排序

冒泡排序示意图
/*
演示冒泡排序
*/
class BubbleSortDemo
{
public static void main(String[] args)
{
{
int[] arr = new int[]{2,34,53,24,15,16,78,15,23,56,2};
bubbleSort(arr);
arrErgodic(arr);
}
System.out.println("--------------华丽丽的分割线-------------------");
{
int[] arr = new int[]{2,34,53,24,15,16,78,15,23,56,2};
bubbleSort_2(arr);
arrErgodic(arr);
}
}
/*
定义一个功能函数,用于对int数组进行冒泡排序
1.返回值类型 Void 排序前后指向同一个数组,无返回值.
2.参数列表: 参与排序的数组 int[]
*/
public static void bubbleSort(int[] arr)
{
for (int x=0;x<arr.length-1;x++)//不必取到最后一次拿自己跟自己比较所以-1
{
for (int y=0;y<arr.length-1-x ;y++ )//-1是为了防止越界,-x是为了随着外循环次数的增加,内循环参与比较的元素递减.
{
if(arr[y]>arr[y+1])//注意不要引起越界
{
arr[y]=arr[y]^arr[y+1];
arr[y+1]=arr[y]^arr[y+1];
arr[y]=arr[y]^arr[y+1];
}
}
}
}
//冒泡排序另一种写法,功能和原理相同
public static void bubbleSort_2(int[] arr)
{
for (int x=arr.length-1;x>0;x--)//倒着取,同样不许要取到第一个,外循环只是用来控制整体循环次数.
{
for (int y=0;y<x ;y++ )//x本身已经是arr.length-1了,而且x在不断递减,因此效果跟上变函数一样,只是写法不同
{
if(arr[y]>arr[y+1])
{
arr[y]=arr[y]^arr[y+1];
arr[y+1]=arr[y]^arr[y+1];
arr[y]=arr[y]^arr[y+1];
}
}
}
}
//定义一个功能函数来遍历数组并打印到控制台
public static void arrErgodic(int[] arr)
{
for (int x=0;x<arr.length;x++ )
{
System.out.println("arr["+x+"]\t= "+arr[x]+";");
}
return;
}
}
4.数组的元素查找
(1)基本遍历查找,效率低
(2)折半查找法(二分查找)
前提:数组有序,数组本身的元素就要有序,如果通过排序将其变成有序,那么原始数组中元素与角标的对应关系就被破坏.
思想:通过定义变量来记录查找时变化的min(头角标),mid(中间角标),max(尾角标),直至mid指向所找到的指定元素或max<min发生越界,说明数组中不存在指定要求查找的元素.
/*
二分查找演示
*/
class BinarySearchDemo
{
public static void main(String[] args)
{
int[] arr = new int[]{2,15,21,34,56,67,88,91,109};
int pot = binarySearch(arr,1);
System.out.println("pot = "+pot);
System.out.println("------------------华丽丽的分隔线-----------------------");
int pot2 = binarySearch_2(arr,110);
System.out.println("pot2 = "+pot2);
}
/*
定义一个函数,用二分查找法来查找有序数组用户指定要查找的元素的角标
1.返回值类型,查到的元素的角标 int
2.参数列表 参与运算的数组 int[] , 要查的元素值 int
*/
public static int binarySearch(int[] arr, int num)
{
//定义三个标量来记录二分查找时的头角标,中间角标,尾角标
int min = 0;
int max = arr.length-1;
int mid = (min + max)>>1;//>>1相当于除2,位运算高效.
while(arr[mid] != num)
{
if(num > arr[mid])
{
min = mid+1;
}
else
{
max = mid-1;
}
if(max<min)
{
return -min-1;//如果概数不在数组中,提供其插入点
}
else
{
mid = (min+max)>>1;
}
}
return mid;
}
//另一种写法
public static int binarySearch_2(int[] arr, int num)
{
int min,mid,max;
min = 0;
max = arr.length-1;
while(max>=min)
{
mid = (min+max)>>1;
if(num>arr[mid])
{
min = mid+1;
}
else if(num<arr[mid])
{
max = mid-1;
}
else
{
return mid;
}
}
return -min-1;//如果概数不在数组中,提供其插入点
}
}
查表法:
/*
查表法的演示
*/
class ArrayTest
{
public static void main(String[] args)
{
getHex(60);
getOctal(60);
getBinary(60);
getHex(0);
getOctal(0);
getBinary(0);
}
/*
定义一个函数,通过查表法,对一个十进制数打印出其其他进制.
1.返回值类型 void 直接打印到控制台
2.指定的十进制数 int 二进制截取各进制一位的基数 int 按进制不同转换时二进制下移动的偏移量
*/
public static void trans(int num, int base, int offset)
{
if(num == 0)
{
System.out.print("0");
System.out.println();//这一行是为了打印结束换行,为了格式美观,其实可以和上一行合并,把上一行写成println.
return;//这里如果不写return,一旦条件满足不返回,后边的内容还是会执行,写上就不会执行了.
}
//建立一个十进制与十六进制的对应关系表,使用数组
char[] table = new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//建立一个十进制与其他进制的对应关系表,使用数组
char[] arr = new char[32];
//建立一个数组用来存放转换后进制的每一位
int x = arr.length;
while (num != 0)
{
int temp = num & base;
//System.out.println(table[temp]);
arr[--x] = table[temp];//先--再赋值
num = num>>>offset;
}
for (int y=x;y<arr.length ;y++)//因为前边有可能会有很多空字符元素,所以不从0开始遍历,从有效位x开始.
{
//if(arr[y] != '\u0000')
System.out.print(arr[y]);
}
System.out.println();
return;
}
//转换成十六进制打印出
public static void getHex(int num)
{
System.out.print("0x");
trans(num,15,4);
}
//转换成八进制打印出
public static void getOctal(int num)
{
System.out.print("0");
trans(num,7,3);
}
//转换成二进制打印出
public static void getBinary(int num)
{
trans(num,1,1);
}
}
二维数组:
定义方法:例如 int[][] arr = new int[3][2]; int[][] arr = new int[3][]; int[][] arr = {{2,4,3},{1,5,6,0},{3,1}};
二维数组的内存加载方式:

/*
二维数组的演示
*/
class Array2Demo
{
public static void main(String[] args)
{
int[][] arr = new int[4][3];//创建一个二维数组,该数组中有4个一维数组,每个一维数组中有3个元素.
System.out.println(arr);//直接打印二维数组,得到二维数组的标识和哈希值:[[I@de6ced
System.out.println(arr[2]);//打印二维数组中角标为2的一维数组.得到指定一维数组的标识和哈希值:[I@c17164
System.out.println(arr[3][2]);//打印二维数组中角标为3的一维数组中角标为2的元素.得到默认初始值:0
int[][] arr2 = new int[4][];//创建一个二维数组,该数组只指定了其中一维数组的长度,并未指定每个一维数组的具体元素个数.
//每个一维数组的长度不一定,可以分别初始化每个小数组.
System.out.println(arr2);//直接打印二维数组,得到二维数组的标识和哈希值:[[I@1fb8ee3
System.out.println(arr2[2]);//打印二维数组中角标为2的一维数组.该一维数组尚未指向任何元素,默认初始值为null
//System.out.println(arr2[3][0]);//打印二维数组中角标为3的一维数组中角标为0的元素.报空引用异常的错误,该一维数组尚未对元素进行初始化创建不能用指针进行操作.
//练习一个二维数组的遍历
int[][] arr3 = {{12,34,15,67},{2,7,90,33},{45,17,102,110},{77,90,22,55,87,120}};
for (int x=0;x<arr3.length;x++ )
{
for (int y=0;y<arr3[x].length;y++ )
{
System.out.print(arr3[x][y]+" , ");
}
}
}
}
本文深入探讨数组的使用场景及基本操作,包括数组的静态定义、遍历、获取最大值、排序方法(选择排序与冒泡排序)及查找算法(基本遍历查找与折半查找)。同时,介绍查表法在不同进制转换的应用,并展示二维数组的定义与内存加载方式。文章旨在全面理解数组及其相关算法的实用技巧。
5194

被折叠的 条评论
为什么被折叠?



