以下资料均来自 bilibili的韩顺平老师
package sort;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @Author hecheng
* @Date 2020/6/25 21:29
* @Version 1.0
*
* 希尔排序
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = new int[]{ 8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
sheelSort2(arr);
System.out.println(Arrays.toString(arr));
///速度测试 8w 1s不到 80w 1秒
/*int[] arr1 = new int[80000];
//随机生成80000个数
for (int i=0;i<80000;i++){
arr1[i] = (int) (Math.random() * 800000);
}
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = simpleDateFormat.format(date);
System.out.println("转换前的时间为:"+s);
sheelSort2(arr1);
Date date1 = new Date();
String s1 = simpleDateFormat.format(date1);
System.out.println("转换后的时间为:"+s1);*/
///速度测试
}
public static void sheelSort(int[] arr) {
int len = arr.length;
int temp = 0;
for (int gap = len / 2; gap > 0; gap /= 2) { //比如10个数 变为 5 2 1
for (int i = gap; i < len; i++) { //代表多少组 比如gap=5时,表示有5组,2的时候2组
for (int j = i - gap; j >= 0; j -= gap) { //每一组进行插入排序 (这一步明天继续理解下)
if (arr[j] > arr[gap + j]) {
temp = arr[j];
arr[j] = arr[gap + j];
arr[gap + j] = temp;
}
}
}
}
}
/**
* 希尔排序
* 优化
* @param arr
*/
public static void sheelSort2(int[] arr) {
int len = arr.length;
for (int gap = len / 2; gap > 0; gap /= 2) {
for (int i = gap; i < len; i++) {
int j = i;
int temp = arr[j];
while (j - gap >= 0 && temp < arr[j - gap]) {
//移动
arr[j] = arr[j-gap];
j -= gap;
}
//当退出 while 后,就给 temp 找到插入的位置
arr[j] = temp;
}
}
}
}
package sort;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @Author hecheng
* @Date 2020/6/26 9:59
* @Version 1.0
* 快速排序
*/
public class QuickSort {
public static void main(String[] args) {
/*int[] arr = new int[]{8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));*/
///速度测试 800w 1秒 8000w 11秒
int[] arr1 = new int[8000000];
//随机生成80000个数
for (int i=0;i<8000000;i++){
arr1[i] = (int) (Math.random() * 80000000);
}
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = simpleDateFormat.format(date);
System.out.println("转换前的时间为:"+s);
quickSort(arr1, 0, arr1.length - 1);
Date date1 = new Date();
String s1 = simpleDateFormat.format(date1);
System.out.println("转换后的时间为:"+s1);
// System.out.println(Arrays.toString(arr1));
///速度测试
}
/**
* @param arr
* @param left
* @param right
* x=8
* 8, 9, 1, 7, 2, 3, 5, 4, 6, 0
* ② 0, 9, 1, 7, 2, 3, 5, 4, 6, 8 r=9
* ④ 0, 9, 1, 7, 2, 3, 5, 4, 6, 9 l=1,r=8
* ...
* 0, 6, 1, 7, 2, 3, 5, 4, 6, 9 r=8,l=8
*
*/
public static void quickSort(int[] arr, int left, int right) {
if (left < right) {
int l = left, r = right, x = arr[left];
while (l < r) {
//①
while (l < r && arr[r] >= x) { //找出右边的小于x的数
r--;
}
//②
if (l < r) {
arr[l++] = arr[r]; //将刚找到的右边的小于x的数放入左边最前面, 所以l++是将左边要移动的位置 +1
}
//③
while (l < r && arr[l] < x) { //找出左边的大于x的数
l++;
}
//④
if (l < r) {
arr[r--] = arr[l]; //给刚才右边换过来的位置赋上左边选出来的数
}
}
arr[l] = x;
quickSort(arr, left, l - 1);
quickSort(arr, l + 1, right);
}
}
}
package search;
import java.util.Arrays;
/**
* @Author hecheng
* @Date 2020/6/27 15:26
* @Version 1.0
*/
public class FibonacciSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int[] arr = {1, 8, 10, 89, 1000, 1234};
System.out.println("index=" + fibSearch(arr, 10));// 0
}
//因为后面我们 mid=low+F(k-1)-1,需要使用到斐波那契数列,因此我们需要先获取到一个斐波那契数列
//非递归方法得到一个斐波那契数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
//编写斐波那契查找算法
//使用非递归的方式编写算法
/**
* @param a 数组
* @param key 我们需要查找的关键码(值)
* @return 返回对应的下标,如果没有-1
*/
public static int fibSearch(int[] a, int key) {
int low = 0;
int high = a.length - 1;
int k = 0; //表示斐波那契分割数值的下标
int mid = 0; //存放 mid 值
int f[] = fib(); //获取到斐波那契数列
//获取到斐波那契分割数值的下标
while (high > f[k] - 1) {
k++;
}
//因为 f[k] 值 可能大于 a 的 长度,因此我们需要使用 Arrays 类,构造一个新的数组,并指向 temp[]
//不足的部分会使用 0 填充
int[] temp = Arrays.copyOf(a, f[k]);
//实际上需求使用 a 数组最后的数填充 temp
//举例:
//temp = {1,8, 10, 89, 1000, 1234, 0, 0} => {1,8, 10, 89, 1000, 1234, 1234, 1234,}
for (int i = high + 1; i < temp.length; i++) {
temp[i] = a[high];
}
// 使用 while 来循环处理,找到我们的数 key
while (low <= high) { // 只要这个条件满足,就可以找
mid = low + f[k - 1] - 1;
if (key < temp[mid]) { //我们应该继续向数组的前面查找(左边)
high = mid - 1;
//为甚是 k--
//说明
//1. 全部元素 = 前面的元素 + 后边元素
//2. f[k] = f[k-1] + f[k-2]
//因为 前面有 f[k-1]个元素,所以可以继续拆分 f[k-1] = f[k-2] + f[k-3]
//即 在 f[k-1] 的前面继续查找 k--
//即下次循环 mid = f[k-1-1]-1
k--;
} else if (key > temp[mid]) { // 我们应该继续向数组的后面查找(右边)
low = mid + 1;
//为什么是 k -=2
//说明
//1. 全部元素 = 前面的元素 + 后边元素
//2. f[k] = f[k-1] + f[k-2]
//3. 因为后面我们有 f[k-2] 所以可以继续拆分 f[k-1] = f[k-3] + f[k-4]
//4. 即在 f[k-2] 的前面进行查找 k -=2
//5. 即下次循环 mid = f[k - 1 - 2] - 1
k -= 2;
} else { //找到
//需要确定,返回的是哪个下标
if (mid <= high) {
return mid;
} else { //mid超过原数组的下标,则返回high
return high;
}
}
}
return -1;
}
}