数组概述+数组排序+数组查找
1、数组(概述-内存结构)
同一种类型数据的集合,其实数组就是一个容器。
数组的好处:
可以自动给数组中的元素从0开始编号,方便操作这些元素。
格式1:
元素类型[] 数组名 = new 元素类型(元素个数或数组长度)
//需求:想定义一个可以存储3个整数的容器
int[] x = new int[3];//new用来在内存中产生一个容器实体,存储实体。x不是int类型,x是数组类型
int x=3;//在栈内存中开辟空间,数据使用完毕会自动释放。
对比:
int x= new int[3];//new在堆内存中开辟空间,new中元素[0]的地址0x0079赋给x
//打印数据角标为0的元素的值。
system.out.println(x[0]);//打印0
system.out.println(x[1]);打印0。没有初始元素x[1],那么int数据默认初始化值为0
x[0]=59;
x=null;//x变成垃圾,在不确定的时间内系统会清除它。
//java的垃圾回收机制:成长于c++,优化了c++中的内存部分。当内存中的实体不用,c++由程序员手动调用一个程序去完成垃圾回收这功能。
int[] x=new int[3];
int[] y=x;
y[1]=89;
x=null;//没有垃圾。因为y还有利用x所对应的元素。
system.out.println(y[1]);
对比:
int[] x=new int[3];
int[] y=new int[3];
y[1]=89;
system.out.println(x[1]);//打印0。x和y对应的new地址不同
x=null;//有垃圾。x的有无对y没有影响。
system.out.println(x[1]);
2、数组(静态初始化-常见问题)
int[] arr= new int[2];
对比
int arr[]=new int[2];
数组的第二种定义格式
int[] arr=new int[]{3,1,6,5,4};
对比简化后的式子:
int[] arr={3,1,6,5,4};
system.out.println(arr[2]);//打印6
int[] arr=new int[5];
arr[0]=60;
int[] arr=new int[3];
system.out.println(arr[2]);//打印0
system.out.println(arr[3]);//编译通过,运行错误。arrayindexoutofboundsexception;编译时候没有错误提示,没有完全建立数组。运行的时候才会在堆内存中开辟空间[0]、[1]、[2]元素。
int[] arr=new int[3];
arr=null;
system.out.println(arr[1]);//编译通过,运行报错。空指针异常;当引用没有任何指向值null的情况,该引用还在用于操作实体。
3、数组(常见操作-遍历)
//数组的操作
//获取数组中的元素,通常会用到遍历(读取数组的每个元素)。然后通常会用到for循环。
int[] arr=new int[3];
system.out.println("arr["+0+"]="+arr[0]+";");//打印arr[0]=0;
system.out.println("arr["+0+"]="+arr[1]+";");//打印arr[1]=0;
system.out.println("arr["+0+"]="+arr[2]+";");//打印arr[2]=0;
转变为for语句:
int[] arr=new int[3];
for(int x=0;x<3;x++)
{
system.out.println("arr["+x+"]="+arr[x]+";");//arr[x]=0;
}
//数组中有一个属性可以直接获取到数值元素个数。
使用方式:数组名称.length
int[] arr={3,6,5,1,8,9};
system.out.println("length:"+arr.length);//打印该数组的每个数
for(int x=0;x<6;x++)
{
system.out.println("arr["+x+"]="+arr[x]+";");
}//依次打印各个元素。
length:6
arr[0]=3;
arr[1]=6;
arr[2]=5;
arr[3]=1;
arr[4]=8;
arr[5]=9;
对比:
通过length实现功能:
int[] arr={3,6,5,1,8,9};
system.out.println("length:"+arr.length);//打印数字的个数
for(int x=0;x<arr.length;x++)//利用数组arr.length=6
{
system.out.println("arr["+x+"]="+arr[x]+";");
}//依次打印各个元素。
length:6
arr[0]=3;
arr[1]=6;
arr[2]=5;
arr[3]=1;
arr[4]=8;
arr[5]=9;
实现元素求和功能:
int[] arr={3,6,5,1,8,9};
system.out.println("length:"+arr.length);//打印数字的个数
int sum=0;
for(int x=0;x<arr.length;x++)
{
sum +=arr[x];
system.out.println("arr["+x+"]="+arr[x]+";");
}//依次打印各个元素。
length:6
arr[0]=3;
arr[1]=6;
arr[2]=5;
arr[3]=1;
arr[4]=8;
arr[5]=9;
//定义一个功能:用于打印数组中的元素,元素间用分号隔开。
class arraydemo
{
public static void main(sting[] args)
{
int[] arr={3,6,5,1,8,9};
printarray(arr);
}
pubic static void printarray(int[] arr)//用的数组的格式int[]
{
for(int x=0;x<arr.length;x++)
{
system.out.print(arr[x]+";");
}
}
}
//打印:
3;6;5;1;8;9;//发现结尾多了个;不好看,怎么办?
class arraydemo
{
public static void main(sting[] args)
{
int[] arr={3,6,5,1,8,9};
printarray(arr);
printarray(arr);
}
pubic static void printarray(int[] arr)
{
for(int x=0;x<arr.length;x++)
{
if(x!=arr.length-1)
system.out.print(arr[x]+";");
else
system.out.println(arr[x]); //当打印最后一个元素的时候,不打印";"
}
}
}
//打印:
3;6;5;1;8;9
3;6;5;1;8;9
修改版(美化版):
class arraydemo
{
public static void main(sting[] args)
{
int[] arr={3,6,5,1,8,9};
printarray(arr);
}
pubic 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]+"]");
}
}
}
//打印:
[3;6;5;1;8;9]
4、数组(常见操作-获取最值)
//获取一个数组中的最大值
{5,1,6,4,2,8,9}
思路:
1、获取最值需要进行比较,每一次比较都会有一个较大的值,因为该值不确定,通过一个变量进行临时存储。
2、让数组中的每一个元素都和这个变量中的值进行比较
如果大于了变量中的值,就用该变量记录较大的值
3、当所以的元素都比较完成,那么该变量中存储的就是数组中的最大值了\\
步骤:
1、定义变量,初始化为数组中任意一个元素即可。
2、通过循环语句对数组进行遍历
3、在变量过程中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。
需要定义一个功能来完成,以便提高复用性。
1、明确结果,数组中的最大元素 int
2、未知内容:一个数组。int[]
public static int getmax(int[] arr)
{
int max=arr[0];//初始化arr[0]的值时,放在函数的内部更好,阅读和理解性更强。
for(int x=1;x<arr.length;x++)//这样x从1开始就可以了。
{
if(arr[x]>max)
max=arr[x];
}
return max;
}
public static void main(sting[] args)
{
int[] arr={5,1,6,4,2,8,9};
int max=getmax(arr);//定义函数
system.out.println("max="+max);
}//打印max=9;验证功能实现。
获取最大值的另外一种方法。
可不可以将临时变量初始化为0呢?可以。这种方式,其实是在初始化为数组中的任意一个角标。
public static int getmax_2(int[] arr)
{
int max=0;
for(int x=1;x<arr.length;x++)
{
if(arr[x]>arr[max])
max=x;
}
return arr[max];//返回的是数组的一个元素。
}
public static void main(sting[] args)
{
int[] arr={5,1,6,4,2,8,9};
int max=getmax_2(arr);
system.out.println("max="+max);
}//打印max=9;验证功能实现。
//需求:获取最小值。恰好相反。由>变<
public static int getmin(int[] arr)
{
int min=0;
for(int x=1;x<arr.length;x++)
{
if(arr[x]<arr[min])
min=x;
}
return arr[min];
}
public static void main(sting[] args)
{
int[] arr={5,1,6,4,2,8,9};
int min=getmin(arr);
system.out.println("min="+min);
}//打印min=1;验证功能实现。
//需求:获取duoble类型数组的最大值。因为功能一致,所以定义相同函数名称。以重载形式存在。
public static double getmax(duoble[] arr)
{
.............内容同上面的相似。
}
5、数组(排序-选择排序)
{5,1,6,2,8,9}
//给数组的元素从小到大进行排序。
步骤:
可以看出比较的次数:依次减少。
*****嵌套循环。
****
***
**
*
class arraytest
{
public static void selectsort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)//没必要遍历到最后一个角标,当x=5,y=6,超出范围。
{
for(int y=x+1;y<arr.lenght;y++)//尖朝下,改变初始条件
{
if(arr[x]>arr[y])
{int temp= arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
}
public static void main(sting[] args)
{
int[] arr={5,1,6,2,8,9};
//在排序前打印;
printarray(arr);
selectsort(arr);
//在排序后打印;
printarray(arr);
}
//定义一个打印数组功能的函数
pubic 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]+"]");
}
}
//打印
[5, 1, 6, 2, 8, 9]
[1, 2, 5, 6, 8, 9]
//给数组的元素从大到小进行排序。同理把>变成<即可
class arraytest
{
public static void selectsort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)//没必要遍历到最后一个角标
{
for(int y=x+1;y<arr.lenght;y++)
{
if(arr[x]<arr[y])
{int temp= arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
}
public static void main(sting[] args)
{
int[] arr={5,1,6,2,8,9};
//在排序前打印;
printarray(arr);
selectsort(arr);
//在排序后打印;
printarray(arr);
}
pubic 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]+"]");
}
}
//打印
[5, 1, 6, 2, 8, 9]
[9, 8, 6, 5, 2, 1]
//总结:选择排序:
内循环结束一次,最值出现头角标位置。
6、数组排序-冒泡排序
所谓冒泡:就是经过排序后,越大的数会慢慢浮到数组的顶端。像气泡一样,越大越往上
大的数往后面移。
冒泡排序:相邻的两个元素进行比较,如果符合条件换位。最后位得出一个最值数,第二次比较就少了一个元素;以此类推,次数越多,需要比较的元素越少。
public static void bubblesort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)
{
for(int y=0;y<arr.length-x-1;y++)//-x是让每一次比较的元素随着x减少,比如:第2次比较时,就少了x=1个元素;-1,避免角标越界,For循环中y+1会超出范围。
{
if(arr[y]>arr[y+1])
{
int temp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;
}
}
}
}
//冒泡排序:最值出现在最后面。
7、数组排序-位置置换功能抽取
//发现无论什么排序,都需要对满足条件的元素进行位置置换。
所以可以把这部分相同的代码提取出来,单独封装成一个函数。
public static void swap(int[] arr,int a,int b)//这里要定义三个变量,是因为需要把数组传递
{
int temp =arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
冒泡排序的代码变成如下:
public static void bubblesort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)
{
for(int y=0;y<arr.length-x-1;y++)//-x是让每一次比较的元素;-1,避免角标越界。
{
if(arr[y]>arr[y+1])
{
swap(arr,y,y+1);//函数的精髓。函数嵌套。
}
}
}
}
顺序排序的代码变成如下:(从小到大排序)
public static void selectsort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)//没必要遍历到最后一个角标,下面的for中有x+1,会超出范围
{
for(int y=x+1;y<arr.lenght;y++)//这里y=x可以吗?可以是可以但是这样会增加运算量。
{
if(arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
8、数组(折半查找)
数组的查找操作。
class arraytest4
{
public stativ void main(sting[] args)
{
int[] arr={2,4,5,7,19,32,45};
int index=getindex(arr,19);
system.out.println("index="+index);//打印角标4
}
普通查找法:
//定义功能:获取key第一次出现在数组中的位置。如果返回-1代表key在该数组中不存在。
public static int getindex(int[] arr,intkey)
{
for(int x=0;x<arr.length;x++)
{
if(arr[x]==key)
return x;
}
return -1;//-1代表这个数组的角标不存在,是惯例。
}
}
折半查找:提高效率,但是必需要保证该数组是有序的数组。
class arraytest4
{
public stativ void main(sting[] args)
{
int[] arr={2,4,5,7,19,32,45};//数组有序,可以采样折半查找
int index= halfsearch(arr,32);
system.out.println("index="+index);//打印下标5
}
public static int halfsearch(int[] arr,intkey)
{//定义边界
int min,max,mid;
min=0;//最小的数组元素下标0
max=arr.length-1;//最大的数组元素下标
mid=(max+min)/2;//中间数组元素的下标
while(arr[mid]!=key)
{//与mid中间下标做比较
if(arr[mid]<key)//目标元素key>mid,
min=mid+1;//范围缩小到右半边
else if(arr[mid]>key)
max=mid-1;
if(min>max)//?????,当目标不属于该数组时。这种思路比较巧,可以通过数字3来验证。
return -1;
mid=(max+min)/2;
}
return mid;
}
}
方法2:
class arraytest4
{
public static void main(sting[] args)
{
int[] arr={2,4,5,7,19,32,45};
int index= halfsearch(arr,5);
system.out.println("index="+index);//打印下标2
}
public static int halfsearch(int[] arr,intkey)
{
int min=0,max=arr.length-1,mid;
while(min<=max)//?????当数是属于该数组的时候
{
mid=(min+max)>>1;//把除2运算转变成,位运算右移1位。
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else
return mid;
}
return -1;
}
//有一个有序的数组,想要将一个元素插入到该数组中,
还有保证该数组是有序的。
如何获取该元素在数组中的位置。??比如:元素8
class arraytest
{
public static void main(sting[] args)
{
int[] arr={2,4,5,7,19,32,45};
int index= halfsearch(arr,8);//输入元素8
system.out.println("index="+index);//打印下标4
}
public static int halfsearch(int[] arr,intkey)
{
int min=0,max=arr.length-1,mid;
while(min<=max)
{
mid=(min+max)>>1;
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else
return mid;
}
return min;//min就是8需要插入位置的下标。
}
参考下面的注释:
2 4 5 7 19 32 45数组元素
0 1 2 3 4 5 6(数组的下标)
min=0;max=6;mid=6>>1=3;
key=8>7(mid);min=mid+1=4;mid=(4+6)/2=5;
2 4 5 7 19 32 45数组元素
0 1 2 3 4 5 6(数组的下标)
min mid
8<32(mid);max=mid-1=4;mid=(4+4)/2=4;
2 4 5 7 19 32 45数组元素
0 1 2 3 4 5 6(数组的下标)
min
mid
8<19(mid);max=mid-1=3;//此时max<min,结束while循环