1.二分查找(Binary Search)时间复杂度O(logn),前提是数组必须是已经排好序的。遍历查找时间复杂度O(n)。
1) 将查找的目标元素,与数组中间位置的元素进行比较。
2) 如果相等,则表示找到了。
3) 如果目标元素小于中间元素,目标元素只可能出现在中间元素之前,将中间元素前的子数组再进行二分查找。
4) 如果目标元素大于中间元素,将中间元素后的子数组再进行二分查找。
import java.util.Arrays;
import java.util.Scanner;
//二分查找
public class Main {
public static void main(String[] args) {
int[] arr={3,4,8,11,15,17,22,23,29};
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println(binarySearch(arr,n,0,arr.length));
}
public static int binarySearch(int[] arr,int n,int low,int high)
{
int mid=(low+high)/2;
if(n==arr[mid]){
return mid;
}else if(n>arr[mid]){
return binarySearch(arr,n,mid+1,high);
}else{
return binarySearch(arr,n,low,mid-1);
}
}
}
2.十大排序算法
(1)冒泡排序
import java.util.Arrays;
import java.util.Scanner;
//冒泡排序
public class Main {
public static void main(String[] args) {
int[] arr={2,1,6,7,4,17,9,15,29,27,3,34,13,5,21};
//第一层循环是一共进行几次,第二层循环是最右边每确定一个值需要比较几次
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])
{
int a;
a=arr[j];
arr[j]=arr[j+1];
arr[j+1]=a;
}
}
}
for(int item:arr)
{
System.out.println(item);
}
}
}
(2)选择排序
import java.util.Arrays;
import java.util.Scanner;
//选择排序
public class Main {
public static void main(String[] args) {
int[] arr={2,1,6,7,4,17,9,15,29,27,3,34,13,5,21};
int min;
for(int i=0;i<arr.length-1;i++)
{
min=i;
for(int j=i+1;j<arr.length;j++)
{
if(arr[j]<arr[min])
{
min=j;
}
}
if(i!=min)
{
int a=arr[i];
arr[i]=arr[min];
arr[min]=a;
}
}
System.out.println(Arrays.toString(arr));
}
}
(3)插入排序
import java.util.Arrays;
import java.util.Scanner;
//插入排序int[] arr={2,1,6,7,4,17,9,15,29,27,3,34,13,5,21};
public class Main {
public static void main(String[] args) {
int[] arr={2,1,6,7,4,17,9,15,29,27,3,34,13,5,21};
//第一个数字已经排好,从后面的数字里找位置插入
for(int i=1;i<arr.length;i++)
{
int temp=arr[i];
//定义一个指针j用来寻找插入位置
int j=i-1;
while(j>=0&&arr[j]>temp)
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
System.out.println(Arrays.toString(arr));
}
}
(4)快速排序
import java.util.Arrays;
import java.util.Scanner;
//快速排序int[] arr={7,4,10,2,6,9,8};
public class Main {
public static void main(String[] args) {
int[] arr={7,4,10,2,6,9,8};
QuickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void QuickSort(int[] arr,int left,int right)
{
if(left>right)return;
//注意一次快排只需要找到右边第一个小于pivot的位置和左边第一个大于pivot的位置
//只要没相遇,就交换找到的两个值
//然后将pivot移到中间,将小的值移动到左边(千万不要忘记不相遇的条件)
int pivot=arr[left];
int i=left;
int j=right;
while(i<j){
//需要保证在i和j移动的过程中不会相遇
while(i<j&&arr[j]>=pivot)
j--;
while(i<j&&arr[i]<=pivot)
i++;
if(i<j)
{
int a=arr[i];
arr[i]=arr[j];
arr[j]=a;
}
}
arr[left]=arr[i];
arr[i]=pivot;
QuickSort(arr,left,i-1);
QuickSort(arr,i+1,right);
}
}
(5)希尔排序
import java.util.Arrays;
import java.util.Scanner;
//希尔排序int[] arr={7,4,10,2,6,9,8};
public class Main {
public static void main(String[] args) {
int[] arr={7,4,10,2,6,9,8};
//一共进行这些次分组,每个分组分别进行插入排序
for(int step=arr.length/2;step>=1;step/=2)
{
//对这些组数据进行插入排序
for(int i=step;i<arr.length;i++)
{
int temp=arr[i];
int j=i-step;
while(j>=0&&arr[j]>temp)
{
arr[j+step]=arr[j];
j-=step;
}
arr[j+step]=temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
(6)归并排序
import java.util.Arrays;
import java.util.Scanner;
//归并排序
public class Main {
public static void main(String[] args) {
int[] arr=new int[]{5,7,2,6,9,1};
mergeSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void mergeSort(int[] arr, int start, int end)
{
//不断分割
if(start==end)return;
int mid=(start+end)/2;
mergeSort(arr,start,mid);
mergeSort(arr,mid+1,end);
merge(arr,start,mid+1,end);
}
public static void merge(int[] arr, int start, int mid, int end)
{
int[] result=new int[end-start+1];
int p1=start;
int p2=mid;
//合并两个数组
for(int i=0;i<result.length;i++)
{
//arr[p1]<arr[p2]&&p1<mid||p2>end(取反是错误的判断)
//arr[p1]>=arr[p2]||p1>=mid&&p2<=end
if(p2>end||arr[p1]<=arr[p2]&&p1<mid)
{
result[i]=arr[p1];
p1++;
}else if(p2<=end&&arr[p1]>arr[p2]||p1>=mid)
{
result[i]=arr[p2];
p2++;
}
}
for(int i=0;i< result.length;i++)
{
arr[start+i]=result[i];
}
}
}
(7)桶排序
import java.util.Arrays;
//桶排序
public class Main {
public static void main(String[] args) {
int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
int max=getMax(arr);
int min=getMin(arr);
int basketSize=5;
int basketCount=(max-min)/basketSize+1;
int[][] basket=new int[basketCount][0];
for(int j=0;j<arr.length;j++)
{
//计算放到第几个桶里面
int count=(arr[j]-min)/basketSize;
//注意这里的赋值情况
basket[count]=arrayAppend(basket[count],arr[j]);
//对桶内元素进行排序
insertSort(basket[count]);
}
for(int i=0;i<basketCount;i++)
{
for(int j=0;j<basket[i].length;j++)
{
System.out.print(basket[i][j]+" ");
}
}
}
public static void insertSort(int[] arr)
{
//只需要排最后一个元素即可
int key=arr[arr.length-1];
int j=arr.length-1;
while(j>0&&arr[j-1]>key)
{
arr[j]=arr[j-1];
j--;
}
arr[j]=key;
}
public static int[] arrayAppend(int[] arr, int value)
{
arr= Arrays.copyOf(arr,arr.length+1);
//把加入的元素放到桶的最后
arr[arr.length-1]=value;
return arr;
}
public static int getMax(int[] arr)
{
int max=0;
for(int i=1;i<arr.length;i++)
{
if(arr[i]>arr[0])
{
max=i;
}
}
return arr[max];
}
public static int getMin(int[] arr)
{
int min=arr[0];
for(int i=1;i<arr.length;i++)
{
if(arr[i]<min)
min=arr[i];
}
return min;
}
}
(8)堆排序
import java.util.Arrays;
import java.util.Scanner;
//堆排序
public class Main {
public static void main(String[] args) {
int[] arr = {5, 21, 2, 18, 6, 17, 4, 0, 7, 13, 3, 15, 9, 10, 1};
heapSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void heapify(int[] arr,int start,int end)
{
int largest=start;
int lson=start*2+1;
int rson=start*2+2;
if(lson<=end && arr[lson]>arr[largest])
largest=lson;
if(rson<=end && arr[rson]>arr[largest])
largest=rson;
if(largest!=start)
{
int a=arr[largest];
arr[largest]=arr[start];
arr[start]=a;
heapify(arr,largest,end);
}
}
public static void heapSort(int[] arr,int start,int end)
{
//从第一个非叶节点从下往上构建大顶堆,最开始必须有规律
for(int i=end/2-1;i>=start;i--)
{
heapify(arr,i,end);
}
for(int i=end;i>=0;i--)
{
//将大顶堆最大值转移到最后面
int a=arr[0];
arr[0]=arr[i];
arr[i]=a;
//剩余的部分继续构建大顶堆
heapify(arr,start,i-1);
}
}
}
(9)计数排序
import java.util.Arrays;
//计数排序,不太懂为什么重新计数后会正好对应排序好后的序号
public class Main {
public static void main(String[] args) {
int[] arr = {5, 4, 2, 5, 2, 3, 5, 9, 5, 8, 3, 2, 2, 6, 4, 7, 3, 9, 1};
int max=getMax(arr);
int min=getMin(arr);
int[] bucket=new int[max-min+1];
for(int i=0;i<arr.length;i++)
{
bucket[arr[i]-min]++;
}
//不明白为什么要重新排序
for(int i=1;i< bucket.length;i++)
{
bucket[i]=bucket[i]+bucket[i-1];
}
//重新计数后的序列直接与排好序的序列相关
int[] result=new int[arr.length];
for(int i=0;i<arr.length;i++)
{
//第一次用减1,每次用完后都要减1,不然就影响相同的数重新排序
bucket[arr[i]-min]--;
int a=bucket[arr[i]-min];
result[a]=arr[i];
}
System.out.println(Arrays.toString(result));
}
public static int getMax(int[] arr)
{
int max=arr[0];
for(int i=1;i<arr.length;i++)
{
if(arr[i]>max)
max=arr[i];
}
return max;
}
public static int getMin(int[] arr)
{
int min=arr[0];
for(int i=1;i<arr.length;i++)
{
if(arr[i]<min)
min=arr[i];
}
return min;
}
}
(10)基数排序
import java.util.Arrays;
import java.util.Scanner;
import java.util.Random;
import static java.lang.Math.pow;
//基数排序
public class Main {
public static void main(String[] args) {
//随便生成一个大小指定的随机数组
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
int[] arr=new int[num];
Random random=new Random();
for(int i=0;i<arr.length;i++)
{
//生成一个0~100的随机数
arr[i]=random.nextInt(100)+1;
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(radixSort(arr)));
}
public static int[] radixSort(int[] arr)
{
int max=Integer.MIN_VALUE;
for(int i:arr)
{
max=Math.max(max,i);
}
//把数字转换成字符,可以直接给出数字的长度
int count=(max+"").length();
for(int i=0;i<count;i++)
{
int[][] busket=new int[10][arr.length];
int[] index=new int[arr.length];
//从后往前位数,依次放入容器
for(int j=0;j<arr.length;j++)
{
//个位数处以10^0,十位数处以10^1,百位数处以10^2(幂指运算返回值是double)
int unitNum= (int) (arr[j]/pow(10,i)%10);
//根据最低一位数放入数组
busket[unitNum][index[unitNum]++]=arr[j];
}
for(int j=0,arrIndex=0;j<busket.length;j++)
{
for(int k=0;k<index[j];k++)
{
if(busket[j][k]!=0)
arr[arrIndex++]=busket[j][k];
}
}
}
return arr;
}
}