算法分析与设计——检索算法的实现 Java实现:能够人工输入或随机产生一个长度为n的整数数组,要求数组任意两个元素都互不相同

1、设计一个交互界面(例如菜单)供用户选择,如果可能,最好是一个图形化用户界面;
2、能够人工输入或随机产生一个长度为n的整数数组,要求数组任意两个元素都互不相同;
3、设计一个算法判断要求2中产生的整数数组是否为或未排序(输出0)、升序(输出1)、降序(输出2)、先升后降(输出3)、或先降后升(输出4)状态;
4、给定某具体元素,使用顺序检索算法判断该具体元素是否出现在要求2中产生的数组中,并统计关键字比较的次数;
5、给定某具体元素,使用二分检索算法判断该具体元素是否出现在要求2中产生的升序或降序的数组中,并统计关键字比较的次数;
6、给定某具体元素,使用三分检索算法判断该具体元素是否出现在要求2中产生的升序或降序的数组中,并统计关键字比较的次数;
7、给定先升后降(或先降后升)数组,使用二分检索思路查找该数组的最大值(或最小值)。

import java.util.Random;
import java.util.Scanner;
/*
 * @author gfh
 *@Time 2021-10-28
 * 本代码仅作为学习交流使用
 * */
public class Retrieval {
    //自动创建数组
    public static int[] randomArray(int min, int max, int n) {
        int len = max - min + 1;

        if (max < min || n > len) {
            return null;
        }

        //初始化给定范围的待选数组
        int[] source = new int[len];
        for (int i = min; i < min + len; i++) {
            source[i - min] = i;
        }

        int[] result = new int[n];
        Random rd = new Random();
        int index = 0;
        for (int i = 0; i < result.length; i++) {
            //待选数组0到(len-2)随机一个下标
            index = Math.abs(rd.nextInt() % len--);
            //将随机到的数放入结果集
            result[i] = source[index];
            //将待选数组中被随机到的数,用待选数组(len-1)下标对应的数替换
            source[index] = source[len];
        }
        return result;
    }
    //手动创建数组
    public static int[] artificialArray(int n) {
        int[] result = new int[n];
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < n; i++) {
            System.out.println("请输入数组的第" + (i + 1) + "的值:");
            result[i] = sc.nextInt();
        }
        return result;

    }
    //判断数组是否为升序
    public static boolean isUpSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                return false;
            }
        }
        return true;
    }
    //判断数组是否为降序
    public static boolean isDownSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] < array[i + 1]) {
                return false;
            }
        }
        return true;
    }
    //得到数组最大值下标
    public static int getMaxIndex(int[] arr) {//得到数组最大值的下标
        int max = arr[0];
        int max_index = 0;
        for (int x = 1; x < arr.length; x++) {//注意这里不要越界
            if (arr[x] > max) {
                max = arr[x];
                max_index = x;
            }
        }
        return max_index;
    }
    //得到数组最小值下标
    public static int getMinIndex(int[] arr) {//得到数组最小值的下标
        int min = arr[0];
        int min_index = 0;
        for (int x = 1; x < arr.length; x++) {//注意这里不要越界
            if (arr[x] < min) {
                min = arr[x];
                min_index = x;
            }
        }
        return min_index;
    }
    //判断数组为何种类型算法
    public static int arraySortAlgorithm(int[] arr) {
        int result = 0;//乱码序号
        int maxIndex = getMaxIndex(arr);//得到最大值数组下标
        int minIndex = getMinIndex(arr);//得到最小值数组下标
        if (maxIndex == arr.length - 1 && minIndex == 0) {
            if (isUpSort(arr)) {
                System.out.println("为升序数组");
                result = 1;
            } else {
                System.out.println("为乱序数组");
            }
        } else if (maxIndex == 0 && minIndex == arr.length - 1) {
            if (isDownSort(arr)) {
                System.out.println("为降序数组");
                result = 2;
            } else {
                System.out.println("为乱序数组");
            }
        } else if (0 < minIndex && minIndex < arr.length - 1) {
            int[] downArr = new int[minIndex + 1];
            for (int i = 0; i < minIndex + 1; i++) {
                downArr[i] = arr[i];
            }
            int[] upArr = new int[arr.length - minIndex];
            for (int i = 0; i < arr.length - minIndex; i++) {
                upArr[i] = arr[minIndex + i];
            }
            if (isDownSort(downArr) && isUpSort(upArr)) {
                System.out.println("为先降序后升序数组");
                result = 3;
            } else {
                System.out.println("为乱序数组");
            }
        } else if (0 < maxIndex && maxIndex < arr.length - 1) {
            int[] upArr = new int[maxIndex + 1];
            for (int i = 0; i < maxIndex + 1; i++) {
                upArr[i] = arr[i];
            }
            int[] downArr = new int[arr.length - maxIndex];
            for (int i = 0; i < arr.length - maxIndex; i++) {
                downArr[i] = arr[maxIndex + i];
            }
            if (isDownSort(downArr) && isUpSort(upArr)) {
                System.out.println("为先升序后降序数组");
                result = 4;
            } else {
                System.out.println("为乱序数组");
            }
        }
        else {
            System.out.println("为乱序数组");
        }
        return result;
    }
    //顺组检索
    public static int arrayOrderSearch(int[] arr,int tag){
        for (int i = 0; i <arr.length ; i++) {
            if (arr[i]==tag){
                System.out.println("该数组中存在目标元素");
                return i+1;//返回匹配次数
            }
        }
        System.out.println("该数组中无目标元素");
        return arr.length;
    }
    //创建数组
    public static int[] arrayCreate(){
        Scanner s = new Scanner(System.in);
        System.out.println("请选择 1、随机生成数组 2、手动生成数组");
        int chose = s.nextInt();
        if(chose==1){
            System.out.println("请输入生成随机数组的长度n:");
            int n = s.nextInt();
            System.out.println("请输入随机范围的下限:");
            int min = s.nextInt();
            System.out.println("请输入随机范围的上限:");
            int max = s.nextInt();
            int[] result = randomArray(min, max, n);
            return result;
        }
        else if (chose==2){
            System.out.println("请输入手动生成数组的长度n:");
            int n = s.nextInt();
            int[] result = artificialArray(n);
            return result;
        }
        else {
            System.out.println("输入错误");
        }
        return null;
    }
    //二分检索升、降序数组
    public static int arrayBinarySearch(int[] arr, int tag) {
        int i = 0;
        int low = 0;
        int high = arr.length - 1;
        int middle = 0;            //定义middle
        if (isUpSort(arr)) {
            if (tag < arr[low] || tag > arr[high]) {
                System.out.println("目标元素没有出现在该数组中");
                return 0;
            }
            while (low <= high) {
                middle = (low + high) / 2;
                ++i;
                if (arr[middle] > tag) {
                    high = middle - 1;
                } else if (arr[middle] < tag) {
                    low = middle + 1;
                } else if (arr[middle]==tag){
                    System.out.println("目标元素出现在该数组中");
                    return i + 2;
                }
            }
        } else if (isDownSort(arr)) {
            if (tag > arr[low] || tag < arr[high]) {
                System.out.println("目标元素没有出现在该数组中");
                return 0;
            }
            while (low >= high) {
                middle = (low + high) / 2;
                ++i;
                if (arr[middle] < tag) {
                    high = middle - 1;
                } else if (arr[middle] > tag) {
                    low = middle + 1;
                } else if (arr[middle]==tag){
                    System.out.println("目标元素出现在该数组中");
                    return i + 2;
                }
            }
        } else {
            System.out.println("该数组不符合升序或降序要求");
            return -1;
        }
        System.out.println("目标元素不在数组当中");
        return i+2;
    }
    //三分检索升、降序数组
    public static int arrayTernarySearch(int[] arr,int tag){
        int i = 0;
        int left = 0;
        int right = arr.length - 1;
        if (isUpSort(arr)) {
            if (tag < arr[left] || tag > arr[right]) {
                System.out.println("目标元素没有出现在该数组中");
                return 0;
            }
            while (left < right) {
                int midl = left + (right - left) / 3;
                int midr = right - (right - left) / 3;

                i++;
                if (arr[midl] > tag) {
                    right = midl - 1;
                } else if (arr[midr] < tag) {
                    left = midr + 1;
                } else {
                    System.out.println("目标元素出现在该数组中");
                    return i + 2;
                }

            }
        } else if (isDownSort(arr)) {
            if (tag > arr[left] || tag < arr[right]) {
                System.out.println("目标元素没有出现在该数组中");
                return 0;
            }
            while (left < right) {
                int midl = left + (right - left) / 3;
                int midr = right - (right - left) / 3;

                i++;
                if (arr[midl] < tag) {
                    right = midl - 1;
                } else if (arr[midr] > tag) {
                    left = midr + 1;
                } else {
                    System.out.println("目标元素出现在该数组中");
                    return i + 2;
                }

            }

        } else {
            System.out.println("该数组不符合升序或降序要求");
            return -1;
        }
        return -1;
    }
    //二分检索求先升后降数组最大值
    public static int arrayUptoDownBinarySearchMax(int[] arr){
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) {
                return arr[mid];
            } else if (arr[mid] < arr[mid - 1]) {
                right = mid - 1;
            } else if (arr[mid] < arr[mid + 1]) {
                left = mid + 1;
            }
        }
        return -1;
    }
    //二分检索求先降后升数组最小值
    public static int arrayDowntoUpBinarySearchMin(int[] arr){
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
                return arr[mid];
            } else if (arr[mid] > arr[mid - 1]) {
                right = mid - 1;
            } else if (arr[mid] > arr[mid + 1]) {
                left = mid + 1;
            }
        }
        return -1;
    }
    //主函数
    public static void main(String[] args) {
        int con = 1;
        int[] result = arrayCreate();
        Scanner s = new Scanner(System.in);
        System.out.println("请输入检索目标元素");
        int tag = s.nextInt();
        do {
            System.out.println("1、判断数组类型");
            System.out.println("2、顺序查找目标元素");
            System.out.println("3、二分法查找目标元素");
            System.out.println("4、三分法查找目标元素");
            System.out.println("5、二分法先升后降数组找最大值");
            System.out.println("6、二分法先降后升数组找最小值");
            int chose =s.nextInt();
            switch (chose){
                case 1:
                    System.out.println(arraySortAlgorithm(result));
                    break;
                case 2:
                    System.out.println("顺序查找目标元素次数为:"+arrayOrderSearch(result, tag));
                    break;
                case 3:
                    System.out.println("二分法查找目标元素次数为:"+arrayBinarySearch(result, tag));
                    break;
                case 4:
                    System.out.println("三分法查找目标元素次数为:"+arrayTernarySearch(result, tag));
                    break;
                case 5:
                    System.out.println("二分法先升后降数组找最大值为:"+arrayUptoDownBinarySearchMax(result));
                    break;
                case 6:
                    System.out.println("二分法先降后升数组找最小值为:"+arrayDowntoUpBinarySearchMin(result));
                    break;
            }
            System.out.println("是否返回首页?(1是,0退出程序)");
            con=s.nextInt();
        } while (con == 1);
    }
}


判断数组为升序、降序、升序to降序、降序to升序核心思想:
升序、降序没什么好说的for循环匹配就可以了,代码主要是用后一个元素比前一个元素大(小)来判断,是否单调递增(减),主要还是聊一聊先升后降和先降后升。
核心思想:
算法分析与设计——检索算法的实现 Java实现:能够人工输入或随机产生一个长度为n的整数数组,要求数组任意两个元素都互不相同_第1张图片
由此可以先得到数组的最大和最小值,此时需要约束判断该数组的大致走向
1:最大值在数组首尾之间,大致走向为先升后降

if (0 < maxIndex && maxIndex < arr.length - 1)

2:最小值在数组首尾之间,大致走向为先降后升

if (0 < minIndex && minIndex < arr.length - 1)

之后以最大值(最小值)为轴将数组切开,分段来判断。如果两个分段都为单调递增(递减),则可以判断为符合条件,反之可判断为乱序数组

“======================================================”
更新一下排序算法

    //判断数组是否为升序
    public static boolean isUpSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                return false;
            }
        }
        return true;
    }

    //判断数组是否为降序
    public static boolean isDownSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] < array[i + 1]) {
                return false;
            }
        }
        return true;
    }

    //判断数组是否为升、降、先升后降、先降后生
    public static int arraySortAlgorithm(int[] arr) {
        if (isUpSort(arr)) {//判断升序
            return 1;
        }
        if (isDownSort(arr)) {//判断降序
            return 2;
        }
        int flag = 1;
        for (int i1 = 0; i1 < arr.length - 1; i1++) {
            if (flag == 1 && arr[i1] > arr[i1 + 1]) {
                flag = 3;
            }
            if (flag == 3 && arr[i1] < arr[i1 + 1]) {
                flag = 0;
            }
        }
        if (flag == 3) {
            return flag;
        }
        int flag2 = 1;
        for (int i1 = 0; i1 < arr.length - 1; i1++) {
            if (flag2 == 1 && arr[i1] < arr[i1 + 1]) {
                flag2 = 4;
            }
            if (flag2 == 4 && arr[i1] > arr[i1 + 1]) {
                flag2 = 0;
            }
        }
        return flag2;
    }

优化了算法检索,设置了flag——符号位判断,如果该数组符号位只变一次,则表明该数组为先升后降或先降后升否则为乱序数组,其次修改了比较次数的计数,只返回核心比较次数。
在这里插入图片描述
之前为+2,现减去两次比较只保留核心比较次数

你可能感兴趣的:(算法,排序算法,数据结构)