时间复杂度(Time Complexity):
总运算次数表达式中受n的变化影响最大的那一项(不含系数)(注:若算法中语句执行次数为一个常数,则时间复杂度为O(1))
- 一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)
空间复杂度(Space Complexity):
一个算法在运行过程中临时占用存储空间大小的量度(包括程序代码所占用的空间,输入数据所占用的空间和辅助变量所占用的空间这三个方面。)
注:
- 如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);
- 当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(log2n);
- 当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n).
冒泡排序
选择排序
步骤:(升序)
首先找到数组中最小的数,与数组第一位数交换位置(如果最小数是本身与本身交换)。接着在剩下的数中找第二小的数,与数组第二位数交换位置(如果第二小数是本身与本身交换)........按照相同步骤依次执行最后一个元素。
数据交换N次,数据比较(N-1)+(N-2)+........+3+2+1=N*(1+N-1)/2=N^2/2次(最后一个元素与自身交换)
时间复杂度:O(n2)
空间复杂度:O(1)
1 #include<stdio.h>
2 #include<malloc.h>
3 int main()
4 {
5 int n,i,j,min,temp;
6 scanf("%d",&n);
7 int *a=(int *)malloc(sizeof(int)*n);
8 for(i=0;i<n;i++)
9 scanf("%d",&a[i]);
10 for(i=0;i<n;i++)
11 {
12 min=a[i];//最小数
13 temp=i;//最小数在数组中的位置
14 for(j=i+1;j<n;j++)
15 {
16 if(min>a[j])//比较大小
17 {
18 min=a[j];
19 temp=j;
20 }
21 }
22 a[temp]=a[i];//交换
23 a[i]=min;
24 }
25 for(i=0;i<n;i++)
26 printf("%d ",a[i]);
27 return 0;
28 }
- 运行时间与输入无关,有序数组输入其排序用时和相同长度的无序数组是一样的。
- 数据移动最少,每次只需移动两个数组
插入排序
直接插入排序
步骤:(升序)
将原数组分成两组,一组为已排好序的数组A,另一组为乱序数组B。数组A倒序(A[length-1])每个元素依次与数组B的一个元素比较(从B[0]开始),若A组某元素比B组元素大,A组元素后退一位为,B组元素腾出空间,然后B组推下一个元素.
时间复杂度:O(n2)
空间复杂度:O(1)
1 #include<stdio.h>
2 #include<malloc.h>
3 void sort(int *a,int n);
4 int main()
5 {
6 int n,i;
7 scanf("%d",&n);
8 int *a=(int *)malloc(sizeof(int )*n);
9 for(i=0;i<n;i++)
10 scanf("%d",&a[i]);
11 sort(a,n);
12 for(i=1;i<n;i++)
13 printf("%d ",a[i]);
15 return 0;
16 }
17 int less(int a,int b)
18 {
19 if(a<b) return 1;
20 return 0;
21 }
22 void sort(int *a,int n)
23 {
24 int i,j,temp,k;
25 for(i=1;i<n;i++)
26 {
27 temp=a[i];
28 for(j=i-1;j>=0&&less(temp,a[j]);j--)
29 {
30 a[j+1]=a[j];
31 }
32 a[j+1]=temp;
33 }
34 }
- 插入排序所需时间取决于输入元素的顺序
- 插入排序更适用于部分有序的数组,和小规模数组
希尔排序
步骤:(升序)
为加快速度的插入排序,交换不相邻的元素将数组部分变有序。使数组间隔h(h会改变)个元素有序。h在变化前,程序使h个元素间隔的小数组有序。
例:2—6—70(小数组每个元素间隔h个元素)..
时间复杂度:
空间复杂度:O(1)
#include<stdio.h>
#include<malloc.h>
//伸序
int less(int a[],int i,int j)
{
if(a[i]<a[j])
return 1;
return 0;
}
int main()
{
int n,h,i,j,temp,k;
scanf("%d",&n);
int *a=(int *)malloc(sizeof(int)*n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
h=1;
while(h<n/3)
h=3*h+1;
while(h>=1)
{
for(i=h;i<n;i++)
{
for(j=i;j>=h&&less(a,j,j-h);j-=h)
{
temp=a[j];
a[j]=a[j-h];
a[j-h]=temp;
}
}
h/=3;
}
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
疑问1:出现6—4—5这样的小数组,排序后还是为无序小数组?
答:并不会出现6—4—5这样的小数组,因为:
j=h 为 6—4小数组,会重新排序为有序4—6小数组
j=2h 为4—6—5小数组,会重新排序为有序4—5—6小数组
疑问2:如何选择h的递增数列?
书中用的的3*h+1与复杂递增序列的性能相近,但比较简单,所以书中将该递增数列提出作为参考
并未找到最优递增数列
优势:
希尔排序比插入排序和选择排序快得多,并且数组越大,优势越大。
参考资料:《算法第四版》
如何计算时间/空间复杂度:http://www.cnblogs.com/zakers/archive/2015/09/14/4808821.html