算法 + 数据结构

第一节:算法 查找

一.顺序查找

import java.util.Arrays;
/**
 *顺序查找
 */
public class TestSearch {
    public static void main(String[] args) {
        int[] arr=creatArray(10,0,21);
        System.out.println(Arrays.toString(arr));
        int key=10;
        System.out.println(search(arr,key));
    }
    //对指定的数组进行搜索,查找是否存在指定的值,如果存在返回该值的索引,不存在返回-1
    //时间复杂度T(n)=O(n),空间复杂度S(n)=O(1);
    public static int search(int[] arr,int key) {
        if (arr == null)
            return -1;
        int LEN = arr.length;
        if (LEN == 0)
            return -1;
        //常规情况,遍历数组
        for (int i = 0; i < LEN; i++) {
            if (arr[i] == key) {
                return i;
            }
        }
        //如果上面没找到,则返回-1
        return -1;
    }

    //定义一个创建数组的方法
    public static int[] creatArray(int len,int min,int max){
        int[] arr=new int[len];
        for (int i = 0; i < len; i++) {
            arr[i]=randomNumber(min,max);
        }
        return arr;
    }
    //定义一个产生随机数的方法
    public static int randomNumber(int min,int max){
        return (int)(Math.random()*(max-min)+min);
    }
}

2.二分搜索
概念:对待搜索区进行不断的拆分来缩小搜索的范围,实现最终查找的目的。
对搜索的数据的要求:1:需要是一个线性的数列。2:数列需要有序,升序的。
待搜索的数据为21:
在这里插入图片描述

/**
 * 测试二分查找
 */
public class TestBinarySearch {
    public static void main(String[] args) {
        int[] array=TestSearch.creatArray(20,0,30);
        //对数组进行排序
        Arrays.sort(array);
        System.out.println(Arrays.toString(array));
        int key=9;
        //测试自定义递归二分查找方法
        //int index=binarySearchRecursion2(array,key);
        //测试自定义二分查找方法(用循环写的二分查找法)
        int index=binarySearch(array,key);
        System.out.println("index="+index);
    }
    //自定义二分查找方法,使用循环实现,对指定的数组进行二分搜索,查找指定的值
    //时间复杂度:T(n)=O(log2n)  空间复杂度:S(n)=O(1)
    public static int binarySearch(int[] arr,int key){
        //先判断特殊情况
        if(arr==null)
            return -1;

        if(arr.length==0)
            return -1;
        //常规情况
        int low=0;
        int high=arr.length-1;
        int mid=low+high >> 1;//右移以为相当于除以2,位运算符的优先级高于加号;等价于mid=(low+high)/2;
        while(high>=low){
            //取索引为中点的值
            int value=arr[mid];
            if(key==value){
                return mid;
            }else if(key<value){ //待搜索的值在mid的左边
                high=mid-1;
            }else{      //待搜索的值在mid的右边
                low=mid+1;
            }
            //重新定义二分点
            mid=low+high >> 1;
        }
        //如果在上面的循环中没有找到则返回-1;
        return -1;
    }

    //使用递归实现二分搜索
    //对知指定的数组的指定的区间,进行一次二分搜索的行为
    public static int binarySearchRecursion(int[] arr,int key,int low,int high){
        //递归终止条件
        if(high<low){
            return -1;
        }
        //使用递归实现
        int mid=high +low >> 1;//求中间值
        int midValue=arr[mid];
        if(key==midValue){
            return mid;
        }else if(key>midValue){//在mid的右边
            low=mid+1;
            return binarySearchRecursion(arr,key,low,high);
        }else{   //在mid的左边
            high=mid -1;
            return binarySearchRecursion(arr,key,low,high);
        }
    }
    //对指定的数组进行递归二分
    public static int binarySearchRecursion2(int[] arr,int key){
        if(arr==null){
            return -1;
        }
        final int LEN=arr.length;
        if(LEN==0){
            return -1;
        }
        int low=0;
        int high=LEN-1;
        return binarySearchRecursion(arr,key,low,high);
    }
}

第二节 算法 排序

一、相关概念
稳定排序:如果一个数列中有相同的内容,排序之后,相同的内容的相对的前后位置没有发生变化,那么就是稳定的排序。
不稳定排序:如果一个数列中有相同的内容,排序之后,相同的内容的相对的前后位置可能发生变化,那么就是不稳定的排序。
内部排序:所有待排序的数据都在当前的内存中称为内部排序。
外部排序:待排序的数据量很大,全部放到内存中,内存不够使用,需要依赖于外部存储设备。把一部分数据放到外设中。
在这里插入图片描述
二、分类
1、.直接选择排序
在这里插入图片描述
2.直接插入排序
在这里插入图片描述

import java.util.Arrays;

/**
 * 选择排序和插入排序代码
 */
public class TestSort {
    public static void main(String[] args) {
        int[] arr=TestSearch.creatArray(10,0,21);
        System.out.println(Arrays.toString(arr));
        //测试选择排序算法
        selectSort(arr);
        //测试插入排序算法
        //insertSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    //使用选择算法对指定的数组进行排序
    public static void selectSort(int[] arr){
        //处理特殊情况
        if(arr==null)
            return;
        final int LEN=arr.length;
        if(arr.length==0)
            return;
        //常规情况
        //i既用来控制为循环的趟数,还是代表了待排序区的第一个元素的索引
        for (int i = 0; i < LEN-1; i++) {
                //minIndex 存的是待排序区的最小值的索引
                int minIndex=i;
                //内层循环用于第i趟的最小元素索引的查找
            for (int j = i+1; j < LEN; j++) {
                if(arr[j]<arr[minIndex]){
                    //minIndex就保存了最小值的索引
                    minIndex=j;
                }
            }
            //互换位置
            if(minIndex!=i){  //待排序区肚饿第一个元素不是最小值
                int temp=arr[i];
                arr[i]=arr[minIndex];
                arr[minIndex]=temp;
            }
        }
    }

    //使用直接插入排序对指定的数组进行排序
    public static void insertSort(int[] arr){
        //特殊情况处理
        if(arr==null)
            return;
        final int LEN=arr.length;
        if(LEN==0)
            return;
        //外层循环控制趟数,并且外层循环的i代表了无序区的第一个元素的索引
        for (int i = 1; i < LEN; i++) {
            //备份无序区的第一个元素
            int temp=arr[i];
            //扩大j的作用域
            int j=0; //初始化j的值
            //从后往前比较,i-1代表了有序区的最后一个元素的索引
            for (j = i-1; j >=0 && arr[j]>=temp ; j--) {
                arr[j+1]=arr[j];
            }
            //将备份的值填到最后被以后的那个下标的位置
            arr[j+1]=temp;
        }
    }
}

三、数组的扩容

import java.util.Arrays;

/**
 *数组扩容
 */
public class TestArrayExpansion {
    public static void main(String[] args) {
        int[] arr = {23,34,45,3,2};
        //新创建一个数组,长度是现有数组的1.5倍
        int[] newArr=new int[arr.length*3 >> 1];
        //将原来的数组复制过来
        System.arraycopy(arr,0,newArr,0,arr.length);
        //在将需要添加的数据添加到数组元素尾部
        newArr[arr.length]=77;
        //将原数组的引用指向新数组
        arr=newArr;

        //将上面内容用一句代码实现
        arr=Arrays.copyOf(arr,arr.length*3>>1);
        System.out.println(Arrays.toString(arr));
    }
}

第二节、数据结构

概念
数据结构:一组具有某些关系的数据的集合。
学习数据结构:主要就是学习数据之间的关系,关系决定了数据被访问的特点。
逻辑结构:数据之间的逻辑关系。(例如:一个学生拥有一本书,学生对象里面真的有一本书吗,只是存了这个书对象的引用)
存储结构:数据之间的存储的关系。

一 、数组
一种很简单的数据结构。
元素之间的关系:元素之间是连续的,通过一个个连续的序号可以进行访问。(是线性结构)
元素的特点:根据索引访问元素的效率很高,遍历元素的效率很高、删除元素,插入元素、效率比较低。
二、栈:一种线性关系的数据结构。
在这里插入图片描述
自己写了一个栈,代码如下:

/**
 * 手写栈
 */

import com.sun.org.apache.xpath.internal.SourceTree;

import java.util.Arrays;

public class Test {
    public static void main (String[] args) throws Exception{
        MyStack myStack=new MyStack();
        myStack.push("a");
        myStack.push("_");
        myStack.push(true);
        myStack.push(1.1);
        myStack.push(false);
        System.out.println(myStack.toString());
        System.out.println(myStack.search(true));
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack);
    }
}
//设计类来描述栈
class MyStack{
    //定义栈的初始容量
    public static final int DEFAULT_CAPACITY = 6;
    //底层使用数组实现
    private Object[] elementDate;
    //栈顶指针
    private int index;
    public MyStack(){
        elementDate=new Object[DEFAULT_CAPACITY];
        //index=0;  这一句不写的话,默认值也是零
    }
    public MyStack(int initCapacity){
        elementDate=new Object[initCapacity];
        //index=0;
    }

    //压栈操作
    public void push(Object o){
        //栈满了,扩容,扩容的规则:1.5倍
        /*
        if(isFull()){
            //扩容
            elementDate=Arrays.copyOf(elementDate,elementDate.length*3>>1);
            elementDate[index]=o;//容量不够先扩容,再在尾部增加数据
        } else{
            elementDate[index]=o;//容量够的话直接在尾部增加数据
            index++;
        }
        */
        //上面的代码有相同的部分,可以进行优化,并且写的更高级 如下所示:
        if(isFull()){
            //扩容
            Arrays.copyOf(elementDate,elementDate.length*3>>1);
        }
        elementDate[index++]=o;//将上面的两句代码合为一句。index++,先赋值再自增;
    }

    //弹栈或者是出栈操作
    public Object pop() throws Exception{
        //栈空了
        if(isEmpty()){
            throw new Exception("感觉身体被掏空");
        }
        //指针下移,然后将指针指向的位置获得
        //index--;
        Object o=elementDate[--index];
        //以免内存泄漏
        elementDate[index]=null;
        return o;
    }

    //获得栈顶元素,但不移除
    public Object peek() throws Exception{
        if(isEmpty()){
            throw new Exception();
        }else{
            return elementDate[index-1];
        }
    }

    //o是否在栈中,存在返回索引,否则返回-1
    public int search(Object o){
        if(isEmpty())
            return -1;
        for (int i = 0; i < index; i++) {
            if(elementDate[i].equals(o))
                return i;
        }
        return -1;
    }

    //得到栈的容量
    public int capacity(){
        return elementDate.length;
    }

    //得到栈中元素的个数
    public int size(){
        return index;
    }

    //得到栈的字符串表示形式
    public String toString(){
        return Arrays.toString(Arrays.copyOf(elementDate,index));//这样就可以将栈中存的null删除,并且得到原数组
    }

    //判断栈是否满了,满了返回true,否则返回false
    public boolean isFull(){
        return index == elementDate.length;
    }

    //判断栈是否为空
    public boolean isEmpty(){
        return index==0;
    }
}

三、链表
也是一种线性的数据结构。每个元素也有一个序号,元素添加的顺序号。0序的。
在这里插入图片描述
在这里插入图片描述
四、树 tree
非线性的数据结构。
在这里插入图片描述
在这里插入图片描述
今日练习:
1:自己实现二分查找法(循环+递归)要求两种实现。
2:实现冒泡排序。
3:实现选择排序。
4:实现插入排序。
5:实现对指定的目录,统计该目录中文件的类型信息。将所有的文件的后缀返回。不能有重复的后缀。要求返回的格式为[.txt;.jpg;.dat]。后缀名之间使用 分号 分割。

import java.io.File;

//实现对指定的目录,统计该目录中文件的类型信息。
//        将所有的文件的后缀返回。不能有重复的后缀。要求返回的格
//        式为[.txt;.jpg;.dat]。后缀名之间使用 分号 分割。
public class Test2 {
    public static void main(String[] args) {
        System.out.println(countFileTypes(new File("c:/7")));
    }

    /**
     * @param file 被统计的目录
     * @return  返回 file 目录下的所有的文件的类型的信息。
     */
    public static String countFileTypes(File file){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        if(file.isDirectory()){
            //得到目录下的所有的子文件
            File[] files = file.listFiles();
            for (File f : files) {//ni.a.txt
                //如何去获得每一个文件的后缀信息
                String name = f.getName();
                //找最后一个 点的 索引值
                int index = name.lastIndexOf(".");
                //获得了包含 .  后缀的信息
                String suffix = name.substring(index);
                //sb 中 没有suffix 的话 添加到尾部。
                if(sb.indexOf(suffix) < 0){
                    sb.append(suffix).append(";");
                }
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值