Java基本算法的实现代码

0. 一些简单的解释

选择排序

  1. 选择[1:-1]数组中的最小值,与索引0交换数值
  2. 选择余下[2:-1]数组中的最小值,与索引1交换数值
  3. 依次遍历余下部分的数组,直到交换所有数值

冒泡排序

  1. 只检查相邻两个元素的大小,按升序交换位置
  2. 为避免最后阶段的无效比较,加入布尔值判断是否有数据进行了交换,无交换直接跳出循环结束排序
  3. 为避免每次比较都要遍历全部数组,加入索引规定每次遍历的索引长度,索引之后的元素再之前的排序阶段已经完成有序,无需再次遍历

快速排序

  1. 跳跃式的数据交换是快排比冒泡快的一个原因
  2. 以索引0的数值做基准对数组进行二分,从右向左找到比基准小的数,从左向右找到比基准大的数,交换
  3. 最终左右指针在中间相遇,此时指针左边都比基准小,右边都比基准大,交换指针与基准的数值
  4. 递归二分,将基准左侧和右侧分别看作新的数组重新选定基准,再次交换
  5. 基准的选择不唯一,通常选择索引0

归并排序

  1. 如果是两个长度相同或相差1的有序数组,只要依次比较同索引的数值,按照小的先放的顺序放入新数组,即可完成归并
  2. 归并排序就是将一个数组从中间二分,形成A,B两个子数组
  3. 分别对A和B进行递归二分直到分成有序或唯一元素的子数组,进行归并
  4. 依次对子数组进行归并操作,最终返回长度与原数组相同的有序数组

二分查找

  1. 每次查找都从有序数组的中间位置开始
  2. 升序时,若中间位置的数值比要找的数大,则只找左半边

找出数组中第二大的数

  1. 假设第一大为第一个数,第二大的数为0
  2. 比较每个元素若比第二个大比第一大小,赋值给第二大
  3. 若比第二大和第一大都大,将第一大赋值给第二大,将该数赋值给第一大
  4. 找不到返回-1

阶乘

  1. 递归的基本用法
  2. 递归与减一的数相乘,直到遇到1,返回1不再递归

1. 选择排序

import java.util.Arrays;

public class 选择排序 {
    public static void main(String[] args) {
        int[] arr={5,4,6,2,1,7,0,9,8,3};
        int[] res = sort(arr);
        System.out.println(Arrays.toString(res));
    }
    public static int[] sort(int[] data){
        int k=0;//选择指针
        int tmp=0;//用于交换位置的临时变量
        for (int i = 0; i < data.length - 1; i++) {
            //遍历第一个到倒数第二个元素
            k=i;//假设索引i的数是最小值
            for (int j = i+1; j < data.length; j++) {
                //遍历第二到最后一个元素
                if (data[j]<data[k]){
                    //如果索引j更小,说明k不是最小,要改
                    k=j;
                }
                //这个循环结束的时候k就是最小值的索引
            }
            //依次找出最小的值所在位置k,与从0开始遍历数组的元素交换
            if (k!=i){
                tmp=data[k];
                data[k]=data[i];
                data[i]=tmp;
            }
        }
        return data;
    }
}

2. 冒泡排序

import org.junit.Test;

import java.util.Arrays;
//冒泡排序
public class 冒泡排序 {
    @Test
    public void a1(){
        int[] arr=new int[]{5,4,2,6,1,8,9,0,3,7};
        System.out.println(Arrays.toString(arr));
        //冒泡排序0-9
        int tmp = 0;
        for (int j = 0; j <arr.length ; j++) {
            for (int i=0;i<arr.length-j-1;i++){
                if (arr[i+1]<arr[i]){
                    tmp=arr[i];
                    arr[i]=arr[i+1];
                    arr[i+1]=tmp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void a2(){
        int[] arr = new int[]{5,6,3,2,1,4,7,0,8,9};
        System.out.println(Arrays.toString(arr));
        int tmp=0;
        for (int i = 0; i < arr.length; i++) {
            //flag为真表示有序
            Boolean flag=true;
            for (int j = 0; j < arr.length-i-1; j++) {
                if (arr[j]>arr[j+1]){
                    tmp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=tmp;
                    //if条件成立说明数组不是有序的
                    flag=false;
                }
            }
            if (flag){
                break;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void a3(){
        int[] arr=new int[]{4,2,3,1,0,7,9,5,6};
        //最后交换顺序的位置
        int lastindex=0;
        //有序范围,首先假设全部有序
        int sortborder=arr.length-1;
        int tmp=0;
        for (int i = 0; i < arr.length; i++) {
            //有序标签.假设全部有序
            boolean flag=true;
            for (int j = 0; j < sortborder; j++) {
                if (arr[j]>arr[j+1]){
                    tmp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=tmp;
                    //交换顺序
                    flag=false;
                    //改变最后交换顺序的位置
                    lastindex=j;
                }
            }
            //逐次缩小比较的范围
            sortborder=lastindex;
            if (flag){
                //没进入过交换顺序的话,说明已经有序,跳出循环
                break;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

}

3. 快速排序

import java.util.Arrays;

//快速排序
public class 快速排序 {

    public static void main(String[] args) {
        int[] arr=new int[]{52, 49, 80, 36, 14, 58, 61, 97, 23, 75};
        quicksort qk=new quicksort();
        qk.arr=arr;
        int[] res = qk.sort(0, arr.length - 1);
        System.out.println(Arrays.toString(res));
    }

    static class quicksort{
        int[] arr;
        int[] sort(int low,int high){
            int i,j,t,tmp;
            if (low>high){
                return arr;
            }
            i=low;
            j=high;
            tmp = arr[low];//基准
            while (i!=j){
                //先从右向左找小于基准的数
                while (i<j && arr[j]>=tmp){
                    j--;
                }
                //再从左向右找大于基准的数
                while (i<j && arr[i]<=tmp){
                    i++;
                }
                //交换上边两个数的位置
                if(i<j){
                    t=arr[i];
                    arr[i]=arr[j];
                    arr[j]=t;
                }
                //循环交换位置,直到i==j退出循环,此时i的位置是基准该在的位置
            }
            //交换基准和循环得到的索引
            arr[low]=arr[i];//arr[low]就是tmp,这里不用再作临时变量了
            arr[i]=tmp;
            //递归处理基准左边数组
            sort(low,i-1);
            //递归处理基准右边数组
            sort(i+1,high);
            return arr;
        }
    }
}

4. 归并排序

import org.junit.Test;

import java.util.Arrays;

public class 归并排序 {
    //1 两个有序数组a,b合并成c
    static int[] sum(int[] a,int alen,int[] b,int blen,int[] c){
        //初始化三个指针对应三个数组
        int i,j,k;
        i=j=k=0;
        //循环直到i或j越界
        while (i<alen && j<blen){
            if (a[i]<b[j]){
                //先放小的数,放完+1
                c[k++]=a[i++];
            }else {
                c[k++]=b[j++];
            }
        }
        //经过上边的循环后的i,j如果还有元素,直接放进去
        while (i<alen){
            c[k++]=a[i++];
        }
        while (j<blen){
            c[k++]=b[j++];
        }
        return c;
    }
    @Test
    public void a1() {
        int[] a={1,3,5,7,9};
        int[] b={2,4,6,8,10,12,14};
        int[] c=new int[a.length+b.length];
        int[] sum = sum(a, a.length, b, b.length, c);
        System.out.println(Arrays.toString(sum));
    }
    //2 归并排序
    //递归,将数组分为两组,判断是否有序,无序继续分两组,直到有序
    @Test
    public void a2(){
        int[] arr={4,5,2,3,6,8,0,9,1,7};
        //start=1从第二个元素开始比较
        int[] res = merge(arr, 1, arr.length);
        System.out.println(Arrays.toString(res));
    }
    //合并方法
    public int[] merge(int[] data,int start,int end){
        if (start<end){
            //取中间点作分组尝试
            int mid=(start+end)/2;
            //递归再二分
            merge(data,start,mid);
            merge(data,mid+1,end);
            //调用分组方法
            System.out.println(Arrays.toString(data));
            part(data,start,mid,end);

        }
        return data;
    }
    //分两组方法
    public void part(int[] data,int start,int mid,int end){
        //分两组A和B,长度分别为中间到左右端长度
        int lena=mid-start+1;//start从1开始,要把这个长度补上
        int lenb=end-mid;
        int[] A=new int[lena+1];//左数组
        int[] B=new int[lenb+1];//右数组

        //分别遍历数组A和B,将给定数组的左右元素分别插入对应位置
        for (int i = 0; i < lena; i++) {
            A[i] = data[i+start-1];
        }A[lena]=Integer.MAX_VALUE;//将数组A的最后一个元素赋值为最大整数
        System.out.println("A:"+Arrays.toString(A));
        for (int i = 0; i < lenb; i++) {
            B[i] = data[i+mid];
        }B[lenb]=Integer.MAX_VALUE;
        System.out.println("B:"+Arrays.toString(B));
        //此时左右两个数组已经是有序的,依次比较放入小数即可
        int m=0;
        int n=0;
        for (int i = start-1; i < end; i++) {
            if (A[m]>B[n]){
                //先放小的数
                data[i]=B[n++];
            }else {
                data[i]=A[m++];
            }
        }
        //最终返回的数组长度依然为初始长度,因此追加的两个最大整数会在A,B的最后被抛弃
    }
}

5. 二分查找


//二分查找法
public class 二分查找 {
    public static int a1(int key){
        //从升序排序的数组中查找KEY所在索引
        int [] arr=new int[]{0,1,2,3,4,5,6,7,8,9};
        //初始化查找的起点和终点
        int end=arr.length-1;
        int start=0;
        while (start<=end){
            //每次都从中间开始找
            int mid=(end+start)/2;
            if (arr[mid]==key){
                return mid;
            }else if (arr[mid]>key){
                //中间数大于key,就找比中间数小的
                end = mid;
            }else {
                start = mid;
            }
        }
        return -1;//表示未找到
    }

    public static void main(String[] args) {
        int i = a1(4);
        System.out.println(i);
    }

}

6. 找出数组中第二大的数

import org.junit.Test;

//找出数组中第二大的数
public class 第二大的数 {
    //判断一个数组中第二大的数
    @Test
    public void a1(){
        String str="3 4 2 5 1 6 7 8";
        String[] strs = str.split("\\s");
        int[] arr=new int[strs.length];
        //转换字符串数组到整数数组
        for (int i = 0; i < arr.length; i++) {
            arr[i]=Integer.parseInt(strs[i]);
        }
        //初始化最大数为数组第一个数
        int max=arr[0];
        int sec=0;
        for (int i = 0; i < arr.length; i++) {
            //遍历数组,如果有数比第二大的数大,就进入交换
            if (arr[i]>sec){
                //如果这个数比第二和第一都大,就赋值第二大数为最大数,最大数为该数
                if (arr[i]>max){
                    sec=max;
                    max=arr[i];
                }else {
                    //如果只比第二大数大,比第一大数小,就直接赋值给第二大数
                    sec=arr[i];
                }
            }
        }
        System.out.println("最大的数:"+max+",第二大的数:"+sec);
    }

}

7. 求一个整数的阶乘


//数的阶乘,递归
public class 阶乘 {
    public static int a1(int num){
        if (num<=0){
            return 0;
        }else if (num==1){
            return 1;
        }else {
            return num*a1(num-1);
        }
    }

    public static void main(String[] args) {
        int i = a1(3);
        System.out.println(i);
    }

}

猜你喜欢

转载自blog.csdn.net/wxfghy/article/details/81098706