快速排序
快速排序思想:
比大小再分区
1.从数组中取出一个数将其作为基准数
2.分区:将比这个数大或等于的数全放到他的右边,小于他 的数全放到他的左边
3.再对左右区间重复第二步,知道各区间只有一个数
实现思路:
1.将基准数挖出来形成一个坑
2.由后向前找比他小的数,找到后挖出此数填到前一个坑中。
3.由前向后找比他大或者等于的数,找到后也挖出此数填到前一个坑中。
4.再重复执行2,3两步骤
代码举例;
public class ArraysUtils {
/**
* @param arr 待排序数组
* @param start 起始索引
* @param end 终止索引
*/
public static void quickSort(int[] arr, int start, int end) {
if (start < end) {
//递归
//获取基准数的索引,左右两区的界线
int index = getIndex(arr, start, end);
//对左区,进行递归
quickSort(arr, start, index - 1);
//对右区,进行递归
quickSort(arr, index + 1, end);
}
}
/*
挖坑填数
1. 将基准数挖出形成第一个坑。
2.由后向前找比他小的数,找到后挖出此数填到前一个坑中。
3.由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
4.再重复执行2,3两步骤。
*/
private static int getIndex(int[] arr, int start, int end) {
int i = start;
int j = end;
//1.找一个数作为基准数
int x = arr[i];
//4.重复2,3步
while (i<j){
// 2.由后向前找比他小的数,找到后挖出此数填到前一个坑中。
while (i < j && arr[j] >= x) {
j--;
}
//找到之后,挖坑填数
if (i < j) {
arr[i] = arr[j];
i++;// 下一次要从前完后找,那就顺便让i递增一下
}
//3.由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
while (i < j && arr[i] < x) {
i++;
}
//找到之后,挖坑填数
if (i < j) {
arr[j] = arr[i];
j--; //下次要从后往前找,那就顺边让j 递减一下
}
}
//让基准数填到最后一个坑中
arr[i]=x;
return i; //i==j 返回基准数所在位置
}
}
public class MyTest {
public static void main(String[] args) {
int[] arr = {21, 70, 67, 45, 66 , 6, 8, 1, 0, 10, -1, 20, 100};
ArraysUtils.quickSort(arr, 0, arr.length - 1);//调用quickSort方法
System.out.println(Arrays.toString(arr));
}
}
希尔排序
希尔排序是插入排序的一种优化,其运算效率高于插入排序,希尔排序又称之为缩小增量排序。
希尔排序原理:
先将原表按增量ht分组,每个子文件按照直接插入法排序。同样,用下一个增量ht/2将文件再分为子文件,再进行直接插入法排序。直到ht=1时整个文件排好序。
核心思想:
合理的选取增量,经过一轮排序之后,序列大致有序,在不断的缩小增量,进行插入排序,直到增量为1整个排序结束
import java.util.Arrays;
public class MyTest1
{
public static void main(String [] args){
int [] arr={10,26,78,12,34,58,88,100};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr) {
// //增量的选取,取数组长度的一半
for (int h = arr.length / 2; h > 0; h /= 2) {
//直接插入排序思想
for (int i =h; i < arr.length; i++)
{
for (int j = i; j >h-1; j -= h)
{
if (arr[j] < arr[j - h]) {
int t = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = t;
}
}
}
}
}
}
使用克努特序列进行希尔排序
克努特序列:
//int h=1;
//h=3*h+1//1,4,13,40,121,364,这种序列就是克努特序列
代码实现
import java.util.Arrays;
public class MyTest2 {
public static void main(String [] args){
int [] arr={10,26,78,12,34,58,88,100};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr)
{
//采用克努特序列进行增量的选取
int ht=1;
while(ht<=arr.length/3)
{
ht=ht*3+1;
}
for (int h = ht; h > 0; h =(h-1)/3)
{
for (int i =h; i < arr.length; i++)
{
for (int j = i; j >h-1; j -= h)
{
if (arr[j] < arr[j - h])
{
int t = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = t;
}
}
}
}
}
}