栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

数据结构基础(笔记)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构基础(笔记)

一、线性查找法

查找一个元素是否存在在数组中

输入:数组、目标元素

输出:目标元素所在的索引,若不存在返回-1

public class xianXingChaZhao {
    private xianXingChaZhao(){}         
    //将构造函数私有化,其他类访问这个类时就不能new一个对象,用户就无法创造这个类的对象
    public static int search(int[] data,int muBiao){ 
        for(int i=0;i< data.length;i++){
            if(data[i]==muBiao)
                return i;
        }
        return -1;
    }//静态方法 不需要new一个对象,直接用 类名.方法名即可调用
    public static void main(String[] args){
        int data[]={24,18,12,9,16,66,32,4};
        int muBiao=16;
        xianXingChaZhao xxcz=new xianXingChaZhao();     
        //虽然将构造函数私有化了,但这个main函数是这个类里的,所以还能访问private
        int res = xianXingChaZhao.search(data,muBiao);  
        //静态方法 直接用类名调用(用普通方法new一个对象也可)
        System.out.println(res);
        int result=xianXingChaZhao.search(data,25);
        System.out.println(result);

    }

}

使用泛型修改

public class xxczfx {
    private  xxczfx(){}
    public static  int search(E[] data,E target){    //泛型参数也是泛型E
        for(int i=0;i< data.length;i++){    //循环不变量  data[0,i)中没有找到目标
            //data[i]是类对象,target也是类对象,判断他俩相等不能用==,得用equals
            if(data[i].equals(target))
                return i;
        }//循环体:维持循环不变量(证明算法正确性)
        return -1;
    }
}

自己定义一个测试类Student

public class Student {
    private String name;
    public Student(String name){
        this.name=name;
    }
    @Override
    public boolean equals(Object student){    //覆盖Object父类中的equals方法
       //看调用equals函数的那个对象和参数里的那个对象是否是一个对象,如果是,直接返回true 相等
        if(this == student)     
            return true;
       //看参数传来的对象是否是空对象,如果是,他肯定和调用equals函数的对象不相等,直接返回false
        if(student == null)         
            return false;
       //如果调用equals方法的对象和参数传来的对象不属于同一个类,直接返回false
        if(this.getClass() != student.getClass())      
            return false;
        Student another = (Student) student;  //将student强制转换成Student类型(可能会有bug)
        return this.name.toLowerCase().equals(another.name.toLowerCase());
    }
}

自己定义一个测试数组类

public class ArrayGenerator {
    public static void main(String[] args) {
    }
    //生成一个0到n的测试数组
    public static Integer[] generatorOrderedArray(int n){
        Integer[] array = new Integer[n];
        for(int a=0;a 

main函数测试

public class Main{
     public static void main(String[] args) {
        //测试1
        Integer[] data={24,18,12,9,16,66,32,4};     //泛型传入的参数必须是包装类Integar
        int res=xxczfx.search(data,16);  //16是个数,java可以自己把他变成包装类(类型推断)
        System.out.println(res);

        //测试2
        Student[] students={new Student("Alice"),
                            new Student("Bobo"),
                            new Student("Charles")};
        Student Bobo = new Student("bobo");
        int res3 = xxczfx.search(students,Bobo);
        System.out.println(res3);

        //测试3
        int[] datasize ={1000000,10000000};
        for(int n:datasize){
            Integer[] arr1 = ArrayGenerator.generatorOrderedArray(n);   //声明一个测试数组
            int res4=0;
            long startTime = System.nanoTime();  //出现一个时间窗,可以用来计时
            for(int k=0;k<100;k++)                  //测试运行100次这个句子需要多少时间
                 res4 = xxczfx.search(arr1,n);
            System.out.println(res4);
            long endTime = System.nanoTime();   //计时
            double time = (endTime-startTime)/1000000000.0;
            System.out.println("n=" + n +",100 runs:" + time + "s");  //打印时间
        }
    }
}

时间复杂度:O(n)

二、选择排序法

非原地排序:每次将还未处理的元素中最小的元素选出来,放在另一个数组最前面。

原地排序:遍历数组,将最小的元素取出来,与i交换,i++,继续遍历剩下的未排序元素,重复之前的操作

 

public static >void select(E[] arr){   //实现可比较的泛型E
        //arr[0....i)是有序的,arr[i...n)是无序的
        for(int i = 0;i< arr.length;i++){
            int position=i;
            for(int j=i;j 0 ) {  
                //.compareTo()方法,如果前者大于后者,返回正数,其他类似
                    position = j;
                }
            }
            swap(arr,position,i);
        }

    }
public static void swap(E[] arr,int i,int j){
        E t=arr[i];
        arr[i]=arr[j];
        arr[j]=t;
    }

创建一个Student类进行测试

public class Student implements Comparable {  //实现Comparable接口
    private String name;
    private int score;
    public Student(String name,int score){
        this.name = name;
        this.score = score;
    }
    @Override
    public int compareTo(Student another){
//       if(this.score> another.score)
//           return 1;
//       else if(this.score

创建一个生成数组的类来进行测试

public class ArrayGenerator {
    private ArrayGenerator(){}

    
    public static Integer[] generatorOrderedArray(int n){
        Integer[] arr = new Integer[n];
        for(int i = 0; i < n; i++){
            arr[i] = i;
        }
        return arr;
    }

    
    public static Integer[] generatorRandomArray(int n, int bound){
        Integer[] arr1 = new Integer[n];
        Random rnd = new Random();
        for(int i = 0; i < n; i++){
            arr1[i] = rnd.nextInt(bound);
        }
        return arr1;
    }

}

创建一个SortingHelper类,用来检查是否排序好和进行运行时间统计

public class SortingHelper {
    private SortingHelper(){}

    
    public static > boolean isSorted(E[] arr){
        for(int i = 1; i < arr.length; i++){
            if(arr[i-1].compareTo(arr[i]) > 0)
                return false;
        }
        return true;
    }

    
    public static > void sortTest(String sortName, E[] arr){
        long startTime = System.nanoTime();   //起始时间
        if(sortName.equals("SelectYd"))
            SelectYd.select(arr);
        else if(sortName.equals("SelectedSort"))
            SelectedSort.select(arr);
        else if(sortName.equals("InsertSort"))
            InsertSort.sort(arr);
        else if(sortName.equals("InsertSort2"))
            InsertSort.sort2(arr);
        else if(sortName.equals("InsertSort3"))
            InsertSort.sort3(arr);
        long endTime = System.nanoTime();     //结束时间
        double time = (endTime - startTime)/1000000000.0;

        // 看数组是否已经排序,如果没排序好,抛出一个运行时异常
        if(!SortingHelper.isSorted(arr)){
            throw new RuntimeException(sortName + " failed");
        }
        System.out.println(sortName+", n= "+arr.length+" : "+time + "s");
    }

}

main函数进行测试

    public static void main(String[] args) {

        //测试用例1(int)
        Integer arr[] = {12,12,34,52,13,42,31,52,68,94};
        SelectYd.select(arr);
        for(int i =0;i< arr.length;i++){
            System.out.print(arr[i] + " ");

        }
        if(!SortingHelper.isSorted(arr)){
            throw new RuntimeException("SelectYd failed");
        }
        System.out.println();

        //测试用例2(student)
        Student[] students = {new Student("Alice",98),
                              new Student("BobO",88),
                              new Student("Charles",100)};
        SelectYd.select(students);
        for(Student student:students){  //为students数组中的每个student循环
            System.out.println(student+"");
        }

        //测试用例3(生成一个随机数组进行排序)
        int[] datasize = {10000,100000};

        for(int n:datasize) {
            Integer[] arr3 = ArrayGenerator.generatorRandomArray(n, n);
            SortingHelper.sortTest("SelectYd",arr3);
        }


    }

时间复杂度:O(n^2)

三、插入排序法

每次处理一个元素,将这个元素插入到前面已经排好序的元素中(处理一个元素时,如果它小于它前面的元素,就与他交换位置,直到插入到合适的位置)

  
public static > void sort(E[] arr){
        for(int i = 1; i < arr.length; i++){
//            for(int j = i; j >= 1; j--){    //从i开始和i-1比较
//                if(arr[j].compareTo(arr[j-1]) < 0)
//                    swap(arr,j-1,j);
//                else
//                    break;
//            }
            for(int j = i; j>=1 && arr[j].compareTo(arr[j-1]) < 0; j--){   //因为arr[j].compareTo(arr[j-1]) < 0也是判断循环终止的条件
                swap(arr,j-1,j);
            }
        }
    }

 public static  void swap(E[] arr, int i, int j){
        E temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

插入排序小优化:将要插入的值暂存到一个变量中,j向数组前面遍历,然后用它和j在的元素作比较,如果他小于j所在的元素,arr[j]就赋值给arr[j+1](第一个[j+1]其实就是要处理的元素位置),遍历完后,将要插入的值放入空出来的位置中

 
 public static > void sort2(E[] arr){
        for(int i = 1; i < arr.length; i++){
            E temp = arr[i];
            int j;
            for( j = i; j >= 1; j--){
                if(arr[j-1].compareTo(temp) > 0)
                    arr[j] = arr[j-1];
                else
//                    arr[j] = temp;    //为什么不能放这里,因为如果要在第一个元素插入temp值的话,这里循环条件是j>=1,当j=0时没办法进循环,就没办法赋值
                break;
            }
            arr[j] = temp;
        }

    }

时间复杂度:对于有序数组,时间复杂度为O(n),整体复杂度还是O(n^2).

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/782166.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号