查找与排序算法

本文章介绍了所有常用的查找和排序
排序的有写 代码 可以直接复制
这里重点说一句 希尔排序 yysd
如果对你有帮助 记得点赞收藏加关注哦 <( ̄▽ ̄)/

查找

线性查找

一次for循环遍历查找元素

二分查找

也叫折半查找

通过中间值不断的将区间除以二 最后获取要查找的值的位置

属于有序查找

时间复杂度为o(log2 n)

mid=(low+high)/2

mid=low-(low-high)/2

插值查找

在二分的基础上 根据比例查找

mid=low+(int)(1.0X(kay-a[low])/(a[high]-a[low])*(high-low))

斐波那契查找

在二分的基础上 根据斐波那契数列进行分割

黄金比例查找

mid=low+0.624*(high-low)

排序

选择排序

时间复杂度O(n^2)

空间复杂度 o(1)

稳定性 :不稳定

每一个元素和后面元素比较如果小或大则交换

package sort;
import java.util.Arrays;
public class Select_Sort {
    public static void main(String[] args) {
        int [] Arr={1,3,4,2,9,7,8};
        Select_sort(Arr);
        System.out.println(Arrays.toString(Arr));
    }
    private static void Select_sort(int[] arr) {//选择排序
        for (int i = 0; i <arr.length-1 ; i++) {
            for (int j = i+1; j <arr.length ; j++) {
                if (arr[i]>arr[j]){
                    swap(arr,i,j);
                }
            }
        }
    }
    private static void swap(int[] arr, int i, int j) {//交换
        int teme=arr[i];
        arr[i]=arr[j];
        arr[j]=teme;
    }
}

冒泡排序

时间复杂度O(n^2)

空间复杂度 o(1)

稳定性 :稳定

每个元素后一个元素比较 符合则交换

package sort;
import java.util.Arrays;
public class bubbleSort {
    public static void main(String[] args) {
        int [] Arr={1,3,4,2,9,7,8};
        bubbleSort(Arr);
        System.out.println(Arrays.toString(Arr));
    }
    private static void bubbleSort(int[] arr) {
        for (int i = 0; i <arr.length-1 ; i++) {
            for (int j = 0; j <arr.length-1-i ; j++) {
                if (arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
    }
    private static void swap(int[] arr, int i, int j) {//交换
        int teme=arr[i];
        arr[i]=arr[j];
        arr[j]=teme;
    }
}

插入排序

时间复杂度O(n^2)

空间复杂度 o(1)

稳定性 :稳定

不断的将当前值插入到前方合适的位置

package sort;
import java.util.Arrays;
public class InsertionSort {
    public static void main(String[] args) {
        int [] Arr={1,3,4,2,9,7,8};
        InsertionSort(Arr);
        System.out.println(Arrays.toString(Arr));
    }
    private static void InsertionSort(int[] arr) {//插入排序
        for (int i = 1; i <arr.length ; i++) {
            for (int j = i; j >0&& arr[j]<arr[j-1]; j--) {
                 swap(arr,j,j-1);
            }
        }
    } 
    private static void swap(int[] arr, int i, int j) {//交换
        int teme=arr[i];
        arr[i]=arr[j];
        arr[j]=teme;
    }
}

优化

不断获取最小值直接插入前方位置 且遇到大的提前终止

private static void InsertionSort(int[] arr) {//交换且提前终止插入排序
        int e=0;
        int j=0;
        for (int i = 1; i <arr.length ; i++) {
            e=arr[i];
            for ( j = i; j >0&& e<arr[j-1]; j--) {
                arr[j]=arr[j-1];
            }
            arr[j]=e;

        }
    }

希尔排序

时间复杂度O(n^1.3)

空间复杂度 o(1)

稳定性 :不稳定

是简单排序的改进版本,他与插入排序的不同之处在于 ,他会优先比较距离较远的元素。

希尔排序右脚缩小增量排序

package sort;
import java.util.Arrays;
import java.util.Random;
public class SheelSort {
        public static void main(String[] args) {
            int[] arr = new int[10];
            Random random = new Random();
            for (int i = 0; i < arr.length; i++) {
                arr[i] = random.nextInt(10);
            }
            sheelSort(arr);
            System.out.println(Arrays.toString(arr));
        }

    private static void sheelSort(int[] arr) {
        for (int gap = arr.length/2; gap >0 ; gap--) {
            for (int i = gap; i <arr.length ; i++) {
                int j=i;
                int e=arr[j];
                while (j-gap>=0 &&arr[j-gap]>e){
                    arr[j]=arr[j-gap];
                    j=j-gap;
                }
                arr[j]=e;
            }

        }
    }
}

选择部分排序 希尔

public static void shellSort(int[] arr, int l, int r) {
    int j=0;
    int e=0;
    int len=r-l+1;
    for (int gap = len; gap >0 ; gap=gap/2) {
        for (int i = gap; i <r ; i++) {
            j=i;
            e=arr[i];
            while ( j-gap>=0 &&arr[j-gap]>e){
                arr[j]=arr[j-gap];
                j=j-gap;
            }
            arr[j]=e;
        }
    }
}

归并排序

时间复杂度O(nlog2n)

空间复杂度 o(n)

稳定性 :稳定

归并排序是建立债归并炒作是的一种有效的排序算法。

该算法是采用分治放的一个非常典型的的应用。

将已有序的子序列合并,得到完全有序的序列;即先使没个子序列有序,再试子序列段间有序。若将两个有序表合并成一个有序表,称为2路归并。

package sort;
import java.util.Arrays;
import java.util.Random;
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        mergeSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    private static void mergeSort(int[] arr, int l, int r) {//归并排序
        if (l >= r) {
            return;
        }
        int mid = (l + r) / 2;
        mergeSort(arr, l, mid);
        mergeSort(arr, mid + 1, r);
        merge(arr, l, mid, r);
    }

    private static void merge(int[] arr, int l, int mid, int r) {
        int[] arrcopy = Arrays.copyOf(arr, arr.length);
        int index = l;
        for (int i = l, j = mid + 1; i <= mid || j <= r; ) {
            if (i > mid) {
                arr[index++] = arrcopy[j];
                j++;
            } else if (j > r) {
                arr[index++] = arrcopy[i];
                i++;
            } else if (arrcopy[i] <= arrcopy[j]) {
                arr[index++] = arrcopy[i];
                i++;
            } else {
                arr[index++] = arrcopy[j];
                j++;
            }
        }
    }
}

小优化

 private static void mergeSort(int[] arr, int l, int r) {//归并排序
        if (l+1 >= r) {//有俩个元素时候直接排序
            int mid = (l + r) / 2;
            merge(arr, l, mid, r);//合并排序
            return;
        }
        int mid = (l + r) / 2;
        mergeSort(arr, l, mid);//制作分组1
        mergeSort(arr, mid + 1, r);//制作分组2
        if(arr[mid]>arr[mid+1]){
        //如果原本排序好了,则不需要排序
            merge(arr, l, mid, r);
        }
    }

堆排序

二叉堆是一颗完全二叉树

堆中的某个结点的值总是不大于父结点的值

package sort;

import java.util.Arrays;
import java.util.Random;

public class HeepSort {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        heepSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static int Len;

    private static void heepSort(int[] arr) {
        //1.将传入的数组堆化 heapify
        Len = arr.length;
        heapify(arr);
        //将最大值与最后一个元素交换 heapify
        for (int i = arr.length - 1; i >= 0; i--) {
            swap(arr, 0, i);
            Len--;
            heapify(arr);
        }
    }

    private static void heapify(int[] arr) {
        for (int i = Len - 1; i >= 0; i--) {
            siftDown(arr, i);
        }
    }

    private static void siftDown(int[] arr, int k) {
        while (leftChild(k) < Len) {
            int j = leftChild(k);
            if (j + 1 < Len && arr[j + 1] > arr[j]) {
                j = rightChild(k);
            }
            if (arr[k] < arr[j]) {
                swap(arr, k, j);
                k = j;
            } else {
                break;
            }
        }
    }

    private static int leftChild(int i) {
        return i * 2 + 1;
    }

    private static int rightChild(int i) {
        return i * 2 + 2;
    }

    private static int parent(int i) {
        return (i - 1) / 2;
    }

    private static void swap(int[] arr, int i, int j) {//交换
        int teme = arr[i];
        arr[i] = arr[j];
        arr[j] = teme;
    }
}

快速排序

时间复杂度O(nlog2n)

空间复杂度 o(1)

稳定性 :不稳定

通过一躺排序将待排序记录独立分隔成独立的两部分,七中一部分巨鹿的关键字均比另一部分小,比另一部分大 ,则可分别对这连部分记录继续进行排序,以达到整个序列有序

注意 l 和1 区分开不要看错了

单路快速排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSCCgeSA-1638188775157)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/image-20211129172314287-16381777981741.png)]

package sort;

import java.util.Arrays;
import java.util.Random;

public class QuickSort1 {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int l, int r) {//单路快速排序
        if (l >= r) {
            return;
        }
        int p = partion(arr, l, r);
        quickSort(arr, l, p - 1);
        quickSort(arr, p + 1, r);
    }

    public static int partion(int[] arr, int l, int r) {
        int v = arr[l];
        int j = l;
        for (int i = l + 1; i <= r; i++) {
            if (arr[i] < v) {
                swap(arr, j + 1, i);
                j++;
            }
        }
        swap(arr, l, j);
        return j;
    }

    private static void swap(int[] arr, int i, int j) {//交换
        int teme = arr[i];
        arr[i] = arr[j];
        arr[j] = teme;
    }
}

优化

public static void quickSort(int[] arr, int l, int r) {//单路快速排序
        if (l >= r) {
            return;
        }
        int p = partion(arr, l, r);
        quickSort(arr, l, p - 1);
        quickSort(arr, p + 1, r);
    }
    private static int partion(int[] arr, int l, int r) {
        //2.优化 随机数不固定  防止极端情况
        swap(arr,l,(int) (Math.random()*(r-l+1)+l));
        int v = arr[l];
        int j = l;
        for (int i = l + 1; i <= r; i++) {
            if (arr[i] < v) {
                swap(arr, j + 1, i);
                j++;
            }
        }
        swap(arr, l, j);
        return j;
    }

双路快速排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2x5kgrqW-1638188775159)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/image-20211129172120570.png)]

比单路快一丢丢

方差小(重复数多)的时候 双路快排会很快

package sort;

import java.util.Arrays;
import java.util.Random;

public class QuickSort2 {
    public static void main(String[] args) {//双路快速排序
        int[] arr = new int[1000];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int l, int r) {
        if (l >= r) {
            return;
        }
        int p = partion(arr, l, r);
        quickSort(arr, l, p - 1);
        quickSort(arr, p + 1, r);
    }
    private static int partion(int[] arr, int l, int r) {
       swap(arr,l,(int) (Math.random()*(r-l+1)+l));
        int v = arr[l];
        int i = l + 1;
        int j = r;
        while (true){
            while (i <= r&&arr[i]<v){
                i++;
            }
            while (j>= l+1&&arr[j]>v){
                j--;
            }
            if (i>j){
                break;
            }
            swap(arr, i, j);
            i++;
            j--;
        }
        swap(arr, l, j);
        return j;
    }

    private static void swap(int[] arr, int i, int j) {//交换
        int teme = arr[i];
        arr[i] = arr[j];
        arr[j] = teme;
    }
}

三路快速排序

将相等的中间值分为中间部分

只有方差小的时候会特别快

package sort;

import java.util.Arrays;
import java.util.Random;

public class QuickSort3 {
    public static void main(String[] args) {//双路快速排序
        int[] arr = new int[10];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int l, int r) {
        if (l >= r) {
            return;
        }
        swap(arr,l,(int) (Math.random()*(r-l+1)+l));
        int v = arr[l];
        int lt = l;
        int gt = r + 1;
        int i = l + 1;
        while (i < gt) {
            if (arr[i] < v) {
                swap(arr, lt + 1, i);
                lt++;
                i++;
            } else if (arr[i] > v) {
                swap(arr, i, gt - 1);
                gt--;
            } else {
                i++;
            }
        }
        swap(arr, l, lt);
        quickSort(arr, l, lt);
        quickSort(arr, gt, r);
    }

    private static void swap(int[] arr, int i, int j) {//交换
        int teme = arr[i];
        arr[i] = arr[j];
        arr[j] = teme;
    }
}

计数排序

计数排序不是基于比较的排序算法,其核心至于将输入的数据转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数

典型的牺牲空间换时间

时间复杂度O(n+m)

空间复杂度 o(n+m)

稳定性 :不稳定

先获取最大最小值 然后创建区间 最后对应++

然后遍历添加

package sort;

import java.util.Arrays;
import java.util.Random;

public class CountingSort {
    public static void main(String[] args) {
        int[] arr = new int[10000];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        countingSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static void countingSort(int[] arr) {
        int min = arr[0];
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        int[] temp = new int[max - min + 1];
        //对应关系 index = number - min number = index + min
        for (int i = 0; i < arr.length; i++) {
            temp[arr[i] - min]++;
        }
        //temp[index] 表示index对应的数字number出现的次数
        int k = 0;
        for (int index = 0; index < temp.length; index++) {
            while (temp[index] != 0) {
                arr[k] = index + min;
                k++;
                temp[index]--;
            }
        }
    }
}

桶排序

是计数排序的升级版

利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定

原理 :假设输入数据服从均匀分布,将数据分到有限数量的桶里面,每个桶再分别排序,(用其他的排序方法).

package sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

public class BucketSort {
    public static void main(String[] args) {
        int[] arr = new int[100];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        bucketSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static void bucketSort(int[] arr) {
        //1.获取最大最小值
        int min = arr[0];
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        //2.计算痛的数量
        int bucketNom=(max-min)/arr.length+1;
        //3.创建所有的桶
        ArrayList<Integer>[] bucksts=new ArrayList[bucketNom];
        for (int i = 0; i <bucksts.length ; i++) {
            bucksts[i]=new ArrayList<>();
        }
        //4.遍历元素分别进桶
        for (int i = 0; i <arr.length ; i++) {
        bucksts[(arr[i]-min)/arr.length].add(arr[i]);
        }
        //5.对每一个桶进行排序
        for (int i = 0; i < bucksts.length; i++) {
            bucksts[i].sort(new Comparator<Integer>() {
                @Override
              public int compare(Integer o1, Integer o2) {
                    return o1.compareTo(o2);
                }
            });
        }
        //6.将桶中的数据放入原数组中
        int index=0;
        for (int i = 0; i <bucksts.length ; i++) {
            for (int j = 0; j <bucksts[i].size() ; j++) {
                arr[index++]=bucksts[i].get(j);
            }
        }
    }
}

基数排序

基数排序是按照地位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级的在前,高优先级相同的低优先级在前。

时间复杂度O(n+m)

空间复杂度 o(n+m)

稳定性 :稳定

package sort;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;

public class RadixSort {
    public static void main(String[] args) {
        int[] arr = new int[100];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(10);
        }
        radixSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static void radixSort(int[] arr) {
        //1.先找到最大值 决定轮数
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        //2.计算位数
        int radex = (max + "").length();
        //3.创建桶
        LinkedList <Integer>[] buckets=new LinkedList[10];
        for (int i = 0; i < buckets.length; i++) {
            buckets[i] = new LinkedList<Integer>();
        }
        //4.不断按优先等级如同 个十 百千 万...
        for (int r = 0; r <=radex ; r++) {
            for (int i = 0; i < arr.length; i++) {
                buckets[getIndex(arr[i],r)].add(arr[i]);
            }
            int index=0;
            for (int i = 0; i <buckets.length ; i++) {
                while (!buckets[i].isEmpty()){
                    arr[index++]=buckets[i].poll();
                }
            }
        }
    }
    private static int getIndex(int num, int r) {
        int ret =0;
        for (int i = 0; i <r ; i++) {
            ret=num%10;
            num/=10;
        }
        return ret;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzsaixuexi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值