基于数组的常见算法

一、数组元素的赋值

练习题1:

        杨辉三角,是二项式系数在三角形中的一种几何排列。在欧洲,这个表叫做帕斯卡三角形。帕斯卡是在1654年发现这一规律的,比杨辉要迟393年,比贾宪迟600年。杨辉三角是中国古代数学的杰出研究成果之一,它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的数与形的结合 。

        使用二维数组打印一个 10 行杨辉三角。 
        【提示】
                1. 第一行有 1 个元素, 第 n 行有 n 个元素
                2. 每一行的第一个元素和最后一个元素都是 1
                3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
                yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

public class YangHuiTest {

    public static void main(String[] args) {
        // 1、声明并初始化二维数组
        int[][] yangHui = new int[10][];

        // 2、给数组的元素赋值
        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];

            // 给首末元素赋值
            yangHui[i][0] = yangHui[i][i] = 1;
            // 给每行的非首末元素赋值
            if(i > 1){
                for(int j = 1;j < yangHui[i].length - 1;j++){
                    yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
                }
            }
        }
        
        // 3、遍历二维数组
        for(int i = 0;i < yangHui.length;i++){
            for(int j = 0;j < yangHui[i].length;j++){
                System.out.print(yangHui[i][j] + "  ");
            }
            System.out.println();
        }
    }
}

练习题2:

        创建一个长度为6的int型数组,要求取值为1-30,同时元素值各不相同

public class ArrayRandom {
    public static void main(String[] args) {
        int[] arr = new int[6];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 30) + 1;

            for (int j = 0; j < i; j++) {
                if (arr[i] == arr[j]) {
                    i--;
                    break;
                }
            }
        }

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

二、数组元素的最大/最小值、平均数、总和

        定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,和值,平均值,并输出出来。
    
        要求:所有随机数都是两位数。

import java.util.Scanner;

public class ArrayOperation {
    public static void main(String[] args) {
        int[] arr = new int[10];

        // 随机10 - 99的整数
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * (100 - 10) + 10);
        }

        // 遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();

        // 求数组元素的最大值
        int maxValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (maxValue < arr[i]) {
                maxValue = arr[i];
            }
        }
        System.out.println("最大值为:" + maxValue);

        // 求数组元素的最小值
        int minValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (minValue > arr[i]) {
                minValue = arr[i];
            }
        }
        System.out.println("最小值为:" + minValue);

        // 求数组元素的总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);
        
        // 求数组元素的平均数
        int avgValue = sum / arr.length;
        System.out.println("平均数为:" + avgValue);
    }
}

三、数组复制

    使用简单数组
        (1)创建一个名为ArrayCopy的类,在main()方法中声明array1和array2两个变量,它们是int[]类型的数组。
        (2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        (3)显示array1的内容。
        (4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值 (如array[0]=0,array[2]=2)。打印出array1。
        思考:array1和array2是什么关系?

public class ArrayCopy {
    public static void main(String[] args) {  //alt + /
        int[] array1, array2;

        array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};

        //显示array1的内容
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }

        //赋值array2变量等于array1
        //不能称作数组的复制。
        array2 = array1;

        //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
        for (int i = 0; i < array2.length; i++) {
            if (i % 2 == 0) {
                array2[i] = i;
            }

        }
        System.out.println();

        //打印出array1
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }

        // array1和array2是什么关系?array1和array2地址值相同,都指向了堆空间的唯一的一个数组实体。
    }
}

解析:

         拓展:修改题目,实现array2对array1数组的复制

public class ArrayCopy {
    public static void main(String[] args) {  //alt + /
        int[] array1, array2;

        array1 = new int[]{2, 3, 5, 7, 11, 13, 17, 19};

        //显示array1的内容
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }

        //数组的复制:
        array2 = new int[array1.length];
        for (int i = 0; i < array2.length; i++) {
            array2[i] = array1[i];
        }


        //修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)
        for (int i = 0; i < array2.length; i++) {
            if (i % 2 == 0) {
                array2[i] = i;
            }

        }
        System.out.println();
        //打印出array1
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

 四、数组反转

        把如下数组进行反转:
        String arr[] = new String[]{"AA","BB","CC","DD","EE","FF","GG"};

public class ArrayReverse01 {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        for (int i = 0; i < arr.length / 2; i++) {
            String temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}
public class ArrayReverse02 {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
            String temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

五、数组查找

5.1 线性查找

        线性查找又叫顺序查找,就是遍历整个列表,逐个元素与给定值比较,若某个元素和给定值相等,则查找成功。如果直到最后一个元素和给定值比较都不相等,则查找失败。

public class ArraySequentialSearch {
    public static void main(String[] args) {
        String arr[] = new String[]{"AA", "BB", "CC", "DD", "EE", "FF", "GG"};

        String findStr = "BB";
        findStr = "QQ";

        boolean isFlag = true;

        for(int i = 0;i < arr.length;i++){
            if(findStr.equals(arr[i])){
                System.out.println("找到了指定的元素,位置为:" + i);
                isFlag = false;
                break;
            }
        }
        if(isFlag){
            System.out.println("很遗憾,没有找到你要查询的元素!");
        }
    }
}

5.2 二分查找

        什么是二分查找呢?二分查找的基本思想是:在有序表中,取中间元素作为比较对象,若给定值与中间元素相等,则查找成功;若给定值小于中间元素,则在中间元素的左半区继续查找;若给定值大于中间元素,则在中间元素的右半区继续查找。不断重复上述过程,直到找到为止。

        从二分查找的定义我们可以看出,使用二分查找有两个前提条件:
        (1)待查找的列表必须有序。
        (2)必须使用线性表的顺序存储结构来存储数据。

        接下来我们来介绍一下折半查找的原理,并自己用代码实现折半查找。

在查找前对数组进行折半操作 (初始化指针位置)

        折半公式 =  (最大索引+最小索引)/ 2

        首先我们可以利用指针思想,假设有一个指针指向最大值(MAX),有一个指针指向最小值(MIN),还有一个指针指向的是最大值和最小值之间的索引(MID)。我把这个过程称为初始化指针位置.

 折半后的指针索引和被查找元素比较

        若被查找元素的值(12)大于中间索引上的值(10),我们就把最小值指针(MIN)移动到中间指针(MID)索引的下一个索引位置,如下图:

 若没有匹配到就继续折半后的指针索引和被查找元素比较。

         若被查找元素的值(12)小于中间索引上的值(15),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:

 若没有匹配到就继续折半后的指针索引和被查找元素比较

        若被查找元素的值(12)小于中间索引上的值(13),我们就把最大值指针(MAX)移动到中间指针(MID)索引的上一个索引位置,如下图:

 若没有匹配到就继续折半后的指针索引和被查找元素比较。

        当小指针(MIN)的索引(4)超过了大指针(MAX)的索引(3)时,就需要停止查找了,如果真有这种情况发生,说明没有查到被查找元素的值(12),此时会返回一个负数(-1),当然如果查找到了就返回其在数组中的索引即可。

 数组的折半查找代码实现

public class ArrayBinarySearch {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 4, 7, 10, 13, 15, 21, 25};

        int findNum = 21;

        // 初始的最小索引
        int min = 0;

        // 初始的末索引
        int max = arr.length - 1;

        boolean isFlag = true;
        while (min <= max) {

            int mid = (min + max) / 2;

            if (findNum == arr[mid]) {
                System.out.println("找到了指定的元素,位置为:" + mid);
                isFlag = false;
                break;
            } else if (arr[mid] > findNum) {
                max = mid - 1;
            } else {//arr[middle] < findNum
                min = mid + 1;
            }
        }

        if (isFlag) {
            System.out.println("很遗憾,没有找到你要查询的元素!");
        }
    }
}

六、数组排序

6.1 冒泡排序

冒泡概述

        冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

        它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

        这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

实现原理

        1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 
        2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。  
        3.针对所有的元素重复以上的步骤,除了最后一个。  
        4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

实现思路

        (1)第一次比较:首先比较第一和第二个数,将小数放在前面,将大数放在后面。

        (2)比较第2和第3个数,将小数 放在前面,大数放在后面。

    ......

        (3)如此继续,知道比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成

        (4)在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。

        (5)在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。

        (6)依次类推,每一趟比较次数减少依次

 实例解析

        排序数组:[10,1,35,61,89,36,55]

冒泡代码

/*
* 使用冒泡排序实现升序排列
* 冒泡排序(升序)的原理:
* 	两两比较,如果前面的值比后面的值大,则交换位置
* 	外层i	0		1		2		3		4
* 原数组	第一轮	第二轮	第三轮	第四轮	第五轮	外层循环5次     arr.length-1   6 - 1
* 98		78		56		44		23		6
* 78		56		44		23		6		23
* 56		44		23		6		44		44
* 44		23		6		56		56		56
* 23		6		78		78		78		78
* 6		98		98		98		98		98
* 					
* 次数		5		4		3		2		1	
* 内层		arr.length-1-i	
* 第一轮得到一个最大值,这个最大值 
* 1.外层循环初始变量i为0,判断依据 i < arr.length - 1
* 2.内存循环初始边框j为0,判断依据 j < arr.length - i - 1
* 3.判断谁大或谁小,然后交换位置
*/
int arr[] = {32,5,100,9,78,1};
for(int i = 0;i < arr.length - 1;i++) { //用来决定轮数  5
    for(int j = 0; j < arr.length - i -1;j++) { //用来决定每轮比较的次数
        if(arr[j] > arr[j+1]) {
            //temp保存哪个值无所谓,但是保存哪个值,就要先给哪个值赋值
            int temp = arr[j+1];
            arr[j+1] = arr[j];
            arr[j] = temp;
        }
    }
}
System.out.println("冒泡升序排列之后:"+Arrays.toString(arr));

6.2 选择排序

        选择排序(Selection sort)是一种简单直观的排序算法。
    
        它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

 实例解析

        第1趟比较:拿第1个元素依次和它后面的每个元素进行比较,如果第1个元素大于后面某个元素,交换它们,经过第1趟比较,数组中最小的元素被选出,它被排在第一位
    
        第2趟比较:拿第2个元素依次和它后面的每个元素进行比较,如果第2个元素大于后面某个元素,交换它们,经过第2趟比较,数组中第2小的元素被选出,它被排在第二位
    
        ......
    
        第n-1趟比较:第n-1个元素和第n个元素作比较,如果第n-1个元素大于第n个元素,交换它们.

选择代码

/*
* 选择排序 - 升序排列:
* 	使用指定位置的值,跟所有的值进行比较;如果前面的值大于后面的值,则交换位置
* 
* 外层循环变量 0		1		2		3	
* 原数组	第一轮	第二轮	第三轮	第四轮		比较了四次,外层循环	arr.length - 1
* 120		10		10		10		10
* 89		120		18		18		18
* 32		89		120		32		32
* 18		32		89		120		89
* 10		18		32		89		120
* 
* 次数		4		3		2		1		看似: arr.length - i - 1
* 
* 1. 外层循环初始变量i为0,小于arr.length - 1
* 2. 内层循环初始变量j为i,小于arr.length - 1
* 		j = 0		< 4
* 		j = 1		< 4
* 		j = 2		< 4
*/
int arr[] = {32,2,78,6,44,100};
for(int i = 0;i < arr.length - 1;i++) {
    for(int j = i; j < arr.length - 1;j++) {
        /*
		* i = 0  arr[i] = 2
		* j = 0  32  2 --> 2 arr[j+1] = 32
		*/
        if(arr[i] > arr[j+1]) {
            int temp = arr[j+1];
            arr[j+1] = arr[i];
            arr[i] = temp;
        }
    }
}
System.out.println("选择排序之后的数组:"+Arrays.toString(arr));

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是波哩个波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值