冒泡排序
public static void bubble(int[] arr){
for (int i = 0; i < arr.length - 1; i++){
//System.out.println("第"+ (i+1) + "趟排序");
boolean flag = false;
for (int j = 0; j < arr.length - 1 - i; j++){
if (arr[j] > arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
flag = true;
}
}
if (!flag){
break;
}
}
}
选择排序
public static void selectSort1(int[] arr){
for (int i = 0;i < arr.length - 1;i++){
for (int j = i + 1; j < arr.length; j++){
if (arr[j] < arr[i]){
//选取更小的往前替换
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
}
//选择排序
public static void selectSort2(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; // 重置minIndex
}
}
// 将最小值,放在arr[i], 即交换
if (minIndex != i) {
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
插入排序
/**
* 插入排序,将无序列的数据插入到有序列
* 采用移动元素的算法
* @param arr
*/
public static void insertSort(int[] arr){
for (int i = 1; i < arr.length; i++){
if (arr[i] < arr[i-1]){
//将当前元素插入到前面,依次判断前面的元素大小,越小越往前,直到比某个数大
int temp = arr[i];
int j;
//挪动元素
for (j = i -1; j >= 0 && temp < arr[j] ; j--){
//大数后移
arr[j+1] = arr[j];
}
//当temp >= arr[j]时扫描结束,在arr[j]的后面插入temp
arr[j+1] = temp;
}
}
}
希尔排序
/**
* 希尔排序:改进的插入排序
* 采用:步长分组+分组内插入排序算法
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = {8,9,1,7,2,3,5,4,6,0};
shellSort2(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 希尔排序之交换法
*/
public static void shellSort(int[] arr){
for (int gap = arr.length/2; gap > 0; gap/= 2){
for (int i = gap; i < arr.length; i++){
int j = i;//用于分组扫描
//同组以每隔一个步长扫描上一个元素并比较大小
while (j-gap >= 0 && arr[j-gap] > arr[j]){
//交换
int temp = arr[j];
arr[j] = arr[j-gap];
arr[j-gap] = temp;
//j继续向前扫描同组上一个元素
j -= gap;
}
}
}
}
/**
* 希尔排序之移动法
*/
public static void shellSort2(int arr[]){
for (int gap = arr.length/2; gap > 0; gap /= 2){
for (int i = gap; i < arr.length; i++){
int j = i;//用于分组扫描
int temp = arr[j];//用于保存待插入的无序数
while (j - gap >= 0 && arr[j-gap] > temp){
//大数后移
arr[j] = arr[j-gap];//以步长为单位进行后移
j -= gap;
}
//将待插入元素放到 j-gap 的后面
arr[j] = temp;
}
}
}
}
快速排序
/**
* 快速排序
* 采用:左右标兵扫描+递归分治,以空间换时间
*/
public class QuickSort {
public static void main(String[] args) {
}
public static void quickSort(int[] arr,int left, int right){
int l = left;
int r= right;
int pivot = arr[(left + right) / 2];//pivot 中轴值
int temp = 0;//用作交换时的中间变量
while (l < r){
//左标兵从前往后找大数,右标兵从后往前找小数
while (arr[l] < pivot){//大数法则
l++;
}
while (arr[r] > pivot){//小数法则
r--;
}
if (l > r){
break;//在找数过程中,左右标兵碰面了,表示找数失败
}
//找数成功,交换左右标兵的值
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//注意一个bug,当数组中存在两个相等的pivot时,要避免死循环
//比较交换完的元素是否有等于pivot,防止两个相等的pivot进入死循环
if (arr[l] == pivot){
r--;//交换完的元素可以跳过
}
if (arr[r] == pivot){
l++;
}
}
//如果一趟下来,l==r,必须l++,r--,将数组左右区分开
if (l == r){
l++;
r--;
}
//向左递归
quickSort(arr,left,r);
//向右递归
quickSort(arr,l,right);
}
}
归并排序
/**
* 归并排序:采取分而治之的思想
* 采用:分割数组成小块区域,再整合小区域思想
* 采用:递归分治 + temp临时中间数组 ,以空间换时间
*/
public class MergetSort {
public static void main(String[] args) {
int[] arr = { 8, 4, 5, 7, 1, 3, 6, 2 };
int[] temp = new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
System.out.println(Arrays.toString(arr));
}
/**
* 分而治之思想,使用递归去分割数组,然后再合并
* @param arr
* @param left
* @param right
* @param temp
*/
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);
}
}
/**
* 合并算法
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
int i = left;
int j = mid + 1;
int t = 0;//用于对temp数组的遍历
//1.
//先把左右两边(有序)的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完毕为止
while (i <= mid && j <= right){
if (arr[i] <= arr[j]){
temp[t] = arr[i];
t++;
i++;
}else{
temp[t] = arr[j];
t++;
j++;
}
}
//2.//把有剩余数据的一边的数据依次全部填充到temp
while (i <= mid){
temp[t] = arr[i];
t++;
i++;
}
while (j <= right){
temp[t] = arr[j];
t++;
j++;
}
//3.
//将temp数组的元素拷贝到arr
//注意,并不是每次都拷贝所有
//第一次合并 tempLeft = 0 , right = 1 // tempLeft = 2 right = 3 // tL=0 ri=3
t = 0;
int tempindex = left;
while (tempindex <= right){
arr[tempindex] = temp[t];
t++;
tempindex++;
}
}
}
桶排序
/**
* 基数排序(桶排序)
* 以0~9的基数创建二维数组,将数字以个十百千位放入桶中,这样从个位开始排起一直到最高位
* 采用:桶二维数组 + 最大位数几位就会排几次 ,以空间换时间
* (以下算法不支持小数、负数。若数据量过大,该算法会出现OOM)
*/
public class RadixSort {
public static void main(String[] args) {
int arr[] = { 53, 3, 542, 748, 14, 214,10};
radixSory(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 获取数组中,最大数的位数
*/
public static int maxDigit(int[] arr){
int max=arr[0];
for (int i = 1; i < arr.length;i++){
if (arr[i] > max){
max = arr[i];
}
}
String maxStr = max + "";
return maxStr.length();
}
/**
* 基数排序
* @param arr
*/
public static void radixSory(int[] arr){
//创建一个桶二维数组,每一行代表一个桶,总共有10个桶
int[][] bucket = new int[10][arr.length];
//创建桶标志数组,标识该桶有多少个有效值
int[] bucketElementCounts = new int[10];
//获取最大有几位数
int maxDigit = maxDigit(arr);
double chu = (double) maxDigit;
chu = Math.pow(10,chu-1);//三位数,截取百位时要除以100,四位数则除以1000
for (int round = 1; round <= chu; round *= 10) {
//截取位数并放入对应桶
for (int j = 0; j < arr.length; j++) {
int digit = arr[j] / round % 10;
//将截取的位数放到对应下标的桶中
int BucketColumn = bucketElementCounts[digit];//得到对应桶中已经放入多少个元素
bucket[digit][BucketColumn] = arr[j];//放入
bucketElementCounts[digit]++;
}
//将桶中的元素再顺序放回arr数组
int index = 0;
for (int m = 0; m < bucket.length; m++) {
if (bucketElementCounts[m] != 0) {//如果改行有数据
//遍历该行
for (int n = 0; n < bucketElementCounts[m]; n++) {
arr[index++] = bucket[m][n];
}
}
//取出改行数据后,将改行数据清零
bucketElementCounts[m] = 0;//将计数器置零
}
}
}
}
堆排序
https://www.cnblogs.com/chengxiao/p/6129630.html