这里写目录标题
1、冒泡排序(每一躺选出一个最大或者最小放在最后)
import java.util.Arrays;
/**
*
* <p>Title: a1BubbleSort</p>
* <p>Description: 稳定的排序算法 </p>
* @author Shenxinyuan
* @date 2020年9月11日
*/
public class a1BubbleSort {
public static void main(String[] args) {
// System.out.println("你好,java!");
int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
BubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
*
* <p>Title: BubbleSort</p>
* <p>Description: 空间复杂度(O(1)) 时间复杂度(O(n^2))</p>
* @param arr
*/
public static void BubbleSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
//优化,置一个变量判断是否发生交换,每一趟都少遍历比较一个数
boolean label = true;
for (int i = 0; i < arr.length && label; i++) {
label = false;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j + 1] < arr[j]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
label = true;
}
}
}
}
}
2、简单选择排序及其优化
思想:每一躺找出最大或者最小的元素的下标跟对应位置交换
优化思想:每一躺找出最大和最小的元素的下标跟对应位置交换
import java.util.Arrays;
public class a2SelectSort {
public static void main(String[] args) {
int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
//SelectSort(arr);
optimizedSelectSort(arr);
System.out.println(Arrays.toString(arr));
}
//不稳定的排序算法,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,
// 那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法
private static void SelectSort(int[] arr) {
// TODO Auto-generated method stub
if(arr==null || arr.length==0) {
return;
}
//时间复杂度(O(n^2)) 空间复杂度(O(1))
//从待排序列选择最大或最小数据跟第一个交换
for(int i =0;i<arr.length;i++) {
int minIndex = i;
for(int j =i+1;j<arr.length;j++) {
//升序
if(arr[j]<arr[minIndex]) {
minIndex = j;
}
}
if(minIndex != i) {
swap(i, minIndex, arr);
}
}
}
//从待排序列中选择最大值和最小值选择排列
//时间复杂度(O(n/2))既O(N) 空间复杂度(O(1))
private static void optimizedSelectSort(int[] arr) {
if(arr == null|| arr.length == 0) {
return;
}
for(int i=0;i<=(arr.length>>1);i++) {
int minIndex = i;
int maxIndex = i;
for(int j =i+1;j<=arr.length-1-i;j++) {
if(arr[j]<arr[minIndex]) {
minIndex = j;
continue;
}
if(arr[j]>arr[maxIndex]) {
maxIndex = j;
}
}
if(minIndex != i) {
swap(i, minIndex, arr);
}
if(maxIndex != i) {
swap(arr.length-1-i, maxIndex, arr);
}
}
}
private static void swap(int i, int j, int[] arr) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
3、插入排序
思想:在有序序列中找第一个比无需序列中第一个元素大的元素的下标,然后将该下标的元素放到有序序列的对应元素的前边
优化思想:在有序列中找第一个比无序序列中第一个元素小的元素的下标,然后将该下标的元素放到有序序列对应元素的后边。
import java.util.Arrays;
public class a3InsertSort {
public static void main(String[] args) {
int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
//InsertSort(arr);
optimizedInsertSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void InsertSort(int[] arr) {
// TODO Auto-generated method stub
if(arr == null||arr.length==0) {
return;
}
for(int i =0;i<arr.length;i++) {
int j;
//在前i个升序数据,找到比第i个数据大的数,跳出循环开始交换数据
for(j =0;j<i;j++) {
if(arr[j] > arr[i]) {
break;
}
}
//以交换的形式,挪动数据arr[i]到有序数据的第j位
for(int k = i-1;k>= j;k--) {
swap(k+1, k, arr);
}
}
}
private static void optimizedInsertSort(int[] arr) {
// TODO Auto-generated method stub
if(arr == null||arr.length==0) {
return;
}else {
for(int i= 0;i<arr.length;i++) {
int j;
int temp = arr[i];//把第i个数据保存在temp中,方便交换数据
//升序
for(j = i-1;j>=0;j--) {
//在前i个有序数据中招第一个比第i个小的数,交换
if(arr[j] < temp) {
break;
}else {
//移动数据ing
arr[j+1] = arr[j];
}
}
//找到该位置,把temp给arr[j+1]
arr[j+1] = temp;
}
}
}
private static void swap(int i, int j, int[] arr) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
4、希尔排序(优化插入排序的拓展)
import java.util.Arrays;
public class a3ShellSort {
public static void main(String[] args) {
int[] arr = {10, 8, 1, 0, 19,
2, 4, 28, 30, 56,
24, 9, 5, 15, 12,
11, 44, 77};
shellSortSort(arr, 3);
//System.out.println(Arrays.toString(arr));
for(int demo:arr) {
System.out.print(demo+" ");
}
}
private static void shellSortSort(int[] arr, int gap) {
// TODO Auto-generated method stub
while(gap >= 1) {//直到间距为1
for(int i =0;i<arr.length;i++) {
int j =0;
int temp = arr[i];
for(j = i-gap;j>=0;j-=gap) {
if(arr[j] <= temp) {
break;
}else {
arr[j+gap] = arr[j];
}
}
arr[j+gap] = temp;
}
gap--;
}
}
}
5、快速选择排序
import java.util.Arrays;
import java.util.Stack;
public class a4QuickSort {
public static void main(String[] args) {
int[] arr = {10, 2, 19, 0, 8, 100, 28, 7, 1, 15,7};
quickSort(arr);
//quickSortByWhile(arr);
System.out.println(Arrays.toString(arr));
}
private static void quickSort(int[] arr) {
// TODO Auto-generated method stub
if (arr.length == 0 || arr == null) {
return ;
} else {
quick(arr,0,arr.length-1);
}
}
private static void quick(int[] arr, int low, int high) {
// TODO Auto-generated method stub
int partition = partition(low,high,arr);
//partition左边的数据都比它小,右边的数据都比他大
//判断左边的数据大于1 个
if(partition > low +1){
quick(arr, low,partition-1);
}
//判断右边的数据大于1 个
if(partition < high-1){
quick(arr, partition+1,high);
}
}
private static int partition(int low, int high, int[] arr) {
// TODO Auto-generated method stub
int mark = arr[low];
while (low < high) {
//从后往前找比基准数据小的元素
while (arr[high] >= mark && low < high) {
high--; //high可能会越界
}
if (low == high) {
break;
}
if(arr[high]<mark){
arr[low] = arr[high];
}
//从后往前找比基准数据小的元素
while (arr[low] <= mark && low < high) {
low++;
}
if (low == high) {
break;
}
if(arr[low]>mark) {
arr[high] = arr[low];
}
}
arr[low] = mark;
return low;
}
private static void quickSortByWhile(int[] arr) {
// TODO Auto-generated method stub
//参数合法性判断
if(arr == null||arr.length==0){
return;
}
Stack<Integer> stack = new Stack<>();
stack.push(0);
stack.push(arr.length-1);
while(!stack.isEmpty()){
int high = stack.pop();
int low = stack.pop();
//mark左边的数字都比他小,右边的数值都比他大
int mid = partition(low,high,arr);
//保证partition后的徐磊长度大于一
//判断左边序列的个数是否大于一
if(mid > low+1){
stack.push(low);
stack.push(mid-1);
}
//判断右边序列的个数是否大于一
if(mid < high-1){
stack.push(mid+1);
stack.push(high);
}
}
}
}
6、堆排序
import java.util.Arrays;
//堆排序的时间复杂度为:O(nlogn)
//空间复杂度:因为堆排序是就地排序,空间复杂度为常数:O(1)
public class a5HeapSort {
public static void main(String[] args) {
int[] arr = {16, 7, 3, 20, 17, 8};
heapSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
System.out.println(Arrays.toString(arr));
}
private static void heapSort(int[] arr) {
// TODO Auto-generated method stub
//创建堆,大根
for (int i = (arr.length - 1) / 2; i >= 0; i--) {
//从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(arr, i, arr.length);
}
//调整堆结构+交换堆顶元素与末尾元素
for (int i = arr.length - 1; i > 0; i--) {
//将堆顶元素与末尾元素进行交换
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//重新对堆进行调整
adjustHeap(arr, 0, i);
}
}
private static void adjustHeap(int[] arr, int parent, int length) {
// TODO Auto-generated method stub
//将temp作为父节点
int temp = arr[parent];
//左孩子
int lChild = 2 * parent + 1;
while (lChild < length) {
//右孩子
int rChild = lChild + 1;
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (rChild < length && arr[lChild] < arr[rChild]) {
lChild++;
}
// 如果父结点的值已经大于孩子结点的值,则直接结束
if (temp >= arr[lChild]) {
break;
}
// 把孩子结点的值赋给父结点
arr[parent] = arr[lChild];
//选取孩子结点的左孩子结点,继续向下筛选
parent = lChild;
lChild = 2 * lChild + 1;
}
arr[parent] = temp;
}
}
7、归并排序
public class a6MergeSort {
public static void main(String[] args) {
int[] a = {49, 38, 65, 97, 76, 13, 27, 50};
mergeSort(a, 0, a.length - 1);
System.out.println("排好序的数组:");
for (int e : a)
System.out.print(e + " ");
}
private static void mergeSort(int[] a, int start, int end) {
// TODO Auto-generated method stub
if (start < end) {//当子序列中只有一个元素时结束递归
int mid = (start + end) / 2;//划分子序列
mergeSort(a, start, mid);//对左侧子序列进行递归排序
mergeSort(a, mid + 1, end);//对右侧子序列进行递归排序
merge(a, start, mid, end);//合并
}
}
//空间复杂度度较大O(n)
//时间复杂度:nlog2n
private static void merge(int[] a, int left, int mid, int right) {
// TODO Auto-generated method stub
int[] tmp = new int[a.length];//辅助数组
int p1 = left, p2 = mid + 1, k = left;//p1、p2是检测指针,k是存放指针
while (p1 <= mid && p2 <= right) {
if (a[p1] <= a[p2])
tmp[k++] = a[p1++];
else
tmp[k++] = a[p2++];
}
//把剩余元素放入temp临时数组
while (p1 <= mid) tmp[k++] = a[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
while (p2 <= right) tmp[k++] = a[p2++];//同上
//复制回原素组
for (int i = left; i <= right; i++)
a[i] = tmp[i];
}
}
8、计数排序
非比较类型的排序
/**
* 计数排序
*
* @param array
* @return
*/
public static int[] CountingSort(int[] array) {
if (array.length == 0) return array;
int bias, min = array[0], max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max)
max = array[i];
if (array[i] < min)
min = array[i];
}
bias = 0 - min;
int[] bucket = new int[max - min + 1];
Arrays.fill(bucket, 0);
for (int i = 0; i < array.length; i++) {
bucket[array[i] + bias]++;
}
int index = 0, i = 0;
while (index < array.length) {
if (bucket[i] != 0) {
array[index] = i - bias;
bucket[i]--;
index++;
} else
i++;
}
return array;
}
9、桶排序
放倒的桶排序,或者“放倒的hashmap”
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
/**
* 桶排序
*
* @param array
* @param bucketSize
* @return
*/
public static ArrayList<Integer> BucketSort(ArrayList<Integer> array, int bucketSize) {
if (array == null || array.size() < 2)
return array;
int max = array.get(0), min = array.get(0);
// 找到最大值最小值
for (int i = 0; i < array.size(); i++) {
if (array.get(i) > max)
max = array.get(i);
if (array.get(i) < min)
min = array.get(i);
}
int bucketCount = (max - min) / bucketSize + 1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
ArrayList<Integer> resultArr = new ArrayList<>();
for (int i = 0; i < bucketCount; i++) {
bucketArr.add(new ArrayList<Integer>());
}
for (int i = 0; i < array.size(); i++) {
bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
}
for (int i = 0; i < bucketCount; i++) {
if (bucketSize == 1) { // 如果带排序数组中有重复数字时 感谢 @见风任然是风 朋友指出错误
for (int j = 0; j < bucketArr.get(i).size(); j++)
resultArr.add(bucketArr.get(i).get(j));
} else {
if (bucketCount == 1)
bucketSize--;
ArrayList<Integer> temp = BucketSort(bucketArr.get(i), bucketSize);
for (int j = 0; j < temp.size(); j++)
resultArr.add(temp.get(j));
}
}
return resultArr;
}
10、基数排序
有一点点类似于hashmap的数据结构
基数排序基于分别排序,分别收集,所以是稳定的。
/**
* 基数排序
* @param array
* @return
*/
public static int[] RadixSort(int[] array) {
if (array == null || array.length < 2)
return array;
// 1.先算出最大数的位数;
int max = array[0];
for (int i = 1; i < array.length; i++) {
max = Math.max(max, array[i]);
}
int maxDigit = 0;
while (max != 0) {
max /= 10;
maxDigit++;
}
int mod = 10, div = 1;
ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++)
bucketList.add(new ArrayList<Integer>());
for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
for (int j = 0; j < array.length; j++) {
int num = (array[j] % mod) / div;
bucketList.get(num).add(array[j]);
}
int index = 0;
for (int j = 0; j < bucketList.size(); j++) {
for (int k = 0; k < bucketList.get(j).size(); k++)
array[index++] = bucketList.get(j).get(k);
bucketList.get(j).clear();
}
}
return array;
}
部分参考自https://www.cnblogs.com/xikui/p/11196148.html