[数据结构]排序算法的时间复杂度

排序算法介绍:

简单的来讲哈,就是将一组数据按照指定的规则顺序进行排列的过程。常见的排序算法分为内部排序外部排序:内部排序就是指所有数据在内部存储中进行排序。相对的外部排序就是指因为数据量过大无法全部加载到内部存储时,需要借助外部存储进行排序的算法。

常见的排序算法:


算法的时间复杂度

衡量一个算法的执行时间一般有两种方法,统计法、估算法。所谓的统计法就是在程序开到到程序结束记录程序的运行时间,但这种方法存在局限性,因为程序的执行时间一般受计算机的硬件、软件限制。同样的程序在不同计算机中的表现不同。估算法则是根据某个算法的时间复杂度来判断那段算法更优。


时间频度

一个算法中语句的执行次数跟算法的执行时间是成正比的,算法中语句的执行次数就称为算法的时间频度。用T(n)来表示

例如:

@Test
	public void run() {
		int res = 0;
		int end = 100;
        //算法1
		for (int i = 1; i <= end; i++) {
			res += i;
		}
        //算法2
		res = (1 + end) * end / 2;
	}

那么在这个例子中算法1执行了end+1次;算法2执行了一次;

所以算法1的时间复杂度为:T(n)=n+1;

所以算法2的时间复杂度为:T(n)=1; 


时间复杂度的计算

忽略常数项

 

T(n)=2n+20

T(n)=2*n

T(n)=3n+10

T(n)=3n

1

22

2

13

3

2

24

4

16

6

5

30

10

25

15

8

36

16

34

24

15

50

30

55

45

30

80

60

100

90

100

220

200

310

300

300

620

600

910

900

由表和折线图不难看出,在相同系数的情况下时间复杂度可以忽略常数项。因为随着数据量的增大曲线重合。

忽略低次项

 

T(n)=2n^2+3n+10

T(2n^2)

T(n^2+5n+20)

T(n^2)

1

15

2

26

1

2

24

8

34

4

5

75

50

70

25

8

162

128

124

64

15

505

450

320

225

30

1900

1800

1070

900

100

20310

20000

10520

10000

由表和折线图不难看出,随着n的增大低次项系数可以忽略。

忽略系数

T(3n^2+2n)

T(5n^2+7n)

T(n^3+5n)

T(6n^3+4n)

1

5

12

6

10

2

16

34

18

56

5

85

160

150

770

8

208

376

552

3104

15

705

1230

3450

20310

30

2760

4710

27150

162120

100

30200

50700

1000500

6000400

 根据折线图可以看出在平方的情况下时间复杂度与系数关系不大,所以可以忽略系数;但是在立方的情况下时间复杂度与系数的关系就非常大了,可以说系数是立方时间复杂度的关键。


一般情况下,一个算法的语句执行次数是数据规模n的某个函数,记做T(n),若存在某个函数f(n)与T(n)的比值无线接近于1,那么T(n)和f(n)就同处一个数量级,表示为f(n)=O(f(n)),为算法的时间复杂度。

计算时间复杂度的方法:

对于平方的算法:忽略常数项,忽略低次项,忽略系数

例:T(n)=n²+7n+6  => T(n)=O(n²)


常见的时间复杂度:

常数阶O(1)

无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1)

对数阶O(log2n)

在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。假设循环x次之后,i 就大于 2 了,此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2n也就是说当循环 log2n 次以后,这个代码就结束了。因此这个代码的时间复杂度为:O(log2n)  。 O(log2n) 的这个2 时间上是根据代码变化的,i = i * 3 ,则是 O(log3n) 。

线性阶O(n)

for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度

线性对数阶O(nlogN) 

线性对数阶O(nlogN) 其实非常容易理解,将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是了O(nlogN)

方阶O(n²)

平方阶O(n²) 就更容易理解了,如果把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²),这段代码其实就是嵌套了2层n循环,它的时间复杂度就是 O(n*n),即  O(n²) 如果将其中一层循环的n改成m,那它的时间复杂度就变成了 O(m*n)

这里立方阶、k次方阶就不举例子了。


平均复杂度和最坏复杂度:

平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,该算法的运行时间。

最坏情况下的时间复杂度称最坏时间复杂度。一般讨论的时间复杂度均是最坏情况下的时间复杂度。

最坏情况下的时间复杂度是算法在任何输入实例上运行时间的界限,这就保证了算法的运行时间不会比最坏情况更长。

平均时间复杂度和最坏时间复杂度是否一致,和算法有关。

这里注明一下最后一张图表的来源:https://blog.csdn.net/JohinieLi/article/details/80959584

从之前的知识可以分析出,选择、插入、冒泡等基本算法至少是需要两层循环。依次可以继续分析下去。

猜你喜欢

转载自blog.csdn.net/we1less/article/details/106244546