IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 6.数组-二维数组 -> 正文阅读

[数据结构与算法]6.数组-二维数组

一、数组高级练习

1.练习

(1).数组反转

/*
	介绍: 
		数组的反转
			数组中的元素颠倒顺序,例如原始数组为1,2,3,4,5,反转后的数组为5,4,3,2,1
	思路: 
		数组最远端的元素互换位置
			○ 实现反转,就需要将数组最远端元素位置交换
            ○ 定义两个变量,保存数组的最小索引和最大索引
            ○ 两个索引上的元素交换位置
            ○ 最小索引++,最大索引--,再次交换位置
            ○ 最小索引超过了最大索引,数组反转操作结束
*/

public class Test01 {
    public static void main(String[] args) {
        // 定义数组, 并初始化
        int[] arr = {11, 22, 33, 44, 55, 66};

        // 定义临时变量, 用于交换数组
        int temp = 0;

        // 反转数组, 只需要执行 arr.length / 次即可
        for (int i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

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

(2).数组的动态扩容,删除,插入

/**
 *
 * 数组的动态操作:扩容,插入,删除
 * 分析:
 * 1.根据原来数组的长度创建一个新数组
 * 2.进行原来数组中元素的转移
 *
 */
 
 public class Test05 {
    public static void main(String[] args) {
        // 定义数组, 并初始化数据
        int[] arr = {51, 123, 15};
        System.out.println("操作前: " + Arrays.toString(arr));

        System.out.println("==========");
        //扩容数据
        arr = add(arr, 30);
        System.out.println("扩容后: " + Arrays.toString(arr));

        System.out.println("==========");
        //插入数据
        arr = insert(arr, 90, 1);
        System.out.println("插入后: " + Arrays.toString(arr));

        System.out.println("==========");
        //删除数据
        arr = delete(arr, 123);
        System.out.println("删除后: " + Arrays.toString(arr));
    }

    /**
     * 删除数据
     * @param arr
     * @param value
     * @return
     */
    private static int[] delete(int[] arr, int value) {
        // 下标, 用来确定是否有该值
        int index = -1;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value){
                index = i;
                break;
            }
        }
        int[] deleteArr;
        if (index == -1){
            return arr;
        }else {
            deleteArr = new int[arr.length - 1];
        }

        // 下标, 用来确定是否有该值
        for (int i = 0; i < deleteArr.length; i++) {
            if (i >= index){
                deleteArr[i] = arr[i + 1];
            }else {
                deleteArr[i] = arr[i];
            }
        }
        return deleteArr;
    }

    /**
     * 插入数据
     * @param arr
     * @param value
     * @param index
     * @return
     */
    private static int[] insert(int[] arr, int value, int index) {
        int[] insertArr = new int[arr.length + 1];
        // 如果下标过大, 则排最后一个,
        // 如果下标过小, 则排第一个
        if (index >= insertArr.length) {
            index = insertArr.length - 1;
        }else if (index <= 0){
            index = 0;
        }

        insertArr[index] = value;
        for (int i = 0; i < arr.length; i++) {
            if (index > i) {
                insertArr[i] = arr[i];
            } else {
                insertArr[i + 1] = arr[i];
            }
        }
        return insertArr;
    }
    /**
     * 扩容数据
     *
     * @param arr
     * @param i
     * @return
     */
    private static int[] add(int[] arr, int i) {
        int[] addArr = new int[arr.length + 1];
        for (int j = 0; j < arr.length; j++) {
            addArr[j] = arr[j];
        }
        addArr[addArr.length - 1] = i;
        return addArr;
    }
}


2.十大内部排序算法

选择排序: 
	直接选择排序、堆排序
交换排序: 
	冒泡排序、快速排序
插入排序: 
	直接插入排序、折半插入排序、Shell排序
归并排序
捅式排序
基数排序

(1).冒泡排序

/*
	原理
		冒泡排序的原理非常简单, 它重复地走访过要排序的数列, 一次比较两个元素, 如果他们的顺序错误就把他们交换过来
	思路
		1.比较相邻的元素, 如果第一个比第二个大(升序), 就交换他们两个
        2.对每一对相邻元素做同样的工作, 从开始第一对到结尾的最后一对, 这步做完后, 最后的元素会是最大的数
        3.针对所有的元素重复以上的步骤, 除了最后一个
        4.持续每次对越来越少的元素重复上面的步骤, 直到没有任何一对数字需要比较为止
*/
public class Test02 {
    public static void main(String[] args) {
        // 定义一个数组, 并初始化
        int[] arr = {1,321,51,-3,-4,55,63,94};

        // 进行数组排序
        getArrayToSort(arr);

        // 把最大的值排到最后
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 用于冒泡排序
     */
    private static void getArrayToSort(int[] arr) {
        //定义一个变量, 用于交换数据
        int temp;
        // 进行循环, 冒泡排序
        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];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

(2).选择排序

原理:
	每一趟从待排序的数据中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕 。
思路:
	给定数组:int[] arr={里面n个数据};
	第一趟排序,在待排序数据1~n中选出最小的数据,将它与数据1交换;
	第二趟,在待排序数据2~n中选出最小的数据,将它与数据2交换;
	以此类推,第i趟在待排序数据数据i~n中选出最小的数据,将它与数据i交换,直到全部排序完成。

public class Test09 {
    public static void main(String[] args) {
        // 定义数组, 并初始化数据
        int[] arr = {1, 2, 8, 4, 9, 5, 5, 2, 8, 4, 9, 1};

        // 选择排序
        selectSort(arr);

        // 排序后数据
        System.out.println("排序后: " + Arrays.toString(arr));
    }

    private static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int index = i;  //定义当前下标
            // 因为要把最小的放在前面, 所以已经放在前的数可以不用在循环
            for (int j = 1 + i; j < arr.length; j++) {
                if (arr[index] > arr[j]){
                    //  如果下标位置大于 循环j的位置, 则改变index下标, 记录最小数的位置
                    index = j;
                }
            }
            if (index != i){
                // 如果index下标改变了, 则与i的位置进行交换, 把最小的数, 放在数组前面
                int temp = arr[index];
                arr[index] = arr[i];
                arr[i] = temp;
            }
        }
    }
}

(3).快速排序: 快!

介绍:
	○ 快速排序由图灵奖获得者Tony Hoare发明, 被列为20世纪十大算法之一, 是迄今为止所有哦内排序算法中速度最快
    的一种. 冒泡排序的升级版, 交换排序的一种, 快速排序的时间复杂度为O(nlog(n))
排序思想:
	1.从数列中挑出一个元素, 称为"基准"(pivot)
    2.重新排序数列, 所有元素比基准值小的摆放在基准前面, 所有元素比基准值大的摆在基准的后面(相同的数可以放
		到任意一边), 在这个分区结束之后, 该基准就处于数列的中间位置, 这个称为分区(partition)操作
    3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序
    4.递归的最底部情形, 是数列的大小是零或一, 也就是永远都已经被排序好了, 虽然一直递归下去, 但是这个算法
		总会结束, 因为在每次的迭代(iteration)中, 它至少会把一个元素摆到它最后的位置去

public class QuickSort {
	private static void swap(int[] data, int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}

	private static void subSort(int[] data, int start, int end) {
		if (start < end) {
			int base = data[start];
			int low = start;
			int high = end + 1;
			while (true) {
				while (low < end && data[++low] - base <= 0)
					;
				while (high > start && data[--high] - base >= 0)
					;
				if (low < high) {
					swap(data, low, high);
				} else {
					break;
				}
			}
			swap(data, start, high);
			
			subSort(data, start, high - 1);//递归调用
			subSort(data, high + 1, end);
		}
	}
	public static void quickSort(int[] data){
		subSort(data,0,data.length-1);
	}
	
	
	public static void main(String[] args) {
		int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
		System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
		quickSort(data);
		System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
	}
}

3.查找算法

(1).线性查找法: 慢!

// 一个数一个数的比较
public class Test03 {
    public static void main(String[] args) {
        // 定义数组, 并初始化数据
        int[] arr = {11, 22, 33, 44, 55, 66};

        int index = getIndexAsArray(arr, 44);
        if (index == -1) {
            System.out.println("没有找到该数据");
        } else {
            System.out.println("下标为: " + index);
        }

    }

    private static int getIndexAsArray(int[] arr, int temp) {
        for (int i = 0; i < arr.length; i++) {
            if (temp == arr[i]) {
                return i;
            }
        }
        return -1;
    }
}

(2).二分查找法:前提有序

/*
	二分查找
		对折对折再对折
	要求
		要求数组元素必须支持比较大小,并且数组中的元素已经按大小排好序
*/
public class Test04 {
    public static void main(String[] args) {
        // 定义一个数组, 并初始化
        int[] arr = {10, 20, 30, 40, 50, 60, 70}; // 7 + 4 / 2 5
        // 要查找的值
        int value = 40;

        // 判断是否找到了 , false 没有找到
        int valueIndex = isFlag(arr, value);

        if (valueIndex == -1) {
            System.out.println("没有找到!!!");
        } else {
            System.out.println("找到了,下标为: " + valueIndex);
        }

    }

    private static int isFlag(int[] arr, int value) {
        //开始坐标
        int start = 0;
        // 结尾坐标
        int end = arr.length - 1;

        // 判断是否找到指定数据
        int valueIndex = -1;

        while (start <= end) {
            int index = (start + end) / 2; //中间的下标
            if (value == arr[index]) {
                valueIndex = index;
                break;
            } else if (value > arr[index]) {
                start = index + 1;
            } else if (value < arr[index]) {
                end = index - 1;
            }
        }
        return valueIndex;
    }
}

二、数组和方法的综合应用

1.可变参数

可变参数(JDK5.0)
	含义:
		在程序中,以实参为元素进行隐式静态初始化的数组
	格式:
		数据类型... 可变参数名
	注意:
		1.当方法除外可变参数外还有其他参数时,需要将可变参数声明在形参列表的最后一个位置,否则编译报错
		2.一个方法最多只能有一个可变参数
		
修饰符 返回值类型 方法名(数据类型... 形参名){}

??其实与这个书写完全等价

修饰符 返回值类型 方法名(数据类型[] 形参名){}

使用方法注意:
??如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置


2.方法形式参数和实际参数的特点

● 形参:
	○ 在定义方法时方法名后面括号中的变量名称称为形式参数(简称形参),即形参出现在方法定义中。

● 实参:
	○ 调用者方法中调用另一个方法时,方法名后面括号中的参数称为实际参数(简称实参),即实参出现在调用者方法中。

● 形式参数和实际参数的特点:
	○ 方法的形参是基本数据类型时,形参值的改变不会影响实参;
	○ 方法的形参是引用数据类型时,形参地址值的改变不会影响实参,但是形参地址值里面的数据的改变会影响实参。

三、二维数组

1.二维数组介绍

含义:
	数组中的元素依旧是数组的数组
分类:
	二维元素: 一维数组中的元素依然是一维数组
	三维元素
	四维元素
	...

2.二维数组初始化

声明:
	数据类型[][] 数组名; (推荐)
	数据类型 数组名[][];
	数据类型[] 数组名[];
初始化
	动态初始化
		格式1:
			数据类型[][] 数组名 = new 数据类型[x][y];
		格式2:
			数据类型[][] 数组名 = new 数据类型[x][];
	静态初始化
		格式:
			数据类型[][] 数组名 = {{N, N, N, ...}, {N, N, N, ...}, ...};

3.二维数组的元素访问和遍历

格式:
	数据类型[x][y]
	
解释:
	x: 元素所在一维数组在二维数组中的位置
	y: 元素在一维数组中的索引
	
例如:
	int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
	arr[0][0] = 1;
	arr[1][1] = 5;
	
遍历二维数组
for(int i = 0; i < arr.length; i++){
    for(int j = 0; j < arr[i].length; j++){
        System.out.print(arr[i][j] + " ");
    }
    System.out.println();
}


4.操作二维数组的注意点

操作二维数组不应使用常数来控制维数。具体方法是array.length表示行数,

array[row].length来表示row行的列数。这样当数组行数和列数不相等时,代码可以自动调整为正确的值。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:15:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:29:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码