排序算法(一)
极客时间:王争:《数据结构与算法之美》:第11讲内容学习笔记
常用排序算法种类与其Java实现
冒泡排序-->时间复杂度(最好:O(n),最坏:O(n^2),平均:O(n^2))-->基于比较
插入排序-->时间复杂度(最好:O(n),最坏:O(n^2),平均:O(n^2))-->基于比较
选择排序-->时间复杂度(最好:O(n^2),最坏:O(n^2),平均:O(n^2))-->基于比较
快排-->时间复杂度(最好:最坏:平均:O(nlogn))-->基于比较
归并-->时间复杂度(最好:最坏:平均:O(nlogn))-->基于比较
桶排序-->时间复杂度(最好:最坏:平均:O(n))-->不是基于比较
计数排序-->时间复杂度(最好:最坏:平均:O(n))-->不是基于比较
基数排序-->时间复杂度(最好:最坏:平均:O(n))-->不是基于比较
排序算法内存消耗(原地排序与否)
算法的内存消耗可以通过空间复杂度来衡量。不过,针对排序算法的空间复杂度,还有一个原地排序(Sorted in place)的概念。原地排序算法,就是特指空间复杂度是 O(1) 的排序算法。
排序算法的稳定性
仅仅用执行效率和内存消耗来衡量排序算法的好坏是不够的。针对排序算法,还有一个重要的度量指标,稳定性。这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。
比如我们有一组数据 2,9,3,4,8,3,按照大小排序之后就是 2,3,3,4,8,9。两个3的先后顺序是否改变。
目的举例:查找订单
查找金额,从低到高,如果金额相同则通过时间,从早到晚。
稳定排序算法可以保持金额相同的两个对象,在排序之后的前后顺序不变。
所以,对数据进行第一次对时间排序之后,通过稳定算法再对金额进行第二次排序。经过第二次排序之后,相同金额的订单仍然保持下单时间从早到晚有序。
冒泡排序(Bubble Sort)
冒泡排序的Java实现
// 冒泡排序,a表示数组,n表示数组大小
public void bubbleSort(int[] a, int n) {
if (n <= 1) return;
for (int i = 0; i < n; ++i) {
// 提前退出冒泡循环的标志位
boolean flag = false;
for (int j = 0; j < n - i - 1; ++j) {
if (a[j] > a[j+1]) { // 交换
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
flag = true; // 表示有数据交换
}
}
if (!flag) break; // 没有数据交换,提前退出
}
}
插入排序(Insertion Sort)
插入排序的Java实现
// 插入排序,a表示数组,n表示数组大小
public void insertionSort(int[] a, int n) {
if (n <= 1) return;
for (int i = 1; i < n; ++i) {
int value = a[i];
int j = i - 1;
// 查找插入的位置
for (; j >= 0; --j) {
if (a[j] > value) {
a[j+1] = a[j]; // 数据移动
} else {
break;
}
}
a[j+1] = value; // 插入数据
}
}
插入排序的优化
希尔排序
选择排序(Selection Sort)
选择排序Java代码实现
// 选择排序,a表示数组,n表示数组大小
public void selectionSort(int[] a, int n) {
if (n <= 1) return; //数组是空或者数组里面只有一个元素,没必要排序
for (int i = 0; i < n-1; ++i) { //最后一个元素没必要再给它排序,因为它就是最大的
int minIndex = i; //初始的时候就认为最小值索引指针在i位置,最小值就是arr[i]
for (int j = i+1; j < n; j++) { //在i后面[i+1,n-1]区间找最小的值
if (a[minIndex]>a[j]) {
minIndex = j; //找到就把最小值索引跟新,找不到最小值索引还在原位
}
}
//将i位置上的元素值和最小索引位置的元素值交换
int temp = a[i];
a[i] = a[minIndex];
a[minIndex] = temp;
}
}
LeetCode-75题练习
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-colors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
public class LeetCode75_sortColors {
@Test
public void test01() {
int[] nums01 = {2, 0, 1};
sortColors(nums01);
}
/**
* 给定一个包含红色、白色和蓝色,一共n 个元素的数组,原地对它们进行排序,
* 使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
* 此题中,我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。
* @param nums
*/
public void sortColors(int[] nums) {
//原地排序算法概念
//排序算法稳定概念
//熟悉快速排序、冒泡排序、插入排序、选择排序
int front = -1; //它前面,包括它自己,全都<1
int after = -1; //它前面,包括它自己,全都<2
int end = nums.length - 1;
for (int i = 0; i < nums.length; i++) {
if (i > end) { //当前值与end值重合的时候说明全部值都做了判断
break;
}
int temp = nums[i];
if (temp == 2) {
nums[i] = nums[end]; // 后面未判断的值换过来
nums[end] = temp; // 当前的这个2给后面指针位置
end--; // 指向新得未做的判断值
i--; // 由于当前值是缓过来的未做判断的,所以循环回溯,对当前值再做判断
}
if (temp == 1) {
after = i;
}
if (temp == 0) {
if (front == -1 && after > -1) { //前边没出现过0,但是出现过1,此时出现0
nums[i] = nums[0];
nums[0] = temp;
}
if (after > -1 && front > -1) { //前边即出现1,也出现过0,此时出现0
nums[i] = nums[front + 1];
nums[front + 1] = temp;
}
front++;
}
}
System.out.println(Arrays.toString(nums));
}
}
拿这个答案去作答时,记得把那句输出语句去掉...