8种排序,写了6中,剩下2种后面再补*-*
package sort;
import java.util.Arrays;
public class Sort {
private static final int[] arr = { 25, 63, 15, 21, 26, 56,45,46,23};
/*
* 冒泡排序: (邻近,两两比较)
* 1. 从0开始到(len-1)都要比较,目的是将最值放入最后(下面,升序,目的则是将最大值依次放入最后) -> 第一个for
* 2. 比较的具体操作: 两两比较,大的往后移,结果最后就是最大值。
* a. 长度arr.len-1 : 可以想象5个数,只需要比4次
* b. 长度arr.len-1-i : 由于i在增1,相反j比较次数就要减1
*/
public static void maopao(int[] arr) {
int tem = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
tem = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tem;
}
}
}
}
/*
* 快速排序:(二分法思想)
* 1. 首先是二分法思想(前后一起走,当前后的下标相等,则说明全部排序完成) -> while
* 2. 具体做法: 从后往前找小于arr[left]值,从前往后找大于arr[left]的值,
* 找到后:
* a. 前后的下标一致,说明找完了,又因为i=j,所以跳出循环
* b. 前后的下标不一致,将两个值前后置换(大的去了后面,小的来了前面),又因为i和j没有相遇,说明没有走完,接着while循环
* 3. 做完后,当时的arr[left]应该找到了,它所在的位置: 将while中找到的中间点i,和left置换位置
* 4. 递归开始下次排序,
* 分两组:
* a. (arr, 0, i-1)
* b. (arr, i+1, arr.len)
*/
public static void fast(int a[], int left, int right) {
int i,j,t;
// 递归调用中,若left>=right,说明达到递归出口,元素已经全部有序
if (left >= right)
return;
// 定义a[left]为切分的基准元素(可优化为随机选取基准元素,消除数据依赖)
int temp = a[left];
i = left;
j = right;
while (i != j) { // 若跳出循环,证明i和j相遇
while (a[j] >= temp && i < j)
j--;// 从右往左找到需要交换的a[j]位置
while (a[i] <= temp && i < j)
i++;// 从左往右找到需要交换的a[i]位置
if (i < j) { // 满足i<j,交换a[i]和a[j]两个位置
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
// 此时,需要将基准数tem归位到i==j的那个位置
a[left] = a[i];
a[i] = temp;
// 将已经归为的左边和右边的数,再次递归调用快速排序
fast(a, left, i - 1);
fast(a, i + 1, right);
}
/*
* 选择排序:(查找最值,进行置换)
* 1. 一共排序次数arr.len-1次 -> 第一个for循环 (对于是len次还是len-1,再解释)
* 2. 每次 [i+1,len]找最小值,因为当时默认最小值是arr[i],所以找到的最小值,就是数组中所有数最小值,将最小值,放最前面。
* 这里有两步:
* a. 在[i+1,len] 中找到最小值 -> 第二个for循环
* b. 将i的值和找到最小值置换
*/
public static void select(int[] arr) {
for(int i=0; i<arr.length-1;i++) { //从第一个开始比较,到最后一个-1
int min = arr[i];
for(int j=i+1; j<arr.length;j++) {
if(min>arr[j]) {
int temp = min;
min = arr[j];
arr[j] = temp;
}
}
if(min != arr[i]) {
int temp = min;
min = arr[i];
arr[i] = temp;
}
}
}
/*
* 插入排序:(不断将最值移向数组头部)
* 1. 先把找位置的元素挖出 -> temp=arr[i]
* 2. 从当前元素下标开始找到数组头下标,如果前面1个比当前这个元素大,则前面元素后移一位 -> while()
* (这里要注意,从头到此刻的过程已经保证次元素前面是排序好的,换句话:不会出现,现在位置是31的这种情况12,13,45,32,31)
* 3. 最后把比找位置的元素大的元素都完后移动后,空出的位置,就是找位置的元素 -> arr[i]=temp
*/
public static void insert(int[] arr) {
int temp;
for(int i=1; i<arr.length; i++) {
//找位置的元素,先挖出
temp = arr[i];
//如果前面的元素比后面元素大,前面元素后退1,整好把挖出元素所在位置填上
while(i>=1 && arr[i-1]>temp) {
arr[i] = arr[i-1];
i--;
}
//如果跳出while循环,说明找位置的元素找到了位置,下标就是当前i
arr[i]=temp;
}
}
/*
* 希尔排序:
* 分两组然后直接插入排序,把插入排序中的分割基值的1改成d。
*/
public static void sheel(int[] a) {
int d = a.length;
while (d != 0) {
d = d / 2;
for (int x = 0; x < d; x++) {// 分的组数
for (int i = x + d; i < a.length; i += d) {// 组中的元素,从第二个数开始
int temp = a[i];// 要插入的元素
while(i>=x+d && arr[i-d]>temp) {
arr[i] = arr[i-d];
i-=d;
}
a[i] = temp;
}
System.out.println(Arrays.toString(a));
}
}
}
/*
* 堆排序:
* 1. 数组->最大堆
* 2. 最大堆的根节点交换末尾子节点,断开交换后的最后节点(将最大元素依次剔除)
* 3. 重复执行1、2,直至所有节点都断开
*/
/*
* 基数排序:
* 依次将数组中的数字从最低位到最后位,依次放入0-9的10个桶中
*/
/*
* 归并排序:
*
*/
public static void sort(int[] arr, int L, int R) {
if(L == R) {
return;
}
int mid = L + ((R - L) >> 1);
sort(arr, L, mid);
sort(arr, mid + 1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int mid, int R) {
int[] temp = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = mid + 1;
// 比较左右两部分的元素,哪个小,把那个元素填入temp中
while(p1 <= mid && p2 <= R) {
temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 上面的循环退出后,把剩余的元素依次填入到temp中
// 以下两个while只有一个会执行
while(p1 <= mid) {
temp[i++] = arr[p1++];
}
while(p2 <= R) {
temp[i++] = arr[p2++];
}
// 把最终的排序的结果复制给原数组
for(i = 0; i < temp.length; i++) {
arr[L + i] = temp[i];
}
}
/*
* 数组中两个数置换
*/
public static void swap(int arr[], int i, int j) {
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
// maopao(arr);
// fast(arr,0,arr.length-1);
// select(arr);
// insert(arr);
System.out.println(">>>>>>>>>"+Arrays.toString(arr)+"<<<<<<<<<\n");
// sheel(arr);
sort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
}
}