正好做题的时候碰到快速排序,就复习一下,顺带着两个基础排序算法 2020.05.15
先解释一个名称,排序算法的稳定性?当排序后2个相等键值的顺序 和 排序前它们的顺序相同,则表示“稳定”。
算法解析:
通过递归的方式,以基准(理论上是任意一个元素,实现时使用下标最小的为基准)为界,将小于基准的移到左边,大于的移到右边,不断递归。
时间复杂度和空间复杂度:
平均时间复杂度O(n log n)
最好时间复杂度O(n log n)
最差时间复杂度O(n的二次方)
空间复杂度O(log n)
package sort;
public class QuickSort {
public static void main(String[] args) {
int[] testArray = {9,7,3,1,8,6,4,2,5,0};
for (int element : testArray) {
System.out.print(element + " ");
}
quickSort(testArray);
System.out.println();
for (int element : testArray) {
System.out.print(element + " ");
}
}
//判断是否合法,并初始化入参
public static void quickSort(int[] number) {
if(number == null || number.length == 0) {
System.out.println("入参不合法");
return;
}
int low = 0;
int high = number.length - 1;
sort(number, low, high);
}
public static void sort(int[] number,int low,int high) {
if(low < high) {
int index = Partition(number, low, high);
sort(number, low, index-1);
sort(number, index+1, high);
}
}
//以第一个值为基准,左右分区,左边比基准小,右边比基准大
public static int Partition(int[] number,int low,int high) {
//临时缓存基准值,方法最后换到分区中间
int temp = number[low];
while (low < high) {
//因为等于在基准左边也行右边也行,就不用考虑等于的情况
while (temp < number[high] && low < high) {
high--;
}
if(low < high) {
number[low] = number [high];
low++;
}
while (temp > number[low] && low < high) {
low++;
}
if(low < high) {
number[high] = number [low];
high--;
}
}
number[low] = temp;
//返回分区中间值的下标,即当前基准下标
return low;
}
}
算法解析:
以升序为例,通过两个循环,第一层循环代表着这个位置,第二层代表着这个从这个位置后的不断比较,如果小与当前位置就交换,然后二次循环继续比较。
优化指的是让,就是在一层循环加一个标记变量,第一种情况,如果二层循环第一次就没有发生交换,说明顺序本身就是排好的;第二种情况,在排序时发现后半部分是已经排好的就不排啦。
时间复杂度和空间复杂度:
平均时间复杂度O(n的二次方)
最好时间复杂度O(n),指的是优化的排序算法
最差时间复杂度O(n的二次方)
空间复杂度O(1),因为只用到一个缓存
package sort;
//冒泡排序
public class BubbleSort {
public static void main(String[] args) {
int[] test = {9,7,3,1,8,6,4,5,2};
for(int i = 0;i < test.length; i++) {
for(int j = i;j < test.length; j++) {
//升序:如果上层值比下层值大,将小的值放在上层值的位置上,简单来说就是找最小值放在上层值的位置上
if(test[i] > test[j]) {
int temp = test[i];
test[i] = test[j];
test[j] = temp;
}
}
}
for(int value : test)
System.out.print(value + "\t");
}
}
优化代码实现:
package sort;
//优化冒泡排序
public class BubbleSort {
public static void main(String[] args) {
int[] test = {9,7,3,1,8,6,4,5,2};
for(int i = 0;i < test.length; i++) {
boolean mark = false;
for(int j = i;j < test.length; j++) {
//升序:如果上层值比下层值大,将小的值放在上层值的位置上,简单来说就是找最小值放在上层值的位置上
if(test[i] > test[j]) {
int temp = test[i];
test[i] = test[j];
test[j] = temp;
mark = true;
}
}
if(mark == false) {
return;
}
}
for(int value : test)
System.out.print(value + "\t");
}
}
算法解析:
以升序为例,通过两个循环,第一层循环代表着这个位置,第二层代表着这个从这个位置后的不断比较选出最小的,和冒泡不同的点是,它是标记位置,二层循环结束后换位置。
时间复杂度和空间复杂度:
平均时间复杂度O(n的二次方)
最好时间复杂度O(n的二次方)
最差时间复杂度O(n的二次方)
空间复杂度O(1),因为只用到一个缓存
package sort;
//选择排序
public class SelectionSort {
public static void main(String[] args) {
int[] test = {2,6,4,8,1,5,7,9,3};
for(int i = 0 ; i < test.length;i++) {
int index = i;
for(int j = i ; j < test.length;j++) {
//注意这个位置是拿标志位去比价,而不像冒泡总是拿当初循环第一个位置
//升序:如果标识位比当前位值大,说明不是最小值,标记位变成当前位的下标
if (test[index] > test[j]) {
index = j;
}
}
//在外层循环进行交换
int tempValue = test[index];
test[index] = test[i];
test[i] = tempValue;
}
for(int value : test) {
System.out.print(value + "\t");
}
}
}