二维数组与数组的排序

一、一维数组的排序

1. 冒泡排序

        冒泡排序是最常用的排序算法,算法重复的走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
        这个算法名字的由来是因为越大的元素会经由交换慢慢“浮”到数列顶端(升序排列)。

  • 代码实现:
    public static void main(String[] args) {
        int[] array = {1,5,9,3,7,4};		//定义数组array验证冒泡排序;
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }
    public static void bubbleSort(int[] array) {
        int temp = 0;
        for (int i = 0;i < array.length-1;i++) {    //i是比较的趟数;
            for (int j = 0;j <array.length-1-i;j++) {
                if (array[j] > array[j+1]) {
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    swap = true;
                }
            }
        }
    }
  • 运行结果:

在这里插入图片描述

  • 若文件的初始状态是乱序的,需要进行n-1趟排序,每趟排序要进行n-1次的比较,且每次比较都必须移动三次来达到交换记录位置,这种情况下,该算法的时间复杂度为O(n^2);

  • 若文件的初始状态是正序的,一趟扫描即可完成排序,所需的关键字的比较次数和记录移动次数均达到最小值,冒泡排序最好的情况下时间复杂度为O(n);

  • 优化后的算法:

    public static void bubbleSort(int[] array) {
        int temp = 0;
        boolean swap = false;
        for (int i = 0;i < array.length-1;i++) {    //i是比较的趟数;
            for (int j = 0;j <array.length-1-i;j++) {
                if (array[j] > array[j+1]) {
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    swap = true;
                }
            }
            if (!swap) {
                break;
            }
        }
    }
  • 算法稳定性:
            冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法
2. 直接插入排序

        直接插入排序的做法是:

  • 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
  • 第一趟比较前两个数,然后把第二个数按大小插入到有序表中;
  • 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。

        直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。

  • 基本思想
    每一趟将一个待排序的记录,按其关键字的大小插入到已经排好序的一组记录的适当位置上,直到所有待排序记录全部插入为止。

  • 代码实现:

    public static void main(String[] args) {
        int[] array = {1,5,9,3,7,4};		//定义数组array验证直接插入排序;
        insertSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void insertSort(int[] array) {
        int temp = 0;
        int j = 0;
        for (int i = 1;i < array.length;i++) {
            temp = array[i];		//temp在进入查找循环之前,保存array[i]的副本;
            for (j = i-1;j >= 0;j--) {
                if (array[j] > temp) {
                    array[j+1] = array[j];
                } else {
                    break;
                }
            }
            array[j+1] = temp;
        }
    }

  • 运行结果:

在这里插入图片描述

  • 直接插入排序的时间复杂度:O(n^2);
  • 算法稳定性:插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。比较是从有序序列的末尾开 始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相 等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的
3. 选择排序

        选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
        对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量temp来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量temp记住它在数组中的位置(下标),等到循环结束的时候,应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。

  • 代码实现:
	 public static void main(String[] args) {
        int[] array = {1,5,9,3,7,4};		//定义数组array验证直接插入排序;
        selectSort(array);
        System.out.println("选择排序: ");
        System.out.println(Arrays.toString(array));
    }
    public static void selectSort(int[] array) {
        int temp;
        for (int i = 0;i < array.length-1;i++) {
            for (int j = i+1;j < array.length;j++) {
                if (array[i] > array[j]) {
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
        }
    }
  • 运行结果:

在这里插入图片描述

  • 选择排序的时间复杂度:O(n^2);
  • 算法稳定性:选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么 交换后稳定性就被破坏了。所以选择排序不是一个稳定的排序算法

二、 二维数组

  1. 多维数组可以看成以数组为元素的数组,可以有二维,三维,甚至更多维数。
  • Java支持两种类型的多维数组:

1)等长数组:也称矩形数组,在二维矩形数组中,每一行都有相同的列数;
2)交错数组:即所谓的正交数组,变长数组,锯齿形数组。在二维矩形数组中,每一行可以有不同的列数;

  • 注意:交错数组比等长数组更灵活,但交错数组的创建和初始化更困难一点
  1. 二维数组的声明和初始化:
        //Java中多维数组的声明和初始化应按照从低维到高维的顺序进行
        类型名[][] 数组变量名 = new int[大小][大小];		//声明并创建一个二维数组;
        
        类型名[][] 数组变量名 = {初始值设定项};		//声明并初始化一个数组;
        
        类型名[][] 数组变量名 = new 类型[][]{初始值设定项};		//声明、创建并初始化一个数组;
        
        类型名[][] 数组变量名;
        数组变量名 = new 类型[大小][大小];		//先声明一个数组,然后使用new创建数组并赋值给数组;
        
        类型名[][] 数组变量名;
        数组变量名 = new 类型[][]{初始值设定项};		//先声明数组,然后创建数组并初始化、赋值给数组;

		类型名[][]数组变量名 = new 类型[大小][大小];
	    数组变量名[下标] = 初始值;		//声明并初始化数组,然后利用赋值语句初始化该实例;
  1. 二维数组的内存分配图:

在这里插入图片描述

  1. 二维数组的基本访问操作

二维数组可以理解为数组的数组:

  • 通过数组的length属性可以获取数组的长度,其基本形式:
数组变量名.length;		//返回“数组变量名”的元素个数;
数组变量名[下标].length;		//返回“数组变量名[下标]”(数组)的元素个数;
数组变量名[下标][下标].length;		//返回“数组变量名[下标][下标]"(数组)的元素个数;
  • 打印数组元素:

(1)for循环;

    public static void main(String[] args) {
    	System.out.println("用for循环打印数组元素:");
        int[][] array;
        array = new int[][]{{1,2,3},{4,5,6}};
        for (int i = 0;i < array.length;i++) {
            for (int j = 0;j < array[i].length;j++) {
                System.out.print (array[i][j] + " ");
            }
        }
    }

运行结果:

在这里插入图片描述

(2)foreach循环

  • foreach-foreach;
    public static void main(String[] args) {
        System.out.println("用foreach循环打印数组元素:");
        int[][] array;
        array = new int[][]{{1,2,3},{4,5,6}};
        for (int[] m : array) {
            for (int n : m) {
                System.out.print(n + " ");
            }
        }
    }

运行结果:

在这里插入图片描述

  • foreach-Arrays.toString;
    public static void main(String[] args) {
        System.out.println("用foreach循环打印数组元素:");
        int[][] array;
        array = new int[][]{{1,2,3},{4,5,6}};
        for (int[] m : array) {
            System.out.println(Arrays.toString(m));
        }
    }

运行结果:

在这里插入图片描述

(3)Arrays.deeptoString();

    public static void main(String[] args) {
    	System.out.println("调用Arrays.deeptoString()打印数组元素:");
        int[][] array;
        array = new int[][]{{1,2,3},{4,5,6}};
        System.out.println(Arrays.deepToString(array));
    }

运行结果:

在这里插入图片描述

  1. 二维数组的拷贝方式:
  • for循环;
  • clone;
  • System.arraycopy();
  • Arrays.copyOf();

用法跟一维数组的拷贝相同

三、打印三阶魔方阵

程序代码:

    public static void main(String[] args) {
        int[][] array = new int[3][3];
        //int Row = array.length;
        int x = 0;      //x,y为数组下标;
        int y = 1;
        array[x][y] = 1;
        for (int i = 2;i <= 9;i++) {     
            x = (x-1+3) % 3;     
            y = (y+1) % 3;
            if (array[x][y] != 0) {      
                x = (x+1+1) % 3;      
                y = (y-1+3) % 3;      
            }
            array[x][y] = i;
        }
        for (int i = 0;i < 3;i++) {
            for (int j = 0;j < 3;j++) {
                System.out.print(array[i][j] + "  ");
            }
            System.out.println();
        }
    }

运行结果:

在这里插入图片描述

四、打印奇数阶魔方阵

程序代码:

import java.util.Scanner;
public class test02 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入魔方阵的阶数: ");		//输入一个大与等于3奇数;
        int Row = scan.nextInt();
        System.out.println("=====================");
        int[][] array = new int[Row][Row];
        matrix(array,Row);
    }
    public static void matrix(int[][] array,int Row) {
        int x = 0;      //x,y为数组下标;
        int y = Row/2;
        array[x][y] = 1;
        for (int i = 2;i <= Row * Row;i++) {      // 将[2,Row^2],Row^2-1个数字放入数组array中;
            x = (x-1+Row) % Row;        //若x = (x-1) % Row,当x = 0时,数组越界;x = (x-1+Row) % Row使x始终大于0;
            y = (y+1) % Row;
            if (array[x][y] != 0) {         //若当前数字的上一行下一列的元素不为0,则将下一个数字放在当下数字的下一行;
                x = (x+1+1) % Row;      //因为在本次循环开始时已经改变了x,y的值,所以当进入if语句时应将x置为上次循环结束时的值,之后再做改变;
                y = (y-1+Row) % Row;        //
            }
            array[x][y] = i;
        }
        //打印矩阵;
        for (int i = 0;i < Row;i++) {
            for (int j = 0;j < Row;j++) {
                System.out.print(array[i][j] + "  ");
            }
            System.out.println();
        }
    }
}

运行结果:

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值