目录
写在前面
本来超详系整理 好了点了发布,结果发现没发出去,回到草稿箱只剩这个半成品了,写了一整天心态崩溃。没有心力再重新来过了,就这样吧,大家记得随时保存TT
刚开始准备秋招刷题,花一天时间简单了解了下数据结构中的排序部分,现将学习到的内容简单整理,文中代码l来自于网络的部分,会在最后附上链接,欢迎大家学习交流。
推荐一个学习数据结构的直观网站:https://visualgo.net/zh
零基础可以先看一下这个自己理解一下再来看文章的整理。
评价指标
排序算法的评价指标主要是两个:
(1)时间复杂度。
O(f(n))关注的是算法执行时间和数据规模的增长关系,表征的是算法的执行时间的变化趋势和f(n)存在正相关关系。就目前的理解它主要关注算法中的循环,也就是存在未知参量n的部分。所以观察代码时间复杂度,首先关注代码中循环最多的部分。
常见的时间复杂度具体举例:
1)O(1)和O(n)和O(m+n)
int HelloWorld(int n) {
int i = 0; #执行时间 1
for(; i<n; i++) { #执行时间n
printf("Hello, World!"); #执行时间n
}
}
以上代码执行时间是(2n+2),O()关注的是变化趋势,所以摄取系数和常数项,以上代码的时间复杂度就是O(n)。就是可以简单的看循环,因为上面那个循环循环了n次所以时间复杂度是O(n),如果没有3/4行即没有循环,这种情况不管代码多少行,执行时间都是常数,则时间复杂度为O(1)。
int HelloWorld(int n,int m) {
int i = 0; #执行时间 1
for (; i<n; i++) { #执行时间n
printf("Hello, World!"); #执行时间n
}
for (int j=0;j<m;j++){
printf("hey!");
}
}
关注循环,上面两个循环,由于m和n的量级无法确定,所以时间复杂度为O(n+m)
2) O(n²)和O(m*n)
int HelloWorld(int n) {
int i = 0; #执行时间 1
for(; i<n; i++) { #执行时间n
for(int j=0;j<n;j++){ #执行时间n
printf("Hello, World!");
}
}
像上面这种循环嵌套循环的则是使用乘法,关注循环,时间复杂度就是O(n²),如果循环里面套的是j<m
则时间复杂度就是O(m*n)
3)O(logn)和 O(nlogn)
int HelloWorld(int n) {
int i = 1;
while( i<n) {
i=i*2;
}
}
关注循环,可能会想这个复杂度不应是O(n)吗,关注n的同时不要忘了关注循环的另一个参数i,循环截止条件是i<n
,循环体中 i=i*2
,所以循环终止的条件也就是2i<n,所以它的复杂度是O(log2n),因为关注的是增长趋势,系数底数都可以忽略,无论是以什么为底,时间复杂度表示为O(logn)。
int HelloWorld(int n) {
int i = 1;
for (int j=0 ;j<n;j++){
while ( i<n) {
i=i*2;
}
}
}
如果是像(2)中所说的有循环套循环,即外面套了一个n 循环,时间复杂度就是O(nlogn)
时间复杂度还有最好、最坏、平均复杂度。最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度。最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度。平均时间复杂度就是平均情况时间复杂度。没有具体去看,等以后有时间再补充。
(2)空间复杂度
和时间复杂度相对应,空间复杂度就是指代码运行期间所临时占用的储存空间大小的变化趋势。也用O()函数表示,表征算法储存空间与数据规模之间的增长关系。
1) O(1)
int HelloWorld(int n) {
int i = 1;
while ( i<n) {
i=i*2;
}
}
像上面这个代码,虽然有循环,但是它需要的临时空间大小不跟n没有比例关系,所以是一个常量。表示为O(1)。
2) O(n)
int HelloWorld(int n) {
int [] list = new int[n];
int i = 1;
while ( i<n) {
i=i*2;
}
}
上一段代码中,分配了一个长度为n的数组空间,所以复杂度是O(n)。