时间频度:一个算法花费的时间与算法的执行次数成正比例,一个算法中语句执行次数称为语句频度或时间频度,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 arr;
}
}
package sort;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int)(Math.random()*8000000); // [0,8000000)
}
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = format.format(date);
System.out.println("before sorting "+ date1Str);
bubble(arr);
Date date2 = new Date();
String date2Str = format.format(date2);
System.out.println("after sorting "+ date2Str);
}
private static void 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 = false; // reset flag for next loop
}
}
}
}
结果:
before sorting 2020-06-14 10:09:58
after sorting 2020-06-14 10:10:09
selection sort
时间复杂度:O(n^2) 时间会缩短很多
基本思想:第一次从整个数组中找到最小值和 arr[0] 进行交换;第二次从 arr[1] - arr[n-1] 中找到最小值和 arr[1] 交换,第三次从 arr[2] - arr[n-1] 找到最小值和 arr[2] 进行交换…第 n-1 次从 arr[n-2] - arr[n-1] 中选取最小值和 arr[n-2] 交换,总共 n-1 次得到一个从小到大的序列
引入 minIndex 获取最小值的下标
package sort;
import java.util.Arrays;
public class SelectionSort {
public static void main(String[] args) {
//int[] arr = {1,34,2,4,56,23,7,-1,20};
//System.out.println(Arrays.toString(arr));
//select(arr);
//System.out.println(Arrays.toString(arr));
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int)(Math.random()*8000000); // [0,8000000)
}
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = format.format(date);
System.out.println("before sorting "+ date1Str);
select(arr);
Date date2 = new Date();
String date2Str = format.format(date2);
System.out.println("after sorting "+ date2Str);
}
private static void select(int[] arr) {
for (int i = 0; i < arr.length-1; i++) {
int minIndex = i;
int min = arr[i];
for (int j = i+1; j < arr.length; j++) {
if(min>arr[j]){
min = arr[j];
minIndex = j;
}
}
if(minIndex!=i){
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
}
before sorting 2020-06-14 10:47:26
after sorting 2020-06-14 10:47:29
insertion sort 时间复杂度:O(n^2)
基本思想: 将n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有 n-1 个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表
将待插入的数据保存的变量中,定义插入的下标
package sort;
import java.util.Arrays;
public class InsertionSort {
public static void main(String[] args) {
int[] arr = {
1,34,2,4,56,23,7,-1,20};
System.out.println(Arrays.toString(arr));
insert(arr);
System.out.println(Arrays.toString(arr));
}
private static void insert(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int insertVal = arr[i]; // 保存待插入的数
int insertIndex = i-1;
while(insertIndex>=0 && insertVal<arr[insertIndex]){
arr[insertIndex + 1] = arr[insertIndex]; // 后移
insertIndex--;
}
if(insertIndex+1!=i){
arr[insertIndex + 1] = insertVal;
}
}
}
}
TEST TIME:
before sorting 2020-06-14 14:31:21
after sorting 2020-06-14 14:31:22
shell sorting 也是一种插入排序;也称为缩小增量排序
基本思想:把记录按照下标的一定增量分组,对每组使用直接插入排序算法排序,随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰好分成一组,算法结束
对有序序列在插入时有两种方法:交换法;移动法
package sort;
import java.util.Arrays;
public class ShellSortExchange {
public static void main(String[] args) {
int[] arr = {
1,34,2,4,56,23,7,-1,20};
System.out.println(Arrays.toString(arr));
shell(arr);
System.out.println(Arrays.toString(arr));
}
private static void shell(int[] arr) {
int temp = 0;
for(int gap = arr.length / 2; gap > 0 ; gap /= 2){
for (int i = gap; i < arr.length; i++) {
for (int j = i-gap; j >= 0 ; j-=gap) {
// if current value is greater than the value added 5 steps
// exchange them
if(arr[j]>arr[j+gap]){
temp = arr[j];
arr[j] = arr[j+gap];
arr[j+gap] = temp;
}
}
}
}
}
}
time:
before sorting 2020-06-14 15:10:09
after sorting 2020-06-14 15:10:15
package sort;
import java.util.Arrays;
public class ShellSortMove {
public static void main(String[] args) {
int[] arr = {
1,34,2,4,56,23,7,-1,20};
System.out.println(Arrays.toString(arr));
shell(arr);
System.out.println(Arrays.toString(arr));
}
private static void shell(int[] arr) {
for(int gap = arr.length / 2; gap > 0; gap /= 2){
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]){
// move
arr[j] = arr[j-gap];
j -= gap;
}
// when quit while loop, found location for inserting temp
arr[j] = temp;
}
}
}
}
}
time:
before sorting 2020-06-14 15:29:08
after sorting 2020-06-14 15:29:08