算法

算法

一、排序算法

在这里插入图片描述

1.冒泡排序

  • 每一次内循环把最大或者最小的交换到顶部,类似冒泡
  • o(n*2):基本不用,太慢
  • 稳定
public class Bubble {
    /**
     * 冒泡排序:每一次内循环把最大或者最小的交换到顶部,类似冒泡
     * @param array
     * @return
     */
    public int[] sort(int [] array){
        if(array==null|| array.length<2){
            return array;
        }
        int temp=0;
        for(int i=0;i<array.length-1;i++){
            int flag=0;//符号位,如果已经有序,就退出循环
            for (int j = 0; j < array.length-i-1; j++) {
                if(array[j+1]<array[j]){ // <升序或者 >降序
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    flag=1;
                }
            }
            if(flag == 0){
                break;
            }
        }

        return array;
    }

    public static void main(String[] args) {
        int []array={1,2,4,3,5,9,8,7};
        int[] sort=new Bubble().sort(array);
        for (int n:sort) {
            System.out.print(n+" ");
        }
    }
}

2.选择排序

  • 从待排序数组中选出最大或最小的元素,放到排序起始位置,再从未排序数组中继续寻找最大(小)元素,放到已排序序列的末尾…。
  • 基本不用,是最不稳定的排序方法(相同的元素在排序后次序可能改变)
  • o(n*2)
public class SelectSort {
    /**
     * 选择排序:从待排序数组中选出最大或最小的元素,放到排序起始位置,
     * 再从未排序数组中继续寻找最大(小)元素,放到已排序序列的末尾....。
     * 是最不稳定的排序方法  o(n*2)
     * @param array
     * @return
     */
    public int[] sort(int [] array){
        if(array==null|| array.length<2){
            return array;
        }
        int temp=0;
        for(int i=0;i<array.length-1;i++){
            int minIndex=i;//认为的最小元素下标
            for (int j = i+1; j < array.length; j++) {
                if(array[minIndex]>array[j]){ // <升序或者 >降序
                    minIndex=j;
                }
            }
            if(minIndex != i){ //判断最小值是否是开始认为的,节省资源
                temp = array[i];
                array[i] = array[minIndex];
                array[minIndex] = temp;
            }
        }

        return array;
    }

}

3.插入排序

  • 第一个元素认为已经排序,取出下一个元素,在已排序序列从后往前扫描,新元素大于已排序元素就将新元素移到下一元素,如果小于就交换位置
  • 样本小且基本有序的时候效率高,稳定,简单排序用插入
  • o(n*2)
public class InsertSort {
    /**
     * 插入排序:第一个元素认为已经排序,取出下一个元素,在已排序序列从后往前扫描,新元素大于已排序元素,
     * 就将新元素移到下一元素,如果小于就交换位置
     * o(n*2)
     * @param array
     * @return
     */
    public int[] sort(int [] array){
        if(array==null|| array.length<2){
            return array;
        }
        int temp=0;
        for(int i=1;i<array.length;i++){
            for (int j = i; j > 0 && array[j]<array[j-1]; j--) {
                temp=array[j];
                array[j]=array[j-1];
                array[j-1]=temp;
            }
        }
        return array;
    }

    public static void main(String[] args) {
        int []array={1,2,4,3,5,9,8,7};
        int[] sort=(new InsertSort()).sort(array);
        for (int n:sort) {
            System.out.print(n+" ");
        }
    }
}

4.希尔排序

  • 首先确定间隔,按间隔插入排序一次,然后缩小间隔排序一次,最后一定有一次间隔为1需要排序一次
  • 特殊的插入排序
  • 间隔大的时候移动的次数少,间隔小的时候移动的距离短,就比插入排序效率高
  • 不稳定,一般也不用,适用于中型排序,O(n*1.3)
    第一种:
public class ShellSort {
    /**
     * 希尔排序:
     * @param array
     * @return
     */
    public int[] sort(int [] array){
        if(array==null|| array.length<2){
            return array;
        }
        int h=0;
        while (h <= array.length / 3){
            h = h*3 + 1;
        }
        int temp=0;
        // array.length/2 等价于 array.length >> 1 (位运算,右移n位相当于除2*n,左移为乘)
        for(int gap = h ;gap>0;gap = (gap-1)/3){ //for(int gap = array.length/2 ;gap>0;gap /= 2){
            for(int i=gap;i<array.length;i++){
                for (int j = i; j > gap - 1; j -= gap) {
                    if(array[j]<array[j-gap]){
                        temp=array[j];
                        array[j]=array[j-gap];
                        array[j-gap]=temp;
                    }
                }
            }
        }

        return array;
    }

    public static void main(String[] args) {
        int []array={1,2,4,3,5,9,8,7};
        int[] sort=new ShellSort().sort(array);
        for (int n:sort) {
            System.out.print(n+" ");
        }
    }
}

5.归并排序

在这里插入图片描述

  • 将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
  • 稳定
  • Java和Python对对象的排序都是改进的归并排序(TIM Sort)(对对象的排序都需要要求稳定)
  • O(n log n),代价是需要额外的内存空间。

一个数组前后以排序好,如[1,2,7,8,3,4,6,]

public int[] sort(int [] array){
    if(array==null|| array.length<2){
        return array;
    }
    int mid = array.length / 2;
    int [] temp = new int[array.length];
    int i=0;
    int j=mid+1;
    int k=0;
    while (i <= mid && j<array.length){
        if(array[i]<=array[j]){ //稳定,相等不会交换次序
            temp[k++] = array[i++];
        } else {
            temp[k++] = array[j++];
        }
    }
    while (i<=mid)
        temp[k++] = array[i++];
    while (j<array.length)
        temp[k++] = array[j++];
    return temp;
}

实现排序

public class MergeSort {
    /**
     * 归并排序
     * 简介:将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
     * 时间复杂度为O(nlogn)
     * 稳定排序方式
     * @param nums 待排序数组
     * @return 输出有序数组
     */
    public static int[] sort(int[] nums,int low,int high){
        int mid = low + (high - low)/2; //防止int+int 溢出
        if(low < high){
            //左边
            sort(nums,low,mid);
            //右边
            sort(nums,mid+1,high);
            //左右归并
            merge(nums,low,mid,high);
        }
        return nums;
    }
    /**
     * 将数组中low到high位置的数进行排序
     * @param nums 待排序数组
     * @param low 待排的开始位置
     * @param mid 待排中间位置
     * @param high 待排结束位置
     */
    public static void merge(int [] nums,int low, int mid, int high){
        int [] temp = new int[high - low +1];//新建排序完的数组

        int i=low;//左指针
        int j=mid+1;//右指针
        int k=0;
        while (i <= mid && j<=high){
            if(nums[i]<=nums[j]){ //稳定,相等不会交换次序
                temp[k++] = nums[i++];
            } else {
                temp[k++] = nums[j++];
            }
        }
        while (i<=mid)
            temp[k++] = nums[i++];
        while (j<=high)
            temp[k++] = nums[j++];
        // 把新数组中的数覆盖nums数组
        for (int k2 = 0; k2 < temp.length; k2++) {
            nums[k2 + low] = temp[k2];
        }
    }

    public static void main(String[] args) {
        int []array={1,2,4,3,5,9,8,7};
        int[] sort=(new MergeSort()).sort(array,0,array.length-1);
        for (int n:sort) {
            System.out.print(n+" ");
        }
    }
}

6.快速排序

在这里插入图片描述

  • O(nlog2n),不稳定
  • 认为是数量级在O(nlog2n)中性能最好
public class QuickSort {
    public void quick(int[] array,int l,int r){
        if(l >= r){
            return ;
        }
        int left = l,right = r;
        int pivot = array[left];  //选定最左边的数为中轴排序
        while (left < right){
            while (left < right && array[right]>= pivot){
                right--;
            }
            array[left] = array[right]; // array[right] < pivot 时,放在左边
            while (left < right && array[left] <= pivot){
                left++;
            }
            array[right] = array[left]; //array[left] > pivot 时,放在右边
            if(left == right){
                array[left] = pivot;  //排完了,把中轴放在中间
            }
        }
        quick(array,l,left-1); //这是left和right相等了
        quick(array,left+1,r);
    }

    public static void main(String[] args) {
        int []array={1,2,4,3,5,9,8,7};
        new QuickSort().quick(array,0,array.length-1);
        for (int n:array) {
            System.out.print(n+" ");
        }
    }
}

7.堆排序

二、查找算法

1.顺序查找

  • 顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。
int SequenceSearch(int a[], int value) {
    for(int i=0; i<a.length; i++)
        if(a[i]==value)
            return i;
    return -1;
}

2.二分查找

  • 折半查找
//二分查找、折半查找
int BinarySearch1(int a[], int value) {
    int low, high, mid;
    low = 0;
    high = a.length - 1;
    while(low<=high) {
        mid = (low+high)/2;
        if(a[mid]==value)
            return mid;
        if(a[mid]>value)
            high = mid-1;
        if(a[mid]<value)
            low = mid+1;
    }
    return -1;
}
  • 递归
//二叉树、递归
int BinarySearch2(int a[], int value, int low, int high) {
    int mid = low+(high-low)/2;
    if(a[mid]==value)
        return mid;
    if(a[mid]>value)
        return BinarySearch2(a, value, low, mid-1);
    if(a[mid]<value)
        return BinarySearch2(a, value, mid+1, high);
    return -1;
}

3.差值查找

//插值查找
int InsertionSearch(int a[], int value, int low, int high) {
    int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
    if(a[mid]==value)
        return mid;
    if(a[mid]>value)
        return InsertionSearch(a, value, low, mid-1);
    if(a[mid]<value)
        return InsertionSearch(a, value, mid+1, high);
    return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值