Java 基础09-数组和算法

数组和算法

1. 数组

1.1 为何要使用数组

在开发中会出现大量重复的,而且是同一个类型的数据,须要同时时候,若是按照一个一个的变量定义,会致使代码出现如下一些问题:
	1、代码过于臃肿
	2、代码阅读性极差
	3、代码维护性极差
复制代码

1.2 Java 中定义数组的格式

变量的定义格式:
    数据类型 变量名 = 初始化数据;

数组的定义格式:
    数据类型[] 数组名 = new 数据类型[容量];

赋值号左侧:
    数据类型:
    	肯定当前数组中可以保存数据类型是什么,要求当前数组中有且只能保存指定的数据类型,严格执行数据类型一致化。
    
    []:
    	1、肯定当前建立的是一个数组类型;
    	2、肯定数组名是一个"引用数据类型",引用数据的变量里面保存的是另外一个数据空间的地址。
            
	数组名:
		1、操做当前数组使用的名字;
		2、数组名是一个引用数据类型变量。
            
            
赋值号右侧:
	new:
		建立数组空间的关键字。
            
	数据类型:
		先后一致,保证数据类型一致化,要求建立的数据类型是指定的数据类型。
            
	[容量]:
		肯定当前数组中数据容量是多少,并且建立以后,不能够改变。
            
数组的下标:
	数组的有效下标是从 0 开始到 数组的容量 - 1。
	若是数组的容量是 10,有效小标的范围就是 0 ~ 9。

使用格式:
	数组名[有效下标];
	arr[0] = 10;
	System.out.println(arr[0]);
复制代码

1.3 数组的内存分析图

栈内存,存储的是值
    
数据存储在内存中

内存是分区域的,目前代码中会涉及到"栈区""堆区"
复制代码

0x8848 这是内存地址。
认为是**省**市**区**路**号
    
数组下标 arr[0] arr[5]
认为是须要寻找的房间号 1001A 1005A
复制代码

1.4 数组和循环不得不说的秘密

对于数组的 CRUD 操做都是依赖循环完成的,并且大部分使用的循环都是 for 循环。
    
由于 for 循环能够经过第一行的循环语句得知当前循环的大概次数,这个特征很是适用于数组。
复制代码
public class Demo {
    
    public static void main(String[] args) {
        
        // 定义一个数组 int 类型,容量为 10
        int[] arr = new int[10];
        
        /* arr.length 是获取数组中的属性,数组的容量。 arr.length 获取的结果就是 10 */
        for(int i = 10; i < arr.length; i++) {
            arr[i] = i + 1;
        }
        
        for(int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}
复制代码

1.5 数组做为方法的参数

// main方法就是一个使用数组做为形式参数列表的方法
// String[] args 就是一个数组做为方法参数的格式
// 数据类型[] 形式参数的名字
public static void main(String[] args) {
    
}


public class Demo {
    
    public static void main(String[] args) {
        
        // 定义一个int类型数组,容量为10
        int[] array = new int[10];

        /* 该方法须要的参数是一个数组类型 把数组名做为方法的参数传入!!! */
        assignIntArray(array);

        printIntArray(array);
    }
    
    /* 需求: 完成一个方法,给予int类型数组进行赋值操做 方法名: assignIntArray 形式参数列表: 须要一个int类型数组,格式 int[] arr 返回值类型: void 这里目前不考虑返回值类型 public static void assignIntArray(int[] arr) */
    /** * 完成一个方法,给予int类型数组进行赋值操做 * @param arr int类型的数组 */
    public static void assignIntArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i + 1;
        }
    }

    /* 需求: 完成一个方法,展现int类型数组 方法名: printIntArray 形式参数列表: 须要展现的int类型数组,格式 int[] arr 返回值类型: void 这里目前不考虑返回值类型,后期会考虑!!!boolean int public static void printIntArray(int[] arr); */
    /** * 展现一个int类型数组 * @param arr 须要的int类型数组 */
    public static void printIntArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}
复制代码

2.练习

2.1 找出指定 int 类型数组中【最大值下标】和【最小值下标】位置

public class Demo {
    
    public static void main(String[] args) {
        
        int[] array = {1, 3, 5, 17, 9, 2, 4, 6, 17, 10};
        int index = maxIndexInArray(array);
        
        System.out.println(index);
    }

    /* 定义一个方法,能够找出指定 int 类型数组中最大值下标位置 方法分析: 方法名: maxIndexInArray 形式参数列表: 这里须要一个 int 类型的数组 int[] array 返回值类型: 这里但愿获得的是最大值下标,全部返回值类型是下标范围,就是 int 类型 public static int maxIndexInArray(int[] array) */

    /** * 找出指定数组中最大值所在下标位置 * @param array 指定的 int 类型数组 * @return 返回最大值所在下标位置 */
    public static int maxIndexInArray(int[] array) {
        
        // 一、假设下标为 0 的数据时最大值
        int maxIndex = 0;

        // 二、利用循环进行两两比较,而且数据比较从 1 开始
        for (int i = 1; i < array.length; i++) {
            // 三、判断下标为 maxIndex 元素若是小于下标为 i 的元素,保存下标 i 的值到 maxIndex
            if (array[maxIndex] < array[i]) {
                maxIndex = i;
            }
        }

        return maxIndex;
    }
}
复制代码
/* 定义一个方法,能够找出指定 int 类型数组中最小值下标位置 方法分析: 方法名: minIndexInArray 形式参数列表: 这里须要一个 int 类型的数组 int[] array 返回值类型: 这里但愿获得的是最小值下标,全部返回值类型是下标范围,就是 int 类型 public static int minIndexInArray(int[] arra */

/** * 找出指定数组中最小下标的元素 * @param array 指定的 int 类型数组 * @return 当前数组中最小值的下标位置 */
public static int minIndexInArray(int[] array) {
    
    int minIndex = 0;
    for (int i = 1; i < array.length; i++) {
        if (array[minIndex] > array[i]) {
            minIndex = i;
        }
    }
    
    return minIndex;
}
复制代码

2.2 找出指定 int 类型数据所在的【下标】位置

/* 定义一个方法,在指定 int 类型数组中,找出指定 int 类型数据所在的下标位置 找到返回值下标值: 0 ~ arr.length - 1 找不到返回 -1 方法分析: 方法名: indexOf 形式参数列表: 第一个: 须要一个 int类型的数据 int[] array 第二个: 肯定须要查询的数据, int int find 返回值类型: int 类型,找到返回值大于等于 0,没有找到返回-1 public static int indexOf(int[] array, int find) */

/** * 找出指定数据在指定数组中下标位置,找到返回值大于等 0,没有找到返回 -1 * @param array 查询数据的数组 int 类型数组 * @param find 查询的指定数据 in t类型数据 * @return 找到返回值大于等 0,没有找到返回 -1 */
public static int indexOf(int[] array, int find) {
    
    // 一、假设找不到数据
    int index = -1;

    // 二、利用循环,两两比较,找出指定数据在数组中下标位置,而且保存到 index 变量中
    for (int i = 0; i < array.length; i++) {
        // 三、下标为 i 的元素就是指定 find 数据,大家保存 下标 i 到 index 变量中
        if (array[i] == find) {
            index = i;
            // 四、若是找到数据,终止循环!!!break;
            break;
        }
    }

    return index;
}
复制代码

2.3 找出全部指定数据的下标位置

import java.util.Arrays;

public class FindAllInArray {
    
    public static void main(String[] args) {
        
        int[] arr = {1, 3, 5, 7, 9, 1, 3, 5, 7, 9};
        int[] indexes = new int[arr.length];

        int count = findAllIndexes(arr, indexes, 5);
        System.out.println(count);

        for (int i = 0; i < count; i++) {
            System.out.println(indexes[i]);
        }
    }

    /* 在一个数组中,找出全部指定数据的下标位置 【难】 方法分析: 方法名: findAllIndexes 找出全部指定元素的下标位置 形式参数列表: 1. 哪个数组中进行查询操做!!! int[] arr 2. 要查询的数据 int find 3. 须要另外的一个数组,保存找到的下标位置 a) 该数组是什么是就类型??? int类型数组 b) 该数组的容量应该是什么??? 和须要查询的目标数组容量是一致的!!! 返回值类型; 不考虑使用数组做为返回值,这里存在必定的隐患】 boolean: 运行成功返回true,运行失败返回false int: ??? 返回找到的数据有多少个 public static int findAllIndexes(int[] arr, int[] indexes, int find) */

    /** * 找出数组中指定元素 find在目标数组 arr的下标位置,而且保存到 indexes 数组中 * 返回值是找到的元素个数,没有找到,返回 0 * @param arr 查询数据目标数组,int类型 * @param indexes 保存找到数据下标位置的数组,int类型 * @param find 须要查询的数据,int类型 * @return 返回值找到的元素个数,没有找到,返回 0 */
    public static int findAllIndexes(int[] arr, int[] indexes, int find) {
        
        // 1. 参数合法性判断
        if (null == arr || null == indexes || arr.length == 0
                || indexes.length == 0 || indexes.length < arr.length) {
            System.out.println("Input parameter is invalid!");
           
            // 返回 0。结束方法,表示没有找到
            return 0;
        }

        // 2. 定义一个变量,计数
        int count = 0;

        // 3. 使用 for循环,遍历目标数组 arr,使用 if判断,找到目标元素
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == find) {
                /* a. 计数 count++ b. 把找到的下标位置放到 indexes数组中 第一次找到: 须要存放到下标为 0的位置,count++ count自增以前是 0 第二次找到: 须要存放到下标为 1的位置,count++ count自增以前是 1 indexes是存放下标位置的数组,count是计数有多少个目标数据 i是找到的下标位置 count同时能够表示当前 indexes数组中的有效元素个数 */
                indexes[count++] = i;
            }
        }

        return count;
    }
}
复制代码

2.4 替换指定元素

import java.util.Arrays;

public class ArrayReplace {
    
    public static void main(String[] args) {
        
        int[] array = {1, 2, 3, 4, 5, 0, 0, 0, 0, 0};

        boolean ret = replace(array, 10);
        System.out.println(ret);
        System.out.println(Arrays.toString(array));
    }

    /* 完成一个方法,替换掉数组中全部元素之为0的元素,替换为指定元素 方法分析: 方法名: replace 形式参数列表: 须要替换数据的int类型数据 须要指定的元素 int类型 (int[] array, int newNumber) 返回值类型: 不推荐使用void,使用void做为返回值的方法,是一个黑盒方法!!! 给予当前方法一个状态的监控!!! boolean 方法运行成功返回true,失败返回一个false 这玩意能失败??? 1. 若是数组的容量为0??? 会失败!!! 2. 数组名是一个引用数据类型,其中保存的内存地址不能为 null 会失败!!! public static boolean replace(int[] array, int newNumber) */

    /** * 替换指定数据中元素为 0的值,替换为 newNumber * @param array int类型数组 * @param newNumber 替换的int类型数组 * @return 方法运行成功返回 true,方法运行失败,返回 false */
    public static boolean replace(int[] array, int newNumber) {
        
        // 1. 参数合法性判断!!!
        if (null == array || array.length == 0) {
            System.out.println("输入参数不合法!!!");
            
            // 输入参数不合法,返回 false 告知调用者,方法执行失败!!!
            return false;
        }

        for (int i = 0; i < array.length; i++) {
            if (0 == array[i]) {
                array[i] = newNumber;
            }
        }

        return true;
    }
}
复制代码

2.4 删除指定下标元素

import java.util.Arrays;

public class ArrayRemove {
    
    public static void main(String[] args) {
        
        int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};

        remove(array, 0);
        System.out.println(Arrays.toString(array));
    }

    /* 完成一个方法,删除指定下标的元素,要求从删除位置开始,以后的元素总体前移。【难】 要求源数据数组是 int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; 删除以后,须要在数组的末尾补0,0是无效元素 方法分析: 方法名: remove / delete 形式参数列表: 1. 删除数据的目标数组 int[] arr 2. 指定删除数据的下标位置 int index 返回值类型: boolean 删除成功返回true,失败返回false 什么状况下会失败: a) 数组容量为0 b) 数组中保存的地址为 null c) 给予的删除下标是一个非法下标 public static boolean remove(int[] arr, int index) */

    /** * 在指定数组中,删除指定下标 index上的元素。 * @param arr 指定的 int类型数组 * @param index 指定的删除数据的下标,可是不能超出数组的有效下标范围 0 ~ arr.length - 1 * @return 删除操做成功返回 true,失败返回 false */
    public static boolean remove(int[] arr, int index) {
        
        // 1. 参数合法性判断
        if (null == arr || arr.length == 0 || index < 0 || index > arr.length -1 ) {
            System.out.println("Input parameter is invalid!");
            
            return false;
        }

        /* 2. 使用 for循环完成操做 这里使用 arr[i] = arr[i + 1]; */
        for (int i = index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
            /* index = 5; arr.length = 10; arr[5] = arr[6]; i++ == 6 arr[6] = arr[7]; i++ == 7 arr[7] = arr[8]; i++ == 8 arr[8] = arr[9]; i++ == 9 arr[9] = arr[10]; ArrayIndexOutOfBoundsException */
        }

        arr[arr.length - 1] = 0;

        return true;
    }
}
复制代码

2.5 添加元素到指定下标

import java.util.Arrays;

public class ArrayInsert {
    
    public static void main(String[] args) {
        
        int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0};

        add(array, 20, 30);

        System.out.println(Arrays.toString(array));
    }

    /* 完成一个方法,添加指定元素到指定下标位置,要求从指定下标位置以后的元素,总体向后移动。【难】 要求源数据数组是 int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0}; 0是无效元素,表示目前数组存在一个空位置 方法分析: 方法名: add 形式参数列表: 1. 数组 int[] arr 2. 指定下标位置 int index 3. 添加的数据 int number 返回值类型: boolean 成功返回true,失败返回false 什么状况下会失败: a) 数组容量为0 b) 数组中保存的地址为 null c) 给予的删除下标是一个非法下标 public static boolean add(int[] arr, int index, int number) */

    /** * 在数组中指定位置,添加指定元素 * * @param arr 指定的操做的数据,为 int类型 * @param index 指定的下标位置,必须是在数组的有效下标范围之内 0 ~ 数组容量 - 1 * @param number 添加的数据,为 int类型 * @return 添加成功返回 true ,失败返回 false */
    public static boolean add(int[] arr, int index, int number) {
        
        // 1. 参数合法性判断
        if (null == arr || arr.length == 0 || index < 0 || index > arr.length - 1) {
            System.out.println("Input parameter is invalid!");
            return false;
        }

        // 2. 利用循环移动数组中的元素,从最后一位开始
        for (int i = arr.length - 1; i > index; i--) {
            arr[i] = arr[i - 1];
            /* index = 5; arr.length = 10; arr[9] = arr[8]; i-- == 8 arr[8] = arr[7]; i-- == 7 arr[7] = arr[6]; i-- == 6 arr[6] = arr[5]; i-- == 5 */
        }

        arr[index] = number;

        return true;
    }
}
复制代码

3. 算法

3.1 选择排序算法

import java.util.Arrays;

public class ArraySort {
    
    public static void main(String[] args) {
        
        int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};

        selectSort(arr);

        System.out.println(Arrays.toString(arr));
    }
    /* 完成一个选择排序算法 */
    public static boolean selectSort(int[] arr) {
        // 1. 参数合法性判断
        if (null == arr || arr.length == 0) {
            System.out.println("Input parameter is invalid!");
            return false;
        }

        // 2. 外层循环控制须要进行多少次选择
        for (int i = 0; i < arr.length - 1; i++) {
            // 3. 使用一个变量,假设当前数组中极值
            int index = i;

            // 4. 找出极值下标位置
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[index] > arr[j]) {
                    index = j;
                }
            }

            // 5. 交换位置
            if (index != i) {
                int temp = arr[index];
                arr[index] = arr[i];
                arr[i] = temp;
            }
        }

        return true;
    }
复制代码

3.2 冒泡排序算法

/* 冒泡排序 */
public static void BubbleSort(int[] arr) {

	int length = arr.length;
	int temp;

	System.out.println("原始顺序: " + Arrays.toString(arr));

	//i表示第几趟排序
	for (int i = 1; i < length; i++) {

		//每次都从最后一个开始,知道第len-1趟排序
		for (int j = length - 1; j > i - 1; j--) {

			//若是后面的比前面的小,就像泡泡同样冒上去
			if (arr[j] < arr[j - 1]) {
				temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
			}
		}

		System.out.println("第" + i + "趟排序: " + Arrays.toString(arr));
	}
}
复制代码

3.3 二分查找算法

//二分法查找
public class HalfSearch {
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9, 11, 13, 13, 13, 19};

        int i = halfSearch(arr, 13);
        System.out.println(i);
    }

    /** * 二分法查找 * @param arr 通过排序的数组,默认为升序 * @param find 须要查询的数据 * @return 返回值为 int类型,找到数据的下标位置,若是没有找到返回 -1 */
    public static int halfSearch(int[] arr, int find) {
        if (null == arr || arr.length == 0) {
            System.out.println("Input param is invalid");
            return -1;
        }

        int maxIndex = arr.length - 1;
        int minIndex = 0;
        int midIndex = (maxIndex + minIndex) / 2;

        while (minIndex <= maxIndex) {
            /* 假如查询的数据时大于中间数据的,那么也就是说,查询的数据在中间数据右侧 修改最小值下标 */
            if (arr[midIndex] < find) {
                minIndex = midIndex + 1;
                /* 假如查询的数据是小于中间数据,证实当前查询的数据在中间数据的左侧 修改最大值下标 */
            } else if (arr[midIndex] > find) {
                maxIndex = midIndex  - 1;
            } else {
                return midIndex;
            }

            midIndex = (maxIndex + minIndex) / 2;
        }
        return -1;
    }
}
复制代码
相关文章
相关标签/搜索