本文章介绍了所有常用的查找和排序
排序的有写 代码 可以直接复制
这里重点说一句 希尔排序 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;
}
}