一维数组
介绍
- 数组是一种引用类型
- 数组是一种简单的数据结果,线性的结构
- 数组是一种容器,可以来存储其他元素,数组是可以存储任意数据类型的元素。
- 数组可以分为:一维数组、二维数组、三维数组
- 数组中存储的元素类型必须是统一的
- 数组一旦创建,长度是固定的,如果想要增加元素,需要扩容,但是也是新的数组,不是原有的数组
静态初始化数组
静态初始化的相关图解动态初始化数组
int[] a1 = new int[4];
//初始化数组长度为4,里面的数据默认是0,做修改就直接a[1] = 2
//注意:如果定义完对象类型的数组后,要输出用println,这样底层会有一个三目运算,当为空的时候返回null,而不会报空指针异常,如果直接toString输出的话,会报空指针异常
总结:
- 栈中,a1保存的是堆中数组的首元素地址!
- 数组的排列顺序是有规律的,造成的优点就是查找很快,因为查找时计算的就是首元素到偏移量的,但是这样造成的就是增删的效率就慢了(缺点),因为增删会影响原有的数组有序,修改的效率也很快。
- 如果数组中存储的是对象,那么在堆中的这个数组,保存的就是对象的地址。
- 取出数组中最后一个元素就是使用a[a.length-1]
- 由于数组中存储的类型是一致的,所以每一个元素中在数组中存储所占的空间大小是一样的。
什么时候使用动态初始化?什么时候使用静态初始化?
其实没有本质区别,无论是动态初始化还是静态初始化,最终的内存分布都是一样的。
如果在创建数组的时候,知道数组中存的数据,这个时候当然采用静态的。当不知道的时候,先去开辟空间。
instanceof关键字
class Animal {
}
public class Cat extends Animal{
void eat(){
System.out.println("小猫吃~");
}
}
public class Dog extends Animal{
void move(){
System.out.println("小狗跑~");
}
}
题目:如果把cat和Dog的对象放在数组中,怎么判断是用eat还是move?
//创建一个数组
Animal[] as = new Animal[4];
//给每个元素赋值
Dog d1 = new Dog();
Dog d2 = new Dog();
Cat c1 = new Cat();
Cat c2 = new Cat();
as[0] = d1;
as[1] = d2;
as[2] = c1;
as[3] = c2;
//需求,遍历数组,如果是dog执行move,如果是cat执行eat
for(int i = 0;i<as.length;i++){
Animal a = as[i];
if(a instanceof Cat){
//强制类型转换
Cat c = (Cat)a;
c.eat;
}else{
Dog d = (Dog)a;
d.move();
}
}
关于main方法中的数组的参数args
public class Test{
public static void main(String[] args){
}
}
//这个String[] args就是在java运行的时候,可以提供参数
//参数格式: java Test szw 123456
//这个就是代表数组中存放了szw和123456,中间用空格空开
关于数组的拷贝,这个也可以用到扩容
静态方法进行初始化拷贝public class Test{
public static void main(String[] args){
//System.arrayCopy(原数组,原数组的开始下标,目标数组,目标数组的开始下标,拷贝的长度);
int[] src = {1,2,3,4};
int[] target = {9,9,3,9,9,9};
//把src数组从下标0开始的4长度拷贝到target数组中从三开始
System.arrayCopy(src,0,target,2,4);
}
}
二维数组
特点
- 二维数组是一个特殊的一维数组
- 特殊的一维数组,特殊在一个一维数组中的每一个元素都是一个一维数组
public class Test{
public static void main(String[] args){
//静态初始化一个二维数组
int[][] a = {
{1,2,3},
{11,22,33},
{0,3,4},
{11,32}
};
//所以如果输出a.length,就是4
//需求,不管二维数组的定义,请输出最后一个32
System,out.println(a[a.length-1],[a[a.length-1].length-1]);
}
}
冒泡排序
思路分析
冒泡排序分析注意:就是每一趟排序的时候,次数都会减一,第一趟排序时数组的长度减一!
代码实现
//只有一遍的冒泡排序
@Test
public void BubbleTest(){
int arr[] = {3,9,11,-1,-2};//先定义数组
//定义临时变量
int temp = 0;
for (int i = 0; i < arr.length -1 ; i++){
if (arr[i] > arr[i+1]){
temp = arr[i+1];
arr[i+1] = arr[i];
arr[i] = temp;
}
}
System.out.println("第一遍排序后的结果"+ Arrays.toString(arr));
}
//我们在进行第二遍、第三遍往后的排序中,代码的主体不变,只有i<arr.length-1变化了,那么可以更改为以下
@Test
public void BubbleTest(){
int arr[] = {3,9,11,-1,-2};//先定义数组
//定义临时变量
int temp = 0;
for (int i = 0; i< arr.length - 1; i++){
for (int j = 0; j < arr.length -1 - i ; j++){
if (arr[j] > arr[j+1]){
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
System.out.println("第"+(i+1)+"遍排序后的结果"+ Arrays.toString(arr));
}
}
}
//优化!
//优化的作用就是当两趟的排序一样,没有发生变化,就可以停止排序了,这样节省了一部分时间
@Test
public void BubbleTest(){
int arr[] = {3,9,11,-2,-1};//先定义数组
//定义临时变量
int temp = 0;
Boolean flag = false;
for (int i = 0; i< arr.length - 1; i++){
for (int j = 0; j < arr.length -1 - i ; j++){
if (arr[j] > arr[j+1]){
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
flag = true;
}
}
if (!flag){
break;
}else{
flag = false;//重置
}
System.out.println("第"+(i+1)+"遍排序后的结果"+ Arrays.toString(arr));
}
}
}
选择排序
基本思想
在一组数组中,找到最小的一个值,和第一个做交换。然后继续找到第二个最小的值,与第二个值进行一个交换。
选择排序分析注意:每次排序之后,交换的那个位置不再进行下一次的排序,因为他已经是当前位置最小的数据了。
代码实现
//第一遍选择排序
@Test
public void SelectTest(){
int[] arr = {101,34,119,1};
int min = arr[0];//假设最小值是数组中的第一个
int minIndex = 0;//最小的下标就是0
for (int i = 1; i<arr.length;i++){
if (min > arr[i]){//如果在第一个数据之后有比假设的最小值要小的话,就把那个值变成最小值存放在min中
min = arr[i];
minIndex = i;
}
}
//一遍之后,肯定找到了最小值,把第一个数据与最小值进行一个交换
arr[minIndex] = arr[0];//把最小值的值与a[0]进行一个交换
arr[0] = min;//让a[0]成为最小值
System.out.println("第一次排序后"+ Arrays.toString(arr));
}
}
//正式代码
@Test
public void SelectTest(){
int[] arr = {101,34,119,1};
for (int i = 0;i<arr.length-1;i++){
int minIndex = i;
int min = arr[i];
//先查找最小值,与一开始定义最小值做比较,注意这里不是交换真正的值,只是把值存入min中
for (int j = i+1;j<arr.length;j++){
if (min > arr[j]){//说明假定的最小值,并不是最小值
min = arr[j];
minIndex = j;
}
}
if (minIndex != i){//这时候才做有用的交换
arr[minIndex] = arr[i];//minIndex就是当前最小的那个数的原始位置
arr[i] = min;
}
System.out.println("第"+(i+1)+"轮排序后"+Arrays.toString(arr));
}
}
二分查找
import org.junit.Test;
public class Test1 {
@Test
public void test(){
int[] a = {10,19,21,33,90};//注意二分查找需要的数组必须是有序的
int target = 99;
int index = twoFind(a, target);
System.out.println((index == -1)?"元素不存在!":"在数组中的下标是"+index);
}
//二分查找
public static int twoFind(int[] a,int target){
//形参是传来一个数组还有待查元素,返回待查元素的在数组中的下标
int index = 0;
int end = a.length-1;
//这里就是为了防止数组下标越界
while (index <= end){
int middle = (index+end) / 2;
if (target == a[middle]){
return middle;
}else if (target > a[middle]){
index = middle + 1;//注意这里的加一和下面的减一
}else if (target < a[middle]){
end = middle - 1;
}
}
//while循环完了还没有找到,就代表没有找到该元素
return -1;
}
}
//关于Arrays中的两个方法
Arrays.sort();//排序
binarySearch(int[] a, int key);//这个是Arrays中的查找
网友评论