排序算法
分类
- 内部排序:将需要处理的数据加载到内存中进行排序;
- 插入排序:直接插入排序 希尔排序
- 选择排序:简单选择排序 堆排序
- 交换排序:冒泡排序 快速排序
- 归并排序
- 基数排序 - 桶排序升级版
- 外部排序:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序(内存与外存结合)
算法的时间复杂度
- 事后统计:程序运行的时间;需要运行程序、依赖于计算机的硬件、软件等环境因素
- 事前估算的方法:分析算法的时间复杂度
时间频度
时间频度:一个算法花费的时间与算法的执行次数成正比例,一个算法中语句执行次数称为语句频度或时间频度,T(n)
// case 1
int total = 0;
int end = 100;
for(int i = 1; i <= end; i++){
total += i;
}
// T(n) = n + 1 总共执行了 n+1 次
// case 2
total = (1 + end)* end / 2;
// T(n) = 1
忽略常数项
忽略低次项
忽略系数
时间复杂度
O(n) : time complexity,一般讨论最坏时间复杂度
不考虑常数,只保留最高阶,不考虑系数
常数阶 O(1):没有循环等复杂结构,消耗的时间不随某个变量的增长而增长
对数阶 O(log2n):while循环
线性阶 O(n):单层for循环
线性对数阶 O(nlog2n):将线性阶的代码循环n遍
平方阶 O(n^2):双层for循环
立方阶 O(n^3)
k次方阶 O(n^k)
指数阶 O(2^n)
空间复杂度
占用存储空间大小的量度 space complexity
冒泡排序
依次比较相邻元素的值,如果发现逆序,则交换,使值较大的元素从前向后移
优化:如果一轮比较下来没有进行交换,说明序列有序,因此在排序过程中设置一个flag判断元素是否进行锅交换
注意:以下代码是按照升序排序,因此第一轮排序之后最大值确定,下一轮排序的范围为 0-arr.length-1-i
时间复杂度:O(n^2)
package sort;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {
1,34,2,4,56,23,7};
int[] arr2 = bubble(arr);
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr[i]+"\t");
}
}
private static int[] bubble(int[] arr) {
int temp = 0;
for (int i = 0; i < arr.length-1; i++) {
boolean flag = false;
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j]>arr[j+1]){
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
flag = true;
}
}
if(flag == false){
break;
}else{
flag = true; // reset flag for next loop
}
}
return a