算法解决思路,将复杂的算法拆分成简单的问题-》逐步解决。
1)类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)定义为该算法所耗费的存储空间,它也是问题规模n的函数。
2)空间复 杂度(Space Complexity)是对一个算法 在运行过程中临时占用存储空间大小的量度。有的算法需要占用的临时工作单元数与解决问题的规模n有关,它隨着n的增大而增大,当n较大时,将占用较多的存储单元,例如快速排序和归并排序算法,基数排序就属于这种情况。
3)在做算法分析时, 主要讨论的是时间复杂度。从用户使用体验上看,更看重的程序执行的速度。一些缓存产品(redis, memcache)和算法(基数排序)本质就是用空间换时间。
选择排序、快速排序、希尔排序、堆排序是不稳定的排序算法,
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
一 冒泡排序算法代码实现如下
冒泡排序的时间复杂度是O(n^2),空间复杂度是O(1),是稳定的排序算法。
package top.chenxiky.sort;
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
*
* @Author: chenxiky
* @Date: 2022/05/17/17:01
* @Description:
*/
public class BubbleSort {
public static void main(String[] args) {
// 定义一个数组
int[] arr = {-3, 9, -1, 10, 8,7};
bubbleSort(arr);
// 输出排序后的结果
System.out.println("arr="+Arrays.toString(arr));
}
/**
* 封装冒泡排序
* @param arr
*/
private static void bubbleSort(int[] arr) {
// 比较的趟数(时间复杂程度On^2)
for (int i = 0; i < arr.length - 1; i++) {
// 交换数据的临时变量
int temp = 0;
// 标识变量,表示是否进行过交换,加快排序结果
boolean flag = false;
// 每趟比较的次数
for (int j = 0; j < arr.length - i - 1; j++) {
// 比较
if (arr[j] > arr[j + 1]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// 输出每一趟的效果
System.out.println("第" + (i + 1) + "趟排序后的数组");
System.out.println(Arrays.toString(arr));
// 在一趟排序中,一次交换都发送没有交换过
if (!flag) {
// 跳出循环
break;
}else {
flag = false;// 重置flag,进行下次判断
}
}
}
}
二.选择排序
概念:选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一
元素,再依规定交换位置后达到排序的目的。
选择排序的时间复杂度是O(n^2),是不稳定的算法,它相比较冒泡排序,每次比较后,只更新最小值的下标,每轮循环值最多只做一次值交换。时间上得到了很大的提升。但是也是使用了双层循环,时间复杂度和冒泡排序的一样。
思路;
三.直接插入排序法
直接插入排序算法的时间复杂度为O(n^2),整个算法只需要一个key的辅助变量,所以空间复杂度为O(1)。直接插入排序是一种稳定的排序方法。
每次把数组的第一个数据当成有序。
代码实现如下
package top.chenxiky.sort;
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
*
* @Author: chenxiky
* @Date: 2022/05/17/19:56
* @Description:
*/
public class InsertSort {
public static void main(String[] args) {
// TODO
int[] arr = {101, 34, 119, 1, -1};
insertSort(arr);
}
// 插入排序
public static void insertSort(int[] arr) {
// 初始化
int insertVal = 0;
int insetIndex = 0;
for (int i = 1; i < arr.length; i++) {
// 定义待插入的数
insertVal = arr[i]; // 从数组的第二个数开始,也就是下标为1
insetIndex = i - 1; // 即arr[1]的前面这个数的下标 已经排序的第一个数的下标
// insetIndex >= 0 保证在给insertVal 找到插入位置不越界,
// insertVal < arr[insetIndex]待插入的数还未找到插入位置
while (insetIndex >= 0 && insertVal < arr[insetIndex]) {
// 将结果向前占一位
arr[insetIndex + 1] = arr[insetIndex];
//进行-1操作退出循环 0-1 == -1 后移
insetIndex--;
}
// 当退出循环时,说明要插入的位置找到
// 这里我们需要判断是否需要赋值
if (insetIndex + 1 != i) {
arr[insetIndex + 1] = insertVal;
}
}
System.out.println("排序后=" + Arrays.toString(arr));
}
}
四.希尔排序
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序法高效的改进版本。希尔排序是非稳定排序算法。时间复杂度为O(n^3/2)。
package top.chenxiky.sort;
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
*
* @Author: chenxiky
* @Date: 2022/05/17/22:54
* @Description: 希尔排序
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = {1, 3, -1, 6, 8, 10};
// int[] arr = new int[8];
// for (int i = 0; i < 8; i++) {
// arr[i] = (int) (Math.random() * 8000000);
// }
// 调用封装的函数
shellSort2(arr);
}
/**
* 希尔交换法
*
* @param arr
*/
public static void shellSort(int[] arr) {
// 初始化交换辅助量
int temp = 0;
// 根据前面的逐步分析,使用循环处理
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
// 遍历各组中所有元素(共arr.length / 2组,每组有两个元素,步长为 arr.length/2)
for (int j = i - gap; j >= 0; j -= gap) {
// 如果当前元素加上步长后的那个元素,说明交换
if (arr[j] > arr[j + gap]) {
temp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = temp;
}
}
}
}
// 输出结果
System.out.println("希尔排序结果-交换方式:" + Arrays.toString(arr));
}
/**
* 希尔排序移位法 优化
*/
public static void shellSort2(int[] arr) {
// 增量gap,并逐渐的缩小增量
for (int gap = arr.length >> 1; gap > 0; gap /= 2) {
// 从第gap个元素,逐个对其所在的组进行直接插入排序
for (int i = gap; i < arr.length; i++) {
// 保存下标值
int j = i;
// 临时变量记录插入的数
int temp = arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
// 移动
arr[j] = arr[j-gap];
j -=gap;
}
// 当退出while循环的时候,就给temp找到插入的位置
arr[j] = temp;
}
}
}
System.out.println("希尔排序移位法="+Arrays.toString(arr));
}
}
五.快速排序
package top.chenxiky.sort;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
*
* @Author: chenxiky
* @Date: 2022/05/19/23:01
* @Description: 快速排序
*/
public class QuickSort {
public static void main(String[] args) {
int[] arr = {-9, 78, 0, 23, -657, 70};
quickSort(arr, 0, arr.length - 1);
System.out.println("快排" + Arrays.toString(arr));
}
/**
* 封装
*/
public static void quickSort(int[] arr, int left, int right) {
int l = left; // 做下标
int r = right; // 右下标
// pivot中轴
int pivot = arr[(left + right) / 2];
int temp = 0; // 临时变量 ,交换时使用
// while循环的目的是让比pivoit 值小放到左边
// 比pivot值大的放到右边
while (l < r) {
// 在pivot的左边一直找,找到大于等于pivoit值,才退出
while (arr[l] < pivot) {
l += 1;
}
//在pivot的右边一直找,找到小于等于pivoit值,才退出
while (arr[r] > pivot) {
r -= 1;
}
//如果l>=r 说明pivot的左右俩的值,已经按照左边全是小于等于pivot,右边全部是大于等于pivot
if (l >= r) {
break;
}
// 交换
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//如果交换完后,发现arr[l] == pivot 相等-- 前移
if (arr[l] == pivot) {
r -= 1;
}
//如果交换完后,发现arr[r] == pivot 相等--后移
if (arr[r] == pivot) {
l += 1;
}
}
// 如果l==r,必须l++,r--,否则出现栈溢出
if (l == r) {
l += 1;
r -= 1;
}
// 向左递归
if (left < r){
quickSort(arr,left,r);
}
if (right >l){
quickSort(arr,l,right);
}
}
}
未完待遇。。。。