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(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;
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];
}
}