数据结构与算法简介以及如何学习

77 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

简介

数据结构(Data Structure):计算机存储、组织数据的方式。

算法(Algorithm):一系列解决问题的指令。算法研究的目的是为了更有效的处理数据,提高数据运算效率。

数据结构与算法的关系:

  • 程序 = 数据结构 + 算法
  • 数据结构为算法提供服务,算法围绕数据结构操作

算法为一些特定的数据结构提供了解决方案,如下表:

数据结构算法
链表遍历链表、删除链表节点
树、图深度/广度优先遍历
数组冒泡/选择/插入/归并/快速排序、顺序/二分搜索

如何学习数据结构与算法

要想学好数据结构与算法可以从下面几个点入手:

  • 理论:熟悉数据结构与算法的特点,应用场景
  • 刷题:做一些算法题
  • 实战:在工作、真实项目中使用

理论

了解掌握常见的数据结构,如下:

  • 栈:先进后出(FILO)的数据结构,是一种特殊的线性表
  • 队列:先进先出(FIFO)的数据结构,是一种特殊的线性表
  • 链表:数据元素按照链式存储结构进行存储的数据结构
  • 集合:由一组无序且不重复的元素构成(ES6中的Set)
  • 字典:无序的、由键-值(key-value)对组成的集合(ES6中的Map)
  • 树:由n(n≥0)个有限节点组成一个具有层次关系的集合,非线性结构
  • 图:由若干给定的顶点及连接两顶点的边所构成的图形
  • 堆:一种经过排序的树形数据结构,每个节点都有一个值,通常我们所说的堆的数据结构是指二叉树

了解掌握常见的排序与搜索算法:冒泡算法、选择算法、插入算法、归并算法、快速算法、顺序算法、二分搜索等

了解掌握常见的算法设计思想:分而治之、动态规划、贪心算法、回溯算法

刷题

  • LeetCode 刷题推荐分类型刷题,不推荐按题号刷。
  • 重点关注通用套路,分析时间复杂度与空间复杂度,如何优化时间复杂度与空间复杂度。

实战

  • 前端与数据结构/算法的结合点(JS中的堆栈、任务队列等)
  • 可以通过阅读vue、react等前端流行库的源码来了解数据结构与算法在前端的应用
  • 工作中使用

算法复杂度

算法复杂度是指算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。

进一步分为 时间复杂度空间复杂度

时间复杂度

时间复杂度 是一个函数,描述该算法的运行时间(大概的时间或趋势,不代表具体的多少秒)。表示方式:用大写字母 O 表示,比如:O(1) O(n) O(logN) 等。

用JS代码来理解:

  • 如下是O(1)时间复杂度的代码,只会执行一次:
let i = 0
i += 1
  • 如下是O(n)时间复杂度的代码,for循环内代码会执行n次:
for(let j = 0; j < n; j++) {
    console.log(j)
}

将前面两段代码结合,时间复杂度也是O(n),可以理解为 O(1) + O(n) = O(n)

let i = 0
i += 1
for(let j = 0; j < n; j++) {
    console.log(j)
}
  • 如下是O(n^2)【O(n)的二次方】时间复杂度的代码,双层for循环
for(let j = 0; j < n; j++) {
    for(let i = 0; i < n; i++) {
        console.log(j, i)
    }
}
  • 如下是 O(logN) 时间复杂度的代码,while循环体内的代码执行了logN次:
let i = 1
while(i < n) {
    console.log(i)
    i *= 2
}

while 停止执行的时机是当 i >= n 的时候,也就是求 2的多少次方大于等于n,所以这个次数是 logN 次。

空间复杂度

空间复杂度 是一个函数,表示算法运行过程中临时占用的空间的大小。表示方式:用大写字母 O 表示,比如:O(1) O(n) O(n^2) 等。

用JS代码来理解:

  • 如下是O(1)时间复杂度的代码,单个变量占用空间:
let i = 0
i += 1
  • 如下是O(n)时间复杂度的代码,数组内添加进了n个值相当于占用了n个内存单元:
const arr = []
for(let j = 0; j < n; j++) {
    arr.push(j)
}
  • 如下是O(n^2)时间复杂度的代码,arr是二位数组/矩阵,占用了n的二次方个内存单元
const arr = []
for(let j = 0; j < n; j++) {
    arr.push([])
    for(let i = 0; i < n; i++) {
        arr[j].push(i)
    }
}