package com.sort;
import java.util.Arrays;
public class sortAll {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {26,47,50,2,3,46,47,38,5,15,19,44,4,27,36};
//insertSort(arr);
binaryInsertSort(arr);
//selectSort(arr);
//bubbleSort(arr);
//shellSort(arr);
//mergeSort(arr,0,arr.length-1);
//quickSort(arr,0,arr.length-1);
//arr = heapSort(arr);
System.out.println(Arrays.toString(arr));
}
//===================================插入类排序================================================
//==========================================================================================
//直接插入排序
public static void insertSort(int[] arr){
for(int i = 1; i<arr.length; i++){ //第一个元素当做有序 从第二个元素开始进行插入
for(int j = i-1; j>=0; j--){ //每个元素依次 与其前面 有序的元素 进行比较 小于则交换
if(arr[j] > arr[j+1]){ //这里 注意要用j+1 而不是i 因为我们跟踪 i的位置 需要用j来表示
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
//因为每次的插入都是有序数组 所以 在查找位置的时候 可以采用 折半查找 ----即 折半插入排序
}
}
}
System.out.print("直接插入排序: ");
}
//==========================================================================================
//折半插入排序
public static void binaryInsertSort(int[] arr){
for(int i =1; i<arr.length; i++){
int temp = arr[i]; //待插入的元素
int low = 0; //折半查找的首尾
int high = i-1;
//折半查找
while(low<=high){
int mid = (low+high)/2;
if(temp > arr[mid]){
low = mid +1;
}else{
high = mid -1;
}
}
//移动位置 空出待插入位置
for(int j = i; j>low; j--){ //通过折半查找 low == high 即为待插入位置
arr[j] = arr[j-1];
}
arr[low] = temp;//将元素放入最终位置
}
System.out.print("折半插入排序: ");
}
//==========================================================================================
// 希尔排序--缩小增量排序
public static void shellSort(int[] arr) {
int n = arr.length;
for (int h = n / 2; h > 0; h = h / 2) { //其实就是在直接插入排序外边 将增量1 变为h
// 内部是一个直接插入排序
for (int i = h; i < n; i = i + h) {
for (int j = i-h; j >= 0; j = j - h) {
if (arr[j] > arr[j+h]){
int temp = arr[j];
arr[j] = arr[j+h];
arr[j+h] = temp;
}
}
}
}
System.out.print("嘟嘟希尔排序: ");
}
//===================================交换类排序================================================
//==========================================================================================
//冒泡排序
public static void bubbleSort(int[] arr){
for(int i = 0; i< arr.length- 1; i++){ //第一个for循环表示的是循环轮数 最后一个元素不需要再进行循环轮次
for(int j = 0; j< arr.length-1-i; j++){//从索引0开始,依次两两相比较 最后一个元素不需要 而且每经过一轮 就会有个元素达到最终位置 所以 是 arr.length-1-i
if(arr[j]> arr [j+1]){//依次向后冒泡
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.print("嘟嘟冒泡排序: ");
}
//==========================================================================================
//快速排序
public static void quickSort(int[] arr, int low, int high){
int i = low;
int j = high;
int temp = 0;
//一轮快速排序
if(low<high){
temp = arr[low];//
while(i!=j){
while(i<j && arr[j]>temp){//从右往左找到一个比temp小的值
j--;
}
if(i<j){
arr[i] = arr[j];//将该值放到temp左边zzzzzzzzzzzzzzzzzzzzzzl
i++;
}
while(i<j && arr[i]<temp){//从左往右找到一个比temp大的值
i++;
}
if(i<j){
arr[j] = arr[i];//将该值放到temp右边
j--;
}
}
arr[i] = temp; //将temp放入最终位置
//迭代中心点左右两边的序列
quickSort(arr, low, i-1);
quickSort(arr, i+1, high);
}
//只是为了仅仅打印一次这句话 与快速排序无关
if(low==2){
System.out.print("嘟嘟快速排序: ");
}
}
//===================================选择类排序================================================
//==========================================================================================
//直接选择排序
public static void selectSort(int[] arr){
for(int i =0; i<arr.length-1; i++){ //从第一个元素开始 依次与后面所有元素 比较 选出最小的进行交换位置
int minIndex = i;
for(int j = i+1; j<arr.length; j++){
if(arr[minIndex] > arr[j]){
minIndex = j; //当然也可以直接在这里交换 但是这样记录最小坐标 可以减少交换次数
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
System.out.print("直接选择排序: ");
}
//==========================================================================================
//堆排序
public static int[] heapSort(int[] arr){
int len = arr.length;
int[] newarr = rebuildArr(arr); //重构数组 存储位置从索引1开始
int temp = 0;
for(int i = len/2; i>=1;--i){//建立初始堆 i= len/2 是第一个不为叶子结点的元素
shift(newarr, i, len);
}
for(int i=len; i>=2; --i){//进行n-1次循环 完成堆排序 每次循环
//这三句完成 将堆顶的元素 放到最终位置 ---建立初始堆的时候 根节点已经就是最大的元素了
temp = newarr[1];
newarr[1] = newarr[i];
newarr[i] = temp;
shift(newarr, 1, i-1);//在减少了一个元素的无序序列中进行调整 而且需要调整的只有根节点一个元素
}
arr = recArr(newarr);
System.out.print("嘟嘟嘟堆排序: ");
return arr;
}
//调整位置low上节点的位置 使其满足大顶堆的定义
public static void shift(int[] arr, int low, int high){
int i = low;
int j = 2*i;
int temp = arr[i];
while(j<=high){
if(j<high&&arr[j]<arr[j+1]){//将j指向左右孩子中最大的那个
j++;
}
if(temp<arr[j]){ //如果孩子比较大 就交换位置
arr[i] = arr[j];
i=j;
j=2*i;
}else{
break;
}
}
arr[i] = temp;
}
//因为堆排序采用的是 平衡二叉树的结构 从索引1开始存储 方便计算
public static int[] rebuildArr(int[] arr){
int[] newarr = new int[arr.length+1];
for(int i=0; i<arr.length; i++){
newarr[i+1] = arr[i];
}
return newarr;
}
//还原数组
public static int[] recArr(int[] newarr){
int[] arr = new int[newarr.length-1];
for(int i=0; i<arr.length; i++){
arr[i] = newarr[i+1];
}
return arr;
}
//===================================归并类排序================================================
//==========================================================================================
//归并排序 分治策略 二路归并采用迭代的方法, 将每个子段依次进行合并 最终得到一个有序的最终序列
public static void mergeSort(int[] arr, int low, int high){
if(low<high){//递归条件
int mid = (low+high)/2;
mergeSort(arr, low, mid);
mergeSort(arr, mid+1, high);
merge(arr, low, mid, high);
}
//只是为了仅仅打印一次这句话 与归并排序无关
if(low==1){
System.out.print("二路归并排序: ");
}
}
public static void merge(int[] arr, int low, int mid, int high){//合并两路有序序列
int[] temp = arr.clone();//拷贝一个副本用于比较 原来的arr用于存放合并后的序列 所以归并排序的空间复杂度最大
int i = low, j=mid+1, k=low; //将数组分为前后两段,i指向前半段,j指向后半段,k指向要保存的位置
//二路比较
while(i<=mid && j<=high){
if(temp[i]<temp[j]){
arr[k++] = temp[i++];
}else {
arr[k++] = temp[j++];
}
}
while(i<=mid){//如果前半段有剩余 直接加入
arr[k++] = temp[i++];
}
while(j<=high){//如果后半段有剩余 直接加入
arr[k++] = temp[j++];
}
}
}