package Sort;
import java.util.Arrays;
public final class SortUtils {
/***
* @Title: 方法测试
*/
public static void main(String[] args) {
int[] arr = {5,2,4,6,1,3};
SortUtils.insertSortObj(arr);
System.out.println("插入排序:------------------"+Arrays.toString(arr));
SortUtils.bubbleSortObj(arr);
System.out.println("冒泡排序:------------------"+Arrays.toString(arr));
SortUtils.choseSortObj(arr);
System.out.println("选择排序:------------------"+Arrays.toString(arr));
SortUtils.arraySortObj(arr);
System.out.println("JAVA自带排序:--------------"+Arrays.toString(arr));
SortUtils.fastSortObj(arr,0,5);
System.out.println("快速排序:------------------"+Arrays.toString(arr));
SortUtils.shellSortObj(arr);
System.out.println("希尔排序:------------------"+Arrays.toString(arr));
SortUtils.mesrgeSort(arr,0,arr.length-1);
System.out.println("归并排序:------------------"+Arrays.toString(arr));
}
/**
*
* @Title: 插入排序
* @Description: TODO 插入排序的工作方式像我们平常排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。
* 然后,我们每次从桌子上拿走一张牌并将它插入到左手中正确的位置,我们从右到左将它与在手中的每张牌进行比较。
* 拿在左手上的牌总是排好序的,原来这些牌是桌子上牌堆中顶部的牌—–《算法导论》
*/
public static void insertSortObj(int[] arr) {
int temp = 0;
for (int i = 1; i < arr.length; i++) {
int j = i - 1;
temp = arr[i];
while (j >= 0 && arr[j] > temp) {
// 把数组整体后移一位
arr[j + 1] = arr[j];
j--;
}
// 将要插入的数放到整个后移了的数组的前面因为上面做了j--,现在的下标应该是要插入的位置
arr[j + 1] = temp;
}
}
/***
* @Title 冒泡排序--倒叙(从大到小排序)
* @Description: TODO
* 冒泡排序是排序中比较简单的一种,基本的思想就是比较数组中相邻两个数的大小。如果前面一个比后面一个数值大就交换位置
*/
public static void bubbleSortObj(int[] arr) {
for(int i = 0 ; i < arr.length ; i++){//外层循环控制排序趟数
for(int j = 0 ; j < arr.length-1-i ; j++){//内层循环控制每一趟排序多少次
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
/**
* @Title 选择排序 --升序(从小到大排序)
* @Description: TODO 选择排序和使用Arrays.sort(int[] arr) 是一个道理
* 每次都在未排好序的序列里面选出最小的,最后排成一个升序的数组。
*/
public static void choseSortObj(int[] arr) {
int temp = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
/**
* @Title 自带的排序
* @Description: TODO 使用数组自带的方法排序--升序(从小到大) Arrays.sort(int[] arr)
*/
public static void arraySortObj(int[] arr) {
Arrays.sort(arr);
}
/**
* @Title 快速排序
* @Description: TODO 快速排序的基本思想就是,先找一个数作为基数,然后将数组中其他的数与之进行比较,
* 小的放在这个数的前面,大的放到这个数的后面。再将这个数的前面和后面的数当成单独的数组,
* 再进行同样的操作,迭代到最后只剩一个数的时候。
* @param first
* 第一个位置
* @param last
* 数组的最后一个位置
*/
public static void fastSortObj(int[] arr, int first, int last) {
if (first < last) {
int i = first, j = last, x = arr[first];
while (i < j) {
// 先从右到左找第一个小于x的数
while (i < j && arr[j] >= x) {
j--;
}
// 如果找到了就跳出循环,并把值放入a[i]这个坑
if (i < j) {
arr[i++] = arr[j];
}
// 从左到又寻找第一个大于x的数
while (i < j && arr[i] < x) {
i++;
}
// 如果找到就跳出循环,并将其值放入a[j]这个坑
if (i < j) {
arr[j--] = arr[i];
}
}
// 将最初的基数放入a[i]这个坑
arr[i] = x;
// 递归调用
fastSortObj(arr, first, i - 1);
fastSortObj(arr, i + 1, last);
}
}
/**
*
* @Title: 希尔排序
* @Description: TODO 希尔排序有点类似于插入排序,在排序前,我们首先要获得一个步长
* (当前位置往后走的步数),一般是数组的长度除以2;
* 把当前的这个数与数组在当前位置呢往后面走n个步长的值进行一个插入排序。
*/
public static void shellSortObj(int arr[]) {
int j, gap, n = arr.length;
for (gap = n / 2; gap > 0; gap /= 2) {
for (j = gap; j < n; j++) {
if (arr[j] < arr[j - gap]) {
// 把当前j位置的值放到temp里面保存起来
int temp = arr[j];
// j往前面走步长gap
int k = j - gap;
// 如果有a[k]>temp的话,把排好序的整个后移gap
// 把要插入的值放到当前的位置,就是插入排序
while (k >= 0 && arr[k] > temp) {
arr[k + gap] = arr[k];
k -= gap;
}
arr[k + gap] = temp;
}
}
}
}
/***
*
* @Title: 归并排序
* @Description: TODO
* 归并排序是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。
* 然后再把有序子序列合并为整体有序序列。
*
* TODO 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and
* Conquer)的一个非常典型的应用。
* 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序
* 。若将两个有序表合并成一个有序表,称为2-路归并
*
* TODO
* 归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),
* 算法不是自适应的,不需要对数据的随机读取
*/
public static void mergeSortObj(int arr[], int left, int center, int right) {
int[] tmpArr = new int[right + 1];
int mid = center + 1;
int index = left; // index记录临时数组的索引
int tmp = left;
// 从两个数组中取出最小的放入中临时数组
while (left <= center && mid <= right) {
tmpArr[index++] = (arr[left] <= arr[mid]) ? arr[left++]
: arr[mid++];
}
// 剩余部分依次放入临时数组
while (mid <= right) {
tmpArr[index++] = arr[mid++];
}
while (left <= center) {
tmpArr[index++] = arr[left++];
}
// 将临时数组中的内容复制回原数组
for (int i = tmp; i <= right; i++) {
arr[i] = tmpArr[i];
}
}
public static void mesrgeSort(int[] arr, int left, int right) {
if (left >= right)
return;
int center = (left + right) >> 1;
mesrgeSort(arr, left, center);
mesrgeSort(arr, center + 1, right);
mergeSortObj(arr, left, center, right);
}
}