1.数据结构和算法

数据结构与算法

1.为什么要学习数据结构与算法?

掌握数据结构和算法,不管对于阅读框架源码,还是理解其背后的设计思想,都是非常有用的!

2.什么是数据结构与算法?

从广义上讲,数据结构就是指一组数据的存储结构,算法就是操作数据的一组方法!
从狭义上讲,就是指常见的一些数据结构和算法,如队列,栈,堆,二分查找,动态规划等.
数据结构和算法是相辅相成的,数据结构是为算法服务的,算法是作用在特定的数据结构之上,因此,无法孤立数据结构来学习算法,也无法孤立算法来学习数据结构!

3.复杂度分析

复杂度分析是数据结构与算法中最重要的一个概念,学会了它,就学会了数据结构与算法的精髓!

3.1为什么需要复杂度分析?

通过统计,监控等就能获取到算法的执行时间和占用的内存大小,为什么还需要做空间,时间复杂度分析呢?
统计,监控这种方式叫做事后统计法,这种统计方法有很大的局限性:

  1. 测试结果非常依赖测试环境;
  2. 测试结构受数据规模的影响比较大.

所以需要一种不需要执行就能获取执行时间和空间的方式,这就是时间及空间复杂度!

3.2大O复杂度表示法

估算以下代码的执行时间

 int cal(int n) {
   int sum = 0;
   int i = 1;
   for (; i <= n; ++i) {
     sum = sum + i;
   }
   return sum;
 }
 // T(n)= O(2n+2)

假设每一行代码的执行时间都是unit_time,
第2,3行代码都是1个unit_time,第4,5行都是n个unit_time,代码的总执行时间是
(2n+2)*unit_time 所以 代码的执行时间 T(n)与每行代码的执行次数成正比.
这个规律就是大O表示法

T(n) = O(f(n))

T(n)表示代码的执行时间 , n表示数据规模的大小,f(n)表示每行代码执行的次数总和.
因为这是一个公式,所以用f(n)表示,公式中的O表示执行时间T(n)与f(n)表达式成正比.
当n很大时,比如10000,100000,而公式中的低阶,常亮,系统三部分并不左右增长趋势,所以都忽略.只需要记录一个最大量级即可!
所以以上例子的时间复杂度,可以记为: T(n) = O(n).

3.2.1时间复杂度分析

A. 只关注循环执行次数最多的一段代码.

B. 加法法则:总复杂度等于量级最大的那段代码的复杂度.

int cal(int n) {
   int sum_1 = 0;
   int p = 1;
   for (; p < 100; ++p) {
     sum_1 = sum_1 + p;
   }
	
   int sum_2 = 0;
   int q = 1;
   for (; q < n; ++q) {
     sum_2 = sum_2 + q;
   }
 
   int sum_3 = 0;
   int i = 1;
   int j = 1;
   for (; i <= n; ++i) {
     j = 1; 
     for (; j <= n; ++j) {
       sum_3 = sum_3 +  i * j;
     }
   }
 
   return sum_1 + sum_2 + sum_3;
 }

时间复杂度 T(n)= T1(n)+T2(n) = max(O(f(n)),O(g(n)) = O(max(f(n),g(n))).

C. 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

int cal(int n) {
   int ret = 0; 
   int i = 1;
   for (; i < n; ++i) {
     ret = ret + f(i);
   } 
 } 
 
 int f(int n) {
  int sum = 0;
  int i = 1;
  for (; i < n; ++i) {
    sum = sum + i;
  } 
  return sum;
 }

时间复杂度T(n)=T1(n)* T2(n) = O(n*n)=O(n2)

3.2.2常见的时间复杂度实例分析

A. 多项式量级

O(1) : 一般情况下,只要算法中不存在循环语句,递归语句,即使有成千上万行的代码,其时间复杂度也是O(1)

O(logn),O(nlogn) : 对数阶时间复杂度非常常见,同时也是最难分析的一种.

 i=1;
 while (i <= n)  {
   i = i * 2;
 }

从代码中可以看到, 变量i从1开始取,每循环1次就乘以2,当大于n时,循环结束.这就是等比数列

x=log2n ,所以这个代码时间复杂度是O(log2n)
在对数阶时间复杂度的表示方法里,忽略对数的底,统一表示为O(logn).

O(m+n),O(m*n) : 代码是由两个数据的规模决定的

int cal(int m, int n) {
  int sum_1 = 0;
  int i = 1;
  for (; i < m; ++i) {
    sum_1 = sum_1 + i;
  }

  int sum_2 = 0;
  int j = 1;
  for (; j < n; ++j) {
    sum_2 = sum_2 + j;
  }

  return sum_1 + sum_2;
}

以上代码时间复杂度为O(m+n)

B. 非多项式量级
O(2n) 和 O(n!)
当数据规模越来越大时,非多项式量级算法的执行时间会急剧增加,求解问题的执行时间会无线增大,所以非多项式量级算法是非常低效的算法.

3.2.3空间复杂度分析

时间复杂度的全程是渐进时间复杂度,表示算法的执行时间与数据规模之间的增长关系.
空间复杂度全程就是渐进空间复杂度,表示算法的存储空间与数据规模之间的增长关系.
常见的空间复杂度就是O(1),O(n),O(n2)

3.2.4最好、最坏、平均、均摊时间复杂度
// n 表示数组 array 的长度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}
  1. 最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度.例子中是O(1).
  2. 最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度.例子中是O(n).
  3. 平均情况时间复杂度, 以以上例子来说, 查找变量x在数据中的位置,有n+1种情况,在数据的0~n-1位置上和不在数组中, 把每种情况下查找遍历的元素个数累加,再除以n+1就是需要遍历元素的平均值.

    公式简化以后,就是**平均时间复杂度**O(n).
    以上公式的最大问题是没有将各种情况发生的概率统计进去,公式可以修改为

    简化以后仍然是O(n),这个值是 加权平均复杂度或者期望时间复杂度.
  4. 均摊时间复杂度就是一种特殊的平均时间复杂度, 当对一个数据结构进行操作时,大部分情况时间复杂度都很低,只有个别情况下时间复杂度比较高,而且存在前后之间的时序关系,这是可以将较高时间复杂度那次操作的耗时,平摊到其他时间复杂度比较低的操作上. 这种分析方法叫做 摊还分析法, 通过这种方法分析的时间复杂度叫做 均摊时间复杂度.

4.数据结构和算法概述

以下是数据结构与算法的知识点

数据结构与算法知识点

5.常见的数据结构和算法

下面主要学习一些常见的数据结构与算法:
10个数据结构: 数组,链表,栈,队列 ,散列表,二叉树,堆,跳表,图,Trie树.
10个算法:
递归,排序,二分查找,搜索,哈希算法,贪心算法,分治算法
,回朔算法,动态规划,字符串匹配算法.

后续章节会详细的讲解这10种数据结构和10种算法.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值