------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
2. 数组的常见操作
对数组操作最基本的动作就是存和取,核心思想就是对角标的操作。
2.1 遍历打印数组:
/**
* 需求:遍历打印数组
* @author jinlong
* */
package com.blog.part1.数组;
public class ArrayPrintDemo
{
public static void main(String[] args)
{
int[] arr = {1,3,5,7,9};
for(int x = 0; x < arr.length; x += 1){
System.out.println("arr[" + x + "] = " + arr[x] + ";");
}
}
}
2.2 获取最值(最大值,最小值)
2.2.1 定义变量记录值
/**
* 需求:获取一个数组的最大值
* 思路:1、需要进行比较,并定义变量记录住每次比较后较大的值。
2、对数组中的元素进行遍历取出,和变量中记录的元素进行比较。如果遍历到的元素大于变量中记录的元素,就用变量该记录住大的值。
3、遍历结果,该变量记录就是最大值。
* @author jinlong
* */
package com.blog.part1.数组;
public class ArrayMaxDemo
{
public static void main(String[] args)
{
int[] arr= {2,4,6,10,8,11};
//调用获取最大值方法
int max = getMax(arr);
System.out.println("max = " + max);
}
//将获取最大值单独写成一个方法,传入参数为数组,返回最大值
public static int getMax(int[] arr)
{
//定义一个int类型变量,来存储最大值,初始值为arr第一个元素的值
int maxEle= arr[0];
for(int x = 1; x < arr.length; x++)
{
//遍历数组,将每个元素与maxEle中值进行比较,如果大于maxEle,那么把它存入maxEle
if(arr[x] > maxEle)
maxEle = arr[x];
}
return maxEle;
}
}
运行结果为:max=11;
2.2.2 定义变量记角标
* @author jinlong
* */
package com.blog.part1.数组;
public class ArrayMaxDemo
{
public static void main(String[] args)
{
int[] arr= {2,4,6,10,8,11};
//调用获取最大值方法
int max =getMax(arr);
System.out.println("max = " + max);
}
//将获取最大值单独写成一个方法,传入参数为数组,返回最大值
public static int getMax(int[] arr)
{
//定义一个int类型变量,来存储最大值的角标,初始值为0.
int maxIndex= 0;
for(int x = 1; x < arr.length; x++)
{
//遍历数组,将每个元素与角标为maxIndex的元素进行比较,如果大于这个值,那么把它的元素角标存入maxIndex
if(arr[x] > arr[maxIndex])
maxIndex = x;
}
//最后返回maxIndex角标所对应的元素即可
return arr[maxIndex];
}
}
2.3 排序
2.3.1 选择排序
/**
* 需求:选择排序
* 思路: 1、首先拿数组第一个元素依次与除其自身外的其他每个元素顺序比较,如果第一个元素大于剩下的某个元素,就互换内容。
2、经过第一轮比较之后,此时,第一个元素就是数组中最小的元素。然后再拿第二个元素与除第一个元素和其自身的元素进行比较,如果第二个元素大于剩下的某个元素,就互换内容。此时,第二个元素就是数组中倒数第二小的元素。
3、依次类推,直到最后一个元素。我们想到for嵌套。
* @author jinlong
* */
package com.blog.part1.数组;
public class ArraySortDemo
{
public static void main(String[] args)
{
int[] arr= {3,7,5,1,9,11};
System.out.print("排序前数组:" );
printArray(arr);
selectSort(arr);
System.out.print("排序后数组:" );
printArray(arr);
}
//定义selectSort方法进行选择排序
public static void selectSort(int[] arr)
{
//for嵌套结构,外层为除最后一个所有元素
for(int x = 0; x < arr.length - 1; x++)
{
//第一层for获取的元素与其他元素比较
for(int y = x + 1; y < arr.length; y++)
{
if(arr[x] > arr[y])
{
//定义临时变量temp来存储中间值,实现两个值互换
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
//遍历打印数组功能函数
public static void printArray(int[] arr)
{
System.out.print("[" );
for(int x = 0; x < arr.length; x++)
{
//为了控制数组打印的格式,进行判断
if(x != arr.length - 1)
System.out.print(arr[x] + "," );
else
System.out.println(arr[x] + "]" );
}
}
}
注意:selectSort方法之所以返回值为void,是因为:arr引用变量是对传入selectSort方法中作为参数的数组的引用, selectSort方法执行完毕之后,我们依然可以通过arr引用变量操作传入的数组。所以,没有必要再通过返回值获取。
/**
* 需求:选择排序
* 思路: 上面的选择排序算法效率比较低,因为数组每一个元素与剩下的元素比较就是为了获得最小的元素并且与之互换。
* 如果是这样,那么更高效率的方式则是只需要通过两个变量,一个记录最小值,一个记录最小值所在的角标即可。
* 等当前元素与余下的所有元素比较完,直接互换,这样只需互换一次就能达到目标,效率自然就会提高。
* @author jinlong
* */
package com.blog.part1.数组;
public class ArraySortDemo
{
public static void main(String[] args)
{
int[] arr= {3,7,5,1,9,11};
System.out.print("排序前数组:" );
printArray(arr);
selectSort(arr);
System.out.print("排序后数组:" );
printArray(arr);
}
//定义selectSort方法进行选择排序
public static void selectSort(int[] arr)
{
//for嵌套结构,外层为除最后一个所有元素
for(int x = 0; x < arr.length - 1; x++)
{
//定义变量来记录最小值的角标
int index=x;
//定义变量来记录数值
int num=arr[x];
//第一层for获取的元素与其他元素比较
for(int y = x + 1; y < arr.length; y++)
{
if(num > arr[y])
{
//如果num比arr【y】大的时候
//最小值是arr【y】最小值角标为y
num = arr[y];
index = y;
}
}
//经过一轮循环后判断最小值角标index和最小值num的角标是不是同一个,如果不是,那就交换
if(index!=x)
{
int temp=arr[index];
arr[index]=arr[x];
arr[x]=temp;
}
}
}
//遍历打印数组功能函数
public static void printArray(int[] arr)
{
System.out.print("[" );
for(int x = 0; x < arr.length; x++)
{
//为了控制数组打印的格式,进行判断
if(x != arr.length - 1)
System.out.print(arr[x] + "," );
else
System.out.println(arr[x] + "]" );
}
}
}
运行结果:
2.3.2 冒泡排序
/**
* 需求:演示冒泡排序
* 思路: 1、首先在第一轮排序中,数组从第一个元素到倒数第二个元素依次与其右边的元素进行比较,如果左边的元素大于右边的元素,那么两个元素就互换。
2、经过第一轮比较,最大的元素就已经存储到数组最右边的结点中了。
3、第二轮排序则是从第一个元素到倒数第三个元素依次与其右边的元素进行比较,如果左边的元素大于右边的元素,那么两个元素就互换。
4、依照此方式,一直到只有第一和第二个元素互相比较而结束。
* @author jinlong
* */
package com.blog.part1.数组;
public class ArraySortDemo1
{
public static void main(String[] args)
{
int[] arr= {20,30,10,50,40};
System.out.print("排序前数组:" );
printArray(arr);
bubbleSort(arr);
System.out.print("排序后数组:" );
printArray(arr);
}
//冒泡排序方法
public static void bubbleSort(int[] arr)
{
//同样是嵌套for循环
for(int x = 0; x < arr.length - 1; x++)
{
for(int y = 0; y < arr.length - 1 -x; y++)
{
if(arr[y] > arr[y+1])
{
//交换两个元素位置
int temp = arr[y];
arr[y] = arr[y+1];
arr[y+1] = temp;
}
}
}
}
//遍历打印数组方法
public static void printArray(int[] arr)
{
System.out.print("[" );
for(int x = 0; x < arr.length; x++)
{
if(x != arr.length - 1)
System.out.print(arr[x] + "," );
else
System.out.println(arr[x] + "]" );
}
}
}
运行结果:
2.4 二分查找(折半查找)
二分查找是一种更高效的查找方式
注意:折半查找的前提是,数组是有序的。所以遇到无序数组要先排序再用二分查找。
/**
* 需求:演示折半查找
* 思路:
1、设置三个变量记录角标:min、max、mid。min初始值为0,max为数组最大角标,mid为(max+min)/2。
2、查看mid角标的元素是否与待查找的值相等,如果相等,则直接返回角标值,程序终止执行。
3、如果待查找的值小于角标为mid的元素值,那么说明待查找的元素的位置可能在min与mid角标之间。设置max = mid - 1,mid = (max + min)/2,重复第1、2步的操作。
4、如果待查找的值大于角标为mid的元素值,那么说明待查找的元素的位置可能在mid与max角标之间。设置min = mid + 1,mid = (max + min)/2,重复第1、2步的操作。
5、如果数组中不存在待查找的元素,那么按照如上流程,最终min角标值会大于max角标值,此时返回-1。
* @author jinlong
* */
package com.blog.part1.数组;
class BinarySearchDemo
{
public static void main(String[] args)
{
//定义一个数组,元素值大小无序
int[] arr= {13,15,19,28,33,45,78,106};
int index = binarySearch(arr,78);
System.out.println("index = " + index);
}
//定声明二分查找方法,传入参数为数组和要查找的值
public static int binarySearch(int[] arr, int key)
{
//这里定义三个变量,分别存储最大值,中间值和最小值的角标
int max,min,mid;
//min最小值为第一个元素的角标
min = 0;
// max初始值为最后一个元素的角标
max =arr. length - 1;
//中间值角标
mid = (max + min)/2;
//while循环,mid角标所对应的值是我们要找的值时停止。
while(arr[mid] !=key)
{
if(key > arr[mid])
//要找的数在中间值的右边,把中间值加一作为最小值的新角标
min = mid + 1;
else if (key < arr[mid])
//要找的数在中间值左边,把最小值角标减一作为新的最大值
max = mid - 1;
//最大值角标要始终大于最小值角标,当接近小于时,返回-1程序结束。
if(max < min)
return -1;
//得到最终mid
mid = (max + min)/2;
}
//返回mid
return mid;
}
}
运行结果:
/**
* 需求:插入数值保证数组有序
* 思路:
可以先通过二分查找,返回min的值,然后将待插入元素存在角标为min的数组位置,
数组中角标为min以及比min大的角标所在的数组元素全部往后顺延一个位置。
* @author jinlong
* */
package com.blog.part1.数组;
class BinarySearchDemo
{
public static void main(String[] args)
{
//定义一个数组,元素值必须是有序的
int[] arr= {13,15,19,28,33,45,78,106};
int index = binarySearch(arr,40);
System.out.println("index = " + index);
}
//定声明二分查找方法,传入参数为数组和要插入的值,返回紧临这个要插入值前边值的角标
public static int binarySearch(int[] arr, int key)
{
//这里定义三个变量,分别存储最大值,中间值和最小值的角标
int max,min,mid;
//min最小值为第一个元素的角标
min = 0;
// max初始值为最后一个元素的角标
max =arr. length - 1;
//中间值角标
mid = (max + min)/2;
//while循环
while(min<=max)
{
mid = (max + min)/2;
if(key > arr[mid])
//要找的数在中间值的右边,把中间值加一作为最小值的新角标
min = mid + 1;
else if (key < arr[mid])
//要找的数在中间值左边,把最小值角标减一作为新的最大值
max = mid - 1;
//
else
return mid;
//得到最终mid
}
//这里返回min角标值
return min;
}
}
运行结果:
所以要插入的位置角标为6
2.5 练习
获取一个十进制整数的2、8、16进制表现形式。
/**
* 需求:打印一个十进制数的二进制、八进制、十六进制值
* 思路: 1、首先判断如果传入的十进制数为0,那么它的2、8、16进制都是0,直接返回0,不需要再执行余下的程序。
2、以将十进制数转换成十六进制数为例:将60与15进行与操作,其值就是60的十六进制的最低位。
再将60无符号右移4位,再与15进行与操作,其值就是60的十六进制的倒数第二位。
把十六进制的所有元素放到一个表里,然后拿%15后的值去查找对应的位置。
0 1 2 3 4 5 6 7 8 9 A B C D E F ==十六进制中的元素。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3、由上面的例子可以总结出,将一个十进制数转换为十六进制的步骤就是:
将十进制数与15相与,将结果存储到一个数组的最低位。
然后将十进制数右移4位,再与15进行与操作,其值就是该数对应的十六进制的倒数第二位。
再右移4位,与15相与...直到相与结果为0为止。
4、进而可以推理得到,10进制转换为2和8进制的规律与转换为16进制很相似,只是偏移量和相与的数字不同而已。
10进制转换为2进制的偏移量为1,相与数字为1。
10进制转换为8进制的偏移量为3,相与数字为7。
* @author jinlong
* */
package com.blog.part1.数组;
public class NumTransDemo
{
public static void main(String[] args)
{
//十进制-->二进制
trans(60,1,1);
//十进制-->八进制
trans(60,7,3);
//十进制-->十六进制
trans(60,15,4);
}
//定义转制的通用方法:
//base值其实就是为要转的进制减一,offset为要偏移的量
public static void trans(int num, int base,int offset)
{
//判断值为0的情况
if(num == 0)
{
System.out.println("0" );
return;
}
//chs装有十六进制中所有元素
char[] chs = {'0','1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' };
//定义数组arr储存二进制码
char[] arr = new char[32];
//定义指针,指向数组arr最后元素的后边
int pos = arr.length ;
while(num != 0)
{
//循环与操作,获取的值作为chs的角标查找对应元素
int temp = num & base;
//arr数组中从后往前插入,获取的元素
arr[--pos] = chs[temp];
//偏移指定值
num = num >>> offset;
}
System.out.println("转换后值为: " );
//从前往后遍历打印arr数组
for(int x = pos; x < arr.length; x++)
{
System.out.print(arr[x]);
}
//换行
System.out.println();
}
}
运行结果为:
注意:现实开发中,JDK中int的包装类Integer提供了转换方法,可以直接使用。