基数排序、查找算法

排序

基数排序

介绍:
在这里插入图片描述
基本思想:
在这里插入图片描述

代码:

package 排序算法.基数排序;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class _基数排序_ {
    public static void main(String[] args) {
//        int[]arr = {53, 3, 542, 748, 14, 214};
//        radixSort(arr);
//        System.out.println(Arrays.toString(arr));

        int[] arr = new int[80000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random()*80000);
        }

        Date date1 = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ss HH:mm:ss");

        String str1 = sdf.format(date1);
        System.out.println(str1);

        radixSort(arr);

        Date date2 = new Date();
        String str2 = sdf.format(date2);
        System.out.println(str2);
    }

    public static void radixSort(int []arr){
        // 求出最大的数据 求出几位数
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(max<arr[i]){
                max = arr[i];
            }
        }

        int maxLength = (max+"").length();

        // 定义数组
        int [][]bucketArray = new int[10][arr.length];// 桶里的数剧
        int []bucketOfcounts = new int[10];// 每个桶实际有多少个数据

        // 桶排序实现maxLength次数
        for (int i = 0,n = 1; i < maxLength; i++,n*=10) {
            // 进行每一次的桶排序,不同位数的排序
            for (int j = 0; j < arr.length; j++) {
                int val = arr[j]/n%10;// 取出相应位置上的数据把他放在对应的桶里面

                bucketArray[val][bucketOfcounts[val]] = arr[j];
                bucketOfcounts[val] ++;// 放入一个数据之后就相应的统计桶里面实际的元素的个数

            }

            // 在桶里面放完数据之后吧这些数据放回到原来的数组中
            int cnt = 0;
            for(int k=0;k< bucketOfcounts.length;k++){
                if(bucketOfcounts[k]!=0){
                    for (int l = 0; l < bucketOfcounts[k]; l++) {
                        arr[cnt++] = bucketArray[k][l];
                    }
                }
                bucketOfcounts[k] = 0; // 放完之后对下一轮排序做准备
            }
        }
    }

    public static void radixSortOfTest(int[]arr){
        // 定义二维数组表示十个桶
        // 包含了十个一维数组,每个一维数组就是一个桶,为了防止放数的时候桶溢出,大小是arr.length
        int [][]bucket = new int[10][arr.length];

        // 为了记录每个桶中实际放了多少的数据,我们定义一维数组来记录每次放入数据的个数
        int []bucketElementCounts = new int[10];

        for (int i = 0; i < arr.length; i++) {

            for(int j = 0;j<arr.length;j++){
                // 取出每个元素的个位
                int digitOfElement = arr[j]/10%10;
                // 放入到对于的桶中,记录放入的个数
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
                bucketElementCounts[digitOfElement]++;
            }

            int index = 0;
            // 遍历每一个桶,将桶中数据放入原数组
            for(int k = 0;k<bucketElementCounts.length;k++){
                // 如果桶中有数据,我们放入到原数组
                if(bucketElementCounts[k]!=0){
                    // 循环改桶即第k个桶 ,放入
                    for(int l = 0;l<bucketElementCounts[k];l++){
                        arr[index++] = bucket[k][l];
                    }
                }

            }

            System.out.println("第一轮对个位的排序结束");
            System.out.println(Arrays.toString(arr));

        }

    }
}


总结:
在这里插入图片描述

排序算法时间复杂度比较

在这里插入图片描述

相关术语解释:

  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
  • 不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
  • 内排序:所有排序操作都在内存中完成;
  • 外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
  • 时间复杂度: 一个算法执行所耗费的时间。
  • 空间复杂度:运行完一个程序所需内存的大小。
  • n: 数据规模
  • k: “桶”的个数
  • In-place: 不占用额外内存
  • Out-place: 占用额外内存

查找算法

线性查找

二分查找

思路:
在这里插入图片描述
代码:

package 查找算法;

import java.util.ArrayList;
import java.util.List;

// 使用二分查找的前提是数组是有序的

public class _二分查找_ {
    public static void main(String[] args) {
        int arr[] = {1,8, 10, 89, 1000, 1000,1234};

        ArrayList<Integer> arrayList= binarySearch(arr,0,arr.length-1,1000);
        System.out.println(arrayList);

    }

    /**
     *
     * @param arr       数组
     * @param left      左边的索引
     * @param right     右边的索引
     * @param findVal   要找的值
     * @return 如果找到返回下标 没有找到返回-1
     */
    public static ArrayList<Integer> binarySearch(int[]arr, int left, int right, int findVal){
        if(left>right){
            return new ArrayList<>();
        }

        int mid = (left+right)/2;
        int midVal = arr[mid];

        if(findVal > midVal){
            return binarySearch(arr,mid+1,right,findVal);
        }else if(findVal < midVal){
            return binarySearch(arr,left,mid-1,findVal);
        }else {
//            return mid;
//            如果要找到所有的值,我们先不返回,将这些下标放到arrayList中 ,然后向做左、右扫描,返回ArrayList
            ArrayList<Integer> resIndexlist = new ArrayList<>();
            // 往左边找
            int temp = mid - 1;
            while(true){
                if(temp<0||arr[temp] != findVal){
                    break;
                }
                resIndexlist.add(temp);
                temp -= 1;
            }

            // 往右边找
            temp = mid+1;
            while(true){
                if(temp>arr.length-1||arr[temp] != findVal){
                    break;
                }
                resIndexlist.add(temp);
                temp += 1;
            }

            resIndexlist.add(mid);
            return resIndexlist;
        }
    }


}

插值查找

思路:
在这里插入图片描述
key

代码:

package 查找算法;

import java.util.Arrays;

//要求数组是有序的  比较紧的连续值
public class _插值查找_ {
    public static void main(String[] args) {
        int []arr = new int[100];
        for (int i = 0; i < 100; i++) {
            arr[i] = i+1;
        }

        int index = InsertSearch(arr,0,arr.length-1,10);
        System.out.println(index);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 要求数组是有序的  比较紧的连续值
     * @param arr         数组
     * @param left        左边下标
     * @param right       右边下标
     * @param findVal     要找的值
     * @return
     */
    public static int InsertSearch(int[]arr,int left,int right,int findVal){
        if(left>right||findVal<arr[0]||findVal>arr[arr.length-1]){
            return -1;
        }

        // 求出mid
        int mid = left + (right - left)*(findVal - arr[left]) / (arr[right] - arr[left]);
        int midVal = arr[mid];
        // 往右边找
        if(findVal>midVal){
            return InsertSearch(arr,mid+1,right,findVal);
        }else if(findVal<midVal){
            return InsertSearch(arr,left, mid-1,findVal);
        }else{
            return mid;
        }
    }
}

斐波那契查找

思路:

在这里插入图片描述

原理:
在这里插入图片描述
其中的n值是任意的,意味着任何的数组都能找到对应的斐波那契数组

斐波那契查找的整个过程可以分为:
1.构建斐波那契数列;
2.计算数组长度对应的斐波那契数列元素个数;
3.对数组进行填充;
4.循环进行区间分割,查找中间值;
5.判断中间值和目标值的关系,确定更新策略;

代码实现:

package 查找算法;

import java.util.Arrays;

// 非递归实现法
public class _斐波那契查找_ {
    public static int maxSize = 20;
    public static void main(String[] args) {
        int []arr = {1,8, 10, 89, 1000, 1234};

        System.out.println(fibSearch(arr,1));

    }

    // 需要菲波那切数列 mid = low + f[k-1]-1;
    public static int[] fibo(){
        int f[] = new int[maxSize];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < maxSize; i++) {
            f[i] =  f[i-1] + f[i-2];
        }
        return f;
    }

    /**
     *
     * @param arr
     * @param findVal  要找的关键码值
     * @return 返回下标,没有-1
     */
    public static int fibSearch(int []arr,int findVal){
        int low = 0;
        int high = arr.length-1;

        int k = 0;//表示斐波那契分割数值的下标
        int mid = 0;// 存放mid值
        int f[] = fibo();// 获取斐波那契数列
        // 获取到斐波那契数列分割的下标
        // 就是找到最近的fibonacci序列代表的元素的个数,如果比arr.length大我们就填充
        while(high>f[k]-1){
            k++;
        }

        // f[k] 对应的值不一定和数组大小相同
        // 因为f[k]值可能大于a的长度,我们需要使用Arrays类,构造一个新的数组,并指向a[]
        // 不足的部分是用0填充
        int []temp = Arrays.copyOf(arr,f[k]); // 原来的数组 数组长度
        System.out.println(Arrays.toString(temp));
        // 实际上使用a数组最后的数填充temp
        for (int i = arr.length; i < temp.length; i++) {
            temp[i] = arr[high];
        }
        System.out.println(Arrays.toString(temp));

        // 使用while来循环处理,找到我们的key
        while(low<=high){
            mid = low +  f[k-1] -1;
            if(findVal<temp[mid]){// 我们应该向数组前面找
                high = mid-1;
                // 前面的数组长度是f[k-1] 为下次的划分做准备
                k--;
            }else if(findVal>temp[mid]){
                low = mid+1;
                // 后面的数组长度是f[n-2]  为下次的划分做准备
                k-=2;

            }else{// 找到,确定返回那个下标
                // 可能会出现这个下标大于原来的长度
                if(mid>arr.length){
                    return arr.length-1;
                }else{
                    return mid;
                }
            }
        }
        return -1;
    }
}

哈希表

使用场景

在缓冲区临时保存需要查找的区域

例如:
在这里插入图片描述
基本介绍:
在这里插入图片描述
案例简单实现:

package 哈希表;

import java.util.Arrays;
import java.util.Scanner;

public class _哈希表_ {
    public static void main(String[] args) {
        HashTable hashTable = new HashTable(7);

        String key = "";
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("add:添加雇员");
            System.out.println("show:显示雇员");
            System.out.println("find:查找雇员");
            System.out.println("exit:退出系统");

            key = scanner.next();
            switch (key){
                case "add":
                    System.out.println("输入id");
                    int id = scanner.nextInt();
                    System.out.println("输入年龄");
                    int age = scanner.nextInt();
                    System.out.println("输入名字");
                    String name = scanner.next();
                    Emp emp = new Emp(id,age,name);
                    hashTable.addEmp(emp);
                    break;
                case "find":
                    System.out.println("输入id");
                    int id1 = scanner.nextInt();
                    hashTable.findEmpById(id1);
                    break;
                case "exit":
                    scanner.close();
                    System.exit(-1);
                case "show":
                    hashTable.listAllEmp();
                    break;
                default:
                    break;
            }
        }

    }
}



// 表示雇员
class Emp{
    public int id;
    public int age;
    public String name;
    public Emp next;
    public Emp(int id ,int age,String name){
        super();
        this.id = id;
        this.age = age;
        this.name = name;
    }

}


// 表示链表
class EmpLinkedList{
    public Emp head;

    public void add(Emp emp){
        if(head == null){
            head = emp;
            return;
        }
        // 不考虑添加问题  ,直接加到最后
        Emp curEmp = head;
        while(true){
            if(curEmp.next == null){
                break;
            }
            curEmp = curEmp.next;
        }
        curEmp.next = emp;
        return;
    }

    public void list(int i){
        if(head==null){
            System.out.printf("这个链表%d是空的~~\n",i);
            return;
        }
        Emp curEmp = head;

        while(true){
            System.out.printf("===>第%d条链表,这个员工是%s,%d \n",i,curEmp.name,curEmp.age);
            if(curEmp.next==null){
                break;
            }
            curEmp = curEmp.next;
        }
    }

    // 根据id查找雇员
    public Emp findEmpById(int id){
        if(head==null){
            System.out.println("链表空");
        }
        Emp curEmp = head;
        while(true){
            if(curEmp.id == id){
                return curEmp;
            }
            curEmp = curEmp.next;
            if(curEmp==null){
                break;
            }
        }
        return null;
    }
}

//创建哈希表
class HashTable{
    private EmpLinkedList[] empLinkedListsArray;
    private int size;

    public HashTable(int size){
        this.size = size;
        empLinkedListsArray = new EmpLinkedList[size];
        // 还需要初始化每一个链表
        for (int i = 0; i < size; i++) {
            empLinkedListsArray[i] = new EmpLinkedList();
        }
    }

    // 添加雇员
    public void addEmp(Emp emp){
        int EmpLinkedListsIndex = hashFun(emp.id);
        empLinkedListsArray[EmpLinkedListsIndex].add(emp);
    }

    // 遍历
    public void listAllEmp(){
        for (int i = 0; i < size; i++) {
            empLinkedListsArray[i].list(i);
        }
    }

    // 查找
    public void findEmpById(int id){
        int index =hashFun(id);
        Emp emp = empLinkedListsArray[index].findEmpById(id);
        if(emp!=null){
            System.out.printf("找到了第%d条链表,名字是%s\n",id,emp.name);
            return;
        }
        System.out.println("没找到");
    }


    //散列函数
    public int hashFun(int id){
        return id % size;
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值