计算机基础课第 32 期分享

上节讲了一些经典算法,比如给数组排序,找图的最短路径。

而上节没讲的是算法处理的数据存在内存里的格式是什么?

你肯定不想数据像 John Green 的大学宿舍一样乱,到处都是食物,衣服和纸。我们希望数据是结构化的,方便读取,因此计算机科学家发明了 "数据结构"。

01

数组

上节已经介绍了一种基本数据结构:数组(Array)也叫列表(list)或向量(Vector)(在其它编程语言里)。数组的值一个个连续存在内存里,所以不像之前,一个变量里只存一个值(比如 j = 5),我们可以把多个值存在数组变量里,为了拿出数组中某个值,我们要指定一个下标(index)大多数编程语言里,数组下标都从 0 开始。用方括号 [ ] 代表访问数组。如果想相加数组 J 的第一个和第三个元素,把结果存在变量 a,可以写a=J[0]+J[2]这样一行代码,数组存在内存里的方式十分易懂。

为了简单,假设编译器从内存地址 1000 开始存数组,数组有7个数字,像上图一样按顺序存,写 j[0],会去内存地址 1000,加 0 个偏移,得到地址 1000,拿值:5。如果写 j[5],会去内存地址 1000,加 5 个偏移,得到地址 1005,拿值:4。

很容易混淆 "数组中第 5 个数" 和 "数组下标为 5 的数",它们不是一回事,记住,下标 5 其实是数组中第 6 个数,因为下标是从 0 开始算的。

数组的用途广泛,所以几乎所有编程语言都自带了很多函数来处理数组。举例,数组排序函数很常见,只需要传入数组,就会返回排序后的数组,不需要写排序算法。

02

字符串

数组最常用的是 字符串 (string),其实就是字母,数字,标点符号等  组成的数组。前面讨论过计算机怎么存储字符,写代码时 用引号括起来就行了 j = "STAN ROCKS",虽然长的不像数组,但的确是数组。幕后看起来像这样,注意,字符串在内存里以 0 结尾,不是"字符0",是"二进制值0" 这叫字符"null",表示字符串结尾。这个字符非常重要,如果调用 print 函数,print 在屏幕上输出字符串,会从开始位置,逐个显示到屏幕,但得知道什么时候停下来,否则会把内存里所有东西 都显示出来。0 告诉函数何时停下。

因为计算机经常处理字符串,所以有很多函数专门处理字符串。比如连接字符串的 strcat,strcat 接收两个字符串,把第二个放到第一个结尾。我们可以用数组做一维列表,但有时想操作二维数据,比如电子表格,或屏幕上的像素,那么需要 矩阵(Matrix),可以把矩阵看成数组的数组。一个 3x3 矩阵就是一个长度为3的数组, 数组里每个元素都是一个长度为3的数组。可以这样初始化,内存里是这样排列的,为了拿一个值,需要两个下标,比如 j2,告诉计算机在找数组 2 里,位置是 1 的元素,得到数字 12。

矩阵酷的地方是,不止能做 3x3 的矩阵,任何维度都行,可以做一个5维矩阵,然后这样访问 a = j218[3],现在你知道了  怎么读一个 5 维矩阵。

03

结构体

目前我们只存过单个数字/字符,存进数组或矩阵,但有时, 把几个有关系的变量存在一起, 会很有用,比如银行账户号和余额,多个变量打包在一起叫结构体 (Struct)。现在多个不同类型数据,可以放在一起,甚至可以做一个数组,里面放很多结构体,这些数据在内存里,会自动打包在一起。如果写 j[0],能拿到  j[0] 里的结构体。然后拿银行账户和余额,存结构体的数组,和其它数组一样。创建时就有固定大小,不能动态增加大小。还有,数组在内存中按顺序存储,在中间插入一个值很困难,但结构体可以创造更复杂的数据结构,消除这些限制,但结构体可以创造更复杂的数据结构,消除这些限制。

我们来看一个结构体,叫 节点(node),它存一个变量一个指针(pointer)。"指针" 是一种特殊变量,指向一个内存地址,因此得名。

用节点可以做链表(linked list)链表是一种灵活数据结构,能存很多个 节点 (node),灵活性是通过每个节点 指向 下一个节点实现的,假设有三个节点,在内存地址 1000,1002, 1008(隔开的原因可能是创建时间不同),它们之间有其他数据,可以看到第一个节点,值是 7,指向地址 1008,代表下一个节点,位于内存地址 1008。现在来到下一个节点,值是 112,指向地址 1002,如果跟着它,会看到一个值为 14 的节点。这个节点  指回地址 1000,也就是第一个节点,这叫循环链表。

但链表也可以是非循环的,最后一个指针是 0,"null",代表链表尽头。当程序员用链表时,很少看指针具体指向哪里,而是用链表的抽象模型,就像上图,更容易看懂。

数组大小需要预先定好,链表大小可以动态增减,可以创建一个新节点,通过改变指针值,把新节点插入链表,链表也很容易重新排序,两端缩减,分割,倒序等。链表也适合上节的排序算法

因为灵活,很多复杂数据结构都用链表,最出名的是 队列(queue)和 栈(stack)。

"队列" 就像邮局排队,谁先来就排前面,"队列" 就像邮局排队,谁先来就排前面。虽然你可能只想买邮票,而前面的人要寄 23 个包裹,这叫 先进先出(FIFO)。我指队列,不是指那 23 个包裹,想象有个指针叫"邮局队列",指向链表第一个节点。第一个节点是 Hank,服务完 Hank 之后,读取 Hank 的指针,把"邮局队列"指向下一个人,这样就把 Hank "出队"(dequeue)了,如果我们想把某人"入队"(enqueue)意思是加到队列里。要遍历整个链表到结尾,然后把结尾的指针,指向新人(Nick)。

只要稍作修改,就能用链表做栈,栈是后进先出(LIFO),可以把"栈"想成一堆松饼,做好一个新松饼,就堆在之前上面,吃的时候,是从最上面开始。美味!栈就不叫"入队""出队"了,叫"入栈"(push) "出栈"(pop)。

如果节点改一下,改成 2 个指针,就能做 树(tree)。很多算法用了 "树" 这种数据结构。同样,程序员很少看指针的具体值,而是把"树"抽象成这样:最高的节点叫"根节点"(root),"根节点"下的所有节点   都叫"子节点"(children)。任何子节点的直属上层节点,叫"母节点"(parent node)。

这个例子能说明 托马斯·杰斐逊 是 阿龙·伯尔 的父亲吗?我让你们的同人文来决定,没有任何"子节点"的节点,也就是"树"结束的地方,叫"叶节点"(leaf)。在这里的例子中,节点最多只可以有 2 个子节点,因此叫 二叉树(binary tree)。但你可以随便改,弄成 3个,4个,或更多,甚至节点可以用链表存所有子节点。

"树"的一个重要性质是(不管现实中还是数据结构中),"根"到"叶"是 单向 的,如果根连到叶,叶连到根就很奇怪。

如果数据随意连接,包括循环,可以用"图"表示,还记得上集用路连接城市的"图"吗?这种结构 可以用有多个指针的节点表示,因此没有,根,叶,子节点和父节点这些概念。可以随意指向。

以上概述了计算机科学中,最主要的一些数据结构这些基本结构之上,程序员做了各种新变体,有不同性质。比如"红黑树"和"堆",我们就不讲了,有兴趣可以搜索。

不同数据结构适用于不同场景,选择正确数据结构会让工作更简单,所以花时间考虑用什么数据结构是值得的。幸运的是,大多数编程语言自带了预先做好的数据结构,比如,C++有"标准模板库",Java有"Java 类库"。程序员不用浪费时间从零写,时间可以花在更有趣的事情。

下一节我们讲计算机理论贡献巨大的人。大家可以留言猜猜这个人是谁?

相关阅读:

  1. 算法入门

  2. 计算机科学家的核心

数据存在内存里的格式是什么?相关推荐

  1. linkedin databus介绍——监听数据库变化,有新数据到来时通知其他消费者app,新数据存在内存里,多份快照...

    概要结构如下图. 图中显示:Search Index和Read Replicas等系统是Databus的消费者.当主OLTP数据库发生写操作时,连接其上的中继系统会将数据拉到中继中.签入在Search ...

  2. php导出excel数据使用csv替代xls格式

    为什么80%的码农都做不了架构师?>>>    php导出excel数据使用csv替代xls格式 一直以来需要将某些后台数据导出来以供运营人员查看,因为他们都用excel.所以最初的 ...

  3. 梦开始的地方 —— C语言数据在内存中的存储(整形+浮点型)

    文章目录 整形在内存中的存储 1. 数值类型的基本分类 2. 整形在内存中的存储 1. 原码.反码.补码 2. 内存中为什么要存放补码? 3. 大小端存储 4. 无符号有符号数练习 5. 有符号数无符 ...

  4. C语言—深度剖析数据在内存中的存储

    深度剖析数据在内存中的存储 数据类型介绍 类型的基本归类 整形在内存中的存储 大小端介绍 整形在内存中的存储的相关练习 浮点型在内存中的存储 浮点型在内存中的存储相关介绍 数据类型介绍 内置类型(C语 ...

  5. python截图直接在内存里调用_python 使用win32api截图全解释

    1.获得应用窗口句柄 hwnd=win32gui.FindWindow(0,"窗口名字") 2.通过应用窗口句柄获得窗口DC hwndDC=win32gui.GetWindowDC ...

  6. Open Street Map 全球城市路网数据下载并转为SHP格式(包含历史道路数据的下载方法)

    一.背景 Open street Map 是一个很好的开源数据获取源,本人正在做关于芝加哥的研究需要用到路网数据,因此需要从Open street Map 下载数据. 二.数据下载方法 1.简单粗暴法 ...

  7. 【Android FFMPEG 开发】FFMPEG AVFrame 图像格式转换 YUV - RGBA ( 获取 SwsContext | 初始化图像数据存储内存 | 图像格式转换 )

    文章目录 I . FFMPEG AVFrame 图像数据帧处理 前置操作 II . FFMPEG 解码 AVPacket 数据到 AVFrame 流程 III. FFMPEG 解码前后的图像格式 IV ...

  8. 汇编 --- 从磁盘(扇区2到18)上读取数据到内存中

    下面代码读取柱面:0,磁头:0,扇区从2到18的数据到内存 0x8200~0xa3ff处 需要明白以下几点: 给定柱面,磁头,一个扇形区域是512字节,对应的物理可以理解为512个灯泡组(一个灯泡组有 ...

  9. 类和对象运行时在内存里是怎么样的?各种变量、方法在运行时是怎么交互的?

    转载自   类和对象运行时在内存里是怎么样的?各种变量.方法在运行时是怎么交互的? 在回答这个问题之前先了解一下Java的一些基础知识. 我们知道Java程序运行在虚拟机环境里,那我们先看一下虚拟机的 ...

最新文章

  1. Java,Hello world 欢迎进入Java世界
  2. 上交三月月赛[SJTU] 1106 sudoku
  3. (转载)为什么欧美拿金牌不感谢祖国
  4. IAR实际使用过程中遇到的问题
  5. memcache-session-manager(flexjson)
  6. 程序运行正常,数据库没反应
  7. python threading 结束线程
  8. 多生产者-多消费者问题
  9. python找钱_python 递归 找零钱
  10. 【AI视野·今日NLP 自然语言处理论文速览 第十六期】Tue, 29 Jun 2021
  11. 王春晖:发展自主知识产权的网安核心技术迫在眉睫
  12. Linux僵尸进程怎么处理,Linux 僵尸进程如何处理
  13. 双硬盘分别装windows和linux,双硬盘分别安装windows和Ubuntu20双系统
  14. 马哥教育——第十四周作业
  15. QQ机器人 微信机器人最新可用框架汇总
  16. 【注意】这款Python快递查询小系统超级好用:不信你自己试试?
  17. 计算机设计大赛赛事总结怎么写,北京科技大学计算机与通信工程学院-2018年计算机设计大赛总结会暨姚琳副教授学术报告...
  18. 20145204 张亚军《信息安全系统设计基础》第九周学习总结
  19. 开源复杂网络分析软件中社团发现算法总结
  20. 什么是Vanilla JavaScript?

热门文章

  1. watchdog linux 进程,watchdog
  2. 大数据学习笔记(六)HDFS-API
  3. 视频去水印免费软件有哪些?视频去水印软件大分享
  4. 怎么用计算机改变声音的音调,男声变女声用什么软件?能电脑语音说话变声吗?...
  5. 《C++0x漫谈》系列之:Concept, Concept!
  6. 电工学复习【4】--三相交流电路
  7. 网盘搜索插件php源码,百度云网盘搜索引擎 PHP版 v1.0
  8. 家庭NAS服务器安装配置
  9. 昇腾Atlas200DK学习笔记(一)——环境部署
  10. vscode 实现在行尾加分号