JAVA基础算法与数据结构
常见排序算法
插入排序
直接插入排序(有序表和无序表的排序)
package com.kuang.pojo;
import java.util.Arrays;
public class insertSort {
public static void main(String[] args) {
int[] arr ={103,-1,94,73};
insertSort(arr);
}
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int insertVal=arr[i];
int insertIndex=i-1;
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex+1]=arr[insertIndex];//insertIndex后移 找插入位置
insertIndex--;
}
arr[insertIndex+1]=insertVal;//插入位置找到 两数交换
System.out.println(Arrays.toString(arr));
}
}
}
速度测试:大概5秒
希尔排序(分组交换法或移位法)
重点移位法:
package com.kuang.pojo;
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
int[] arr={8,9,4,6,3,0,2,7,5};
System.out.println("排序前");
System.out.println(Arrays.toString(arr));
ShellSort(arr);
System.out.println("排序后");
System.out.println(Arrays.toString(arr));
}
public static void ShellSort(int[] arr) {
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
//从gap开始 逐个对其所在的组进行插入排序
for (int i = gap; i < arr.length; i++) {
int j=i;
int temp=arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
//移动
arr[j]=arr[j-gap];
j=j-gap;
}
//退出while后 给temp插入位置
arr[j]=temp;
}
}
}
}
}
速度测试:大概1秒
选择排序
简单选择排序(从变动的数组中选择最小或最大的数和数组前面的数作比较 再交换)
package com.kuang.pojo;
import java.util.Arrays;
public class xz {
public static void main(String[] args) {
int[] arr = {344, 193, 1, 48};
System.out.println("排序前");
System.out.println(Arrays.toString(arr));
xz(arr);
System.out.println("排序后");
System.out.println(Arrays.toString(arr));
}
private static void xz(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex=i;
int min=arr[i];
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min=arr[j];//重置min
minIndex=j;//重置miniIndex
}
}
//将最小值放在arr[i] 即交换
if (minIndex != i) {
arr[minIndex]=arr[i];
arr[i]=min;
}
}
}
}
速度测试:大概2秒
交换排序
冒泡排序(相邻数之间比大小排序 随着索引的移动 排序次数逐渐减少 直到排序完成)
package com.kuang.pojo;
import java.util.Arrays;
public class mp {
public static void main(String[] args) {
int arr[] ={3,9,-1,10,-2};
int temp=0;
boolean flag=false;//标识量 表示是否进行过交换
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]) {
flag=true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
System.out.print(Arrays.toString(arr));
if (!flag) {//一趟中一次没有交换过
break;
}else{
flag=false;//重置
}
}
}
}
速度测试:大概14秒
快速排序(取中间值 按左小右大的方式排列 依次按递归方式排序)
package com.kuang.pojo;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr={-4,48,0,-6,394,9};
QuickSort(arr,0,arr.length-1);
System.out.println("arr="+ Arrays.toString(arr));
}
public static void QuickSort(int[] arr,int left,int right) {
int l=left;
int r=right;
int pivot=arr[(left+right)/2];
int temp=0;//中间值
//while循环的目的是 把比pivot小的数放在左面 比pivot大的数放在右面
while (l < r) {
//从左面一直找 直到找到大于等于pivot的值
while (arr[l] < pivot) {
l+=1;
}
//从最右面一直找 直到找到小于等于pivot的值
while (arr[r] > pivot) {
r-=1;
}
if (l >= r) {
break;
}
//交换
temp=arr[l];
arr[l]=arr[r];
arr[r]=temp;
//如果交换完 发现arr[l]==pivot 相等r-- 前移
if (arr[l] == pivot) {
r-=1;
}
//如果交换完 发现arr[r]==pivot 相等l++ 后移
if (arr[r] == pivot) {
l+=1;
}
}
//若l=r 必须 l++ r-- 防止死循环
if (l == r) {
l+=1;
r-=1;
}
//向左递归
if (left < r) {
QuickSort(arr,left,r);
}
//向右递归
if (right > l) {
QuickSort(arr,l,right);
}
}
}
速度测试:大概2秒
堆排序
代码参考图: 最后为 4 5 6 8 9
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int arr[] = {4, 6, 8, 5, 9};
heapSort(arr);
}
public static void heapSort(int arr[]) {
int temp = 0;
System.out.println("堆排序");
//分部完成
// adjustHeap(arr,1,arr.length);
// System.out.println("第一次"+ Arrays.toString(arr));
// adjustHeap(arr,0,arr.length);
// System.out.println("第二次"+ Arrays.toString(arr));//9 6 8 5 4
//最终代码
//将无序数列构建成一个堆 根据升序降序需求选择大项堆或小项堆
//将堆项元素和末尾元素交换 反复调整 交换步骤 直到有序
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
for (int j = arr.length - 1; j > 0; j--) {
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr, 0, j);
}
System.out.println("数组=" + Arrays.toString(arr));//4 5 6 8 9
}
//将一个数组调整成一个大顶堆 int arr[]={4,6,8,5,9};==>adjustHeap==>得到{4,9,8,5,6}
//若再次调用 得到{9,6,8,5,4}
// arr 待调整数组 i 表示非叶子节点在数组中的索引
// lenght 表示对多少个元素调整
public static void adjustHeap(int arr[], int i, int lenght) {
int temp = arr[i];//取出当前元素值
//开始调整 k:以i为代表的非叶子节点的左子节点
for (int k = i * 2 + 1; k < lenght; k = k * 2 + 1) {
if (k + 1 < lenght && arr[k] < arr[k + 1]) {
//说明左子节点的值小于右子节点的值
k++;
}
if (arr[k] > temp) {
//如果子节点大于父节点
arr[i] = arr[k];//把大的值赋给当前节点 然后循环
i = k;
} else {
break;
}
}
//循环结束后 已经将以i为父节点的数的最大值 放在了最顶部
arr[i] = temp;
}
}
速度测试:大概5秒
归并排序
import java.util.Arrays;
public class MergetSort {
public static void main(String[] args) {
int[] arr={3,8,7,4,6,9,2,1};
//归并需要一个额外空间
int temp[]=new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
System.out.println("排序后="+ Arrays.toString(arr));
}
//分加和的方法
public static void mergeSort(int[] arr,int left,int right,int[] temp) {
if (left < right) {
int mid=(left+right)/2;
//向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归进行分解
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
//合并的方法
public static void merge(int[] arr,int left,int mid,int right,int[] temp) {
int i=left;//初始化i 左边有序列的初始索引
int j=mid+1;//初始化j 右边有序列的初始索引
int t=0;
//一 先把左右两边数据按照规则填充到temp数组
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp[t] = arr[i];
t += 1;
i += 1;
} else {//反之 将右边数据填充到temp数组中
temp[t]=arr[j];
t+=1;
j+=1;
}
}
//二 把剩余一边的数据依次填充到temp中
while (i <= mid) {//若左边有剩余 则全部填充到temp
temp[t]=arr[i];
t += 1;
i += 1;
}
while (j<= right) {//若右边有剩余 则全部填充到temp
temp[t]=arr[j];
t += 1;
j += 1;
}
//三 将temp数组拷贝到arr
t=0;
int tempLeft=left;
while (tempLeft <= right) {
arr[tempLeft]=temp[t];
t+=1;
tempLeft+=1;
}
}
}
速度测试:大概3秒
基数排序
(桶排序 分别按照个位 十位 百位... 把数按顺序放在相应的桶下标 再按顺序组合 进行几轮后出结果)
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int arr[] = {48, 9, 589, 307, 23, 135};
radixSort(arr);
}
public static void radixSort(int[] arr) {
//得到数组最大的位数
int max=arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max=arr[i];
}
}
//得到最大位数是几位数
int maxLength=(max+"").length();
int[][] bucket = new int[10][arr.length];
int[] bucketCounts = new int[10];
//循环代码处理
for (int i = 0, n=1; i < maxLength; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
int digitElement = arr[j] /n % 10;
//放到对应桶中
bucket[digitElement][bucketCounts[digitElement]] = arr[j];
bucketCounts[digitElement]++;
}
//依次取出数据 放入原来数组
int index = 0;
//遍历
for (int k = 0; k < bucketCounts.length; k++) {
//若桶中有数据 我们才放入原数组
if (bucketCounts[k] != 0) {
//循环
for (int l = 0; l < bucketCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
bucketCounts[k] = 0;
}
System.out.println("arr="+ Arrays.toString(arr));
}
}
}
速度测试:不到1秒 非常快
查找算法
二分查找
前提 该数组必须有序
import java.util.ArrayList;
import java.util.List;
public class BinarySearch {
public static void main(String[] args) {
int arr[] = {1, 8, 10, 38, 49, 840, 2000,10,10};
//int resIndex = binarySearch(arr, 0, arr.length - 1, 10);
//System.out.println("resIndex=" + resIndex);
List<Integer> resIndexlist=binarySearch2(arr,0,arr.length-1,10);
System.out.println("resIndexlist=" + resIndexlist);
}
/*
arr 数组
left 左边的索引
right 右边的索引
findVal 要查找的值
*/
public static int binarySearch(int[] arr, int left, int right, int findVal) {
//为防止出现死递归
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if (findVal > midVal) {
//向右递归
return binarySearch(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {//向左递归
return binarySearch(arr, left, mid - 1, findVal);
} else {
return mid;
}
}
public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
//为防止出现死递归
if (left > right) {
return new ArrayList<Integer>();
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if (findVal > midVal) {
//向右递归
return binarySearch2(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {//向左递归
return binarySearch2(arr, left, mid - 1, findVal);
} else {
ArrayList<Integer> resIndexlist = new ArrayList<Integer>();
//向左边扫描 将所有满足条件的下标 都加入到集合中
int temp = mid - 1;
while (true) {
if (temp < 0 || arr[temp] != findVal) {
break;
}
//否则就放入集合中
resIndexlist.add(temp);
temp -= 1;//左移
}
resIndexlist.add(mid);
//右移
temp =mid+1;
while (true) {
if (temp > arr.length - 1 ||
