时间复杂度和空间复杂度
时间复杂度:
首先要说的是,时间复杂度的计算并不是计算程序具体运行的时间,而是算法执行语句的次数。
时间复杂度的计算:
(1)如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
int x=1;
while (x <10)
{
x++;
}
该算法执行次数是10,是一个常数,用时间复杂度表示是O(1)。
(2)当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
;
}
}
该算法for循环,最外层循环每执行一次,内层循环都要执行n次,执行次数是根据n所决定的,时间复杂度是O(n^2)。
(3)循环不仅与n有关,还与执行循环所满足的判断条件有关。
int i=0;
while (i < n && arr[i]!=1)
{
i++;
}
在此循环,如果arr[i]不等于1的话,时间复杂度是O(n)。如果arr[i]等于1的话,则循环执行一次判断跳出,时间复杂度是O(1)。
空间复杂度
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。
计算方法:
①忽略常数,用O(1)表示
②递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间
③对于单线程来说,递归有运行时堆栈,求的是递归最深的那一次压栈所耗费的空间的个数,因为递归最深的那一次所耗费的空间足以容纳它所有递归过程。
如:
int a;
int b;
int c;
printf("%d %d %d \n",a,b,c);
它的空间复杂度O(n)=O(1);
int fun(int n,)
{
int k=10;
if(n==k)
return n;
else
return fun(++n);
}
递归实现,调用fun函数,每次都创建1个变量k。调用n次,空间复杂度O(n*1)=O(n)。
交换排序
时间复杂度(平均,最优,最差),空间复杂度,稳定性
冒泡排序
算法描述:比较两个相邻的元素,如果升序的话,前面的比后面的大,就交换,这样一轮下来,就会找到这组数据中最大的元素,然后抛开这个元素继续重复上述步骤.直到排完为止.
快速排序
算法描述:任取待排序中的某一元素作为基准值<一般为第一个或者最后一个>,按照该排序码,将待排序集合分割成两个子序列,左边的序列比基准值小,右边的比基准值大.然后对左右子序列重复上述步骤.直到排完为止
插入排序
直接插入排序
算法描述:从第一个元素开始,该元素已经排好序,继续取后续元素与排好序的元素依次进行比较,升序的话插入到比前一个大比后一个小的位置,然后重复上述步骤,直到插完元素为止.
希尔排序(直接插入排序的优化)
算法描述:对整个待排序序列进行分组,然后对每一组进行直接插入排序.(4组,2组,1组)
选择排序
直接选择排序
算法描述:在未排序的序列中找到最小的元素,存放到序列的首位置,找到最大的元素存放到序列的末尾.然后抛开首位和末尾,继续重复该步骤,直到排完为止.
堆排序
算法描述:
若升序的话,就将堆调成一个大堆,若降序的话,就将堆调成一个小堆.从倒数第一个非叶子节点开始往根遍历,若当前节点的值都大于左右孩子,则不用动,若是小于,就将左右孩子当中最大的节点与当前节点交换,交换后就需要进行向下调整(因为交换会影响大堆结构).重复上述步骤,直到根节点为止。
归并排序
算法描述:将待排序的元素序列分为两个长度相等的子序列,对每个子序列进行排序,然后将他们合并成一个序列,合并两个子序列的过程称为二路归并.
总览
非比较类排序
计数排序
算法描述:找到待排序列中最大最小的元素,然后以此确定临时空间的大小,在临时空间中,以待排序列组中元素的大小为下标,该元素出现的次数为该下标对应的元素,根据临时空间的统计结果,重新对元素进行回收.
例如:
对
2 3 8 7 1 2 2 2 4 6 5 8 4 7 9 1 2
进行排序
基数排序
算法描述:把待排序中的元素按照低位先排序,然后收集,再按照高位排序,再收集,直至最高位.
①,获取序列中的最大数,然后取得其位数,然后利用计数排序的特点,定义10个元素的数组,分别统计以待排序列元素的每一位为数组的下标的元素的个数,然后再定义一个数组存每个的起始地址.开一个辅助空间,放置元素.再回收这些元素.