ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数据结构入门:逻辑结构、存储结构与数据运算全解析

数据结构入门:逻辑结构、存储结构与数据运算全解析 学数据结构的人十有八九都翻过严蔚敏老师的《数据结构C语言版》。但很多人打开第一章看到“数据”“数据元素”“数据对象”“逻辑结构”“存储结构”这一串术语第一反应是“这有什么好学的”然后直接翻到后面看链表、栈、队列。结果学到后面越学越迷糊连“结构体数组和链表有什么区别”这种基础问题都说不清楚。这篇笔记想把第一章1.1“什么是数据结构”和1.2“基本概念和术语”掰开揉碎讲一遍配合我重新梳理的2.4章节笔记体系帮你把地基打牢。换个说法这一章你如果真吃透了后面学线性表、树、图都是在同一个框架里填细节。这篇内容不是教材原文的复读机而是结合了实际刷题、考研复习和经验总结之后的解读。不管你是在校本科生、准备考研的选手还是自学转码的在职党只要你的目标是把数据结构与算法真正学到能用的程度这篇笔记都能给你省下不少自己琢磨的时间。1. 为什么每个学数据结构的人都该认真对待1.1和1.21.1 “数据结构”到底在研究什么如果只让我用一句话回答“数据结构是什么”我会说它研究的是数据在计算机中如何组织、如何存储、以及围绕这些数据能做什么运算。听起来很抽象但拆开看就三个问题数据之间是什么关系、数据在内存里怎么摆放、用户对数据能做哪些操作。这一章之所以放在全书开头是因为整个学科的所有内容都建立在“数据和数据之间的关系”这个基座上。严蔚敏教材里写得很含蓄但核心观点就是——编写程序解决实际问题时第一步不是写代码而是先想清楚数据怎么组织。就像搬家具进新房子你要先想清楚沙发放哪、书架放哪、床怎么摆而不是直接往屋里堆。代码写得再漂亮数据组织得一团糟程序一样卡成PPT。Niklaus Wirth有句名言算法 数据结构 程序。这句被引用到烂的话其实是很多程序员工作多年后回头才真正理解的。算法描述“怎么做”数据结构描述“数据怎么放”两者缺一不可。而1.1这一节就是告诉你“数据结构为什么有资格和算法并列”。1.2 学完1.1和1.2你应该带走什么我见过不少同学第一章看完一遍感觉“我都会了”但合上书一问他逻辑结构和存储结构到底什么关系他又说不清楚。所以这一章学完你脑子里应该留下三样东西。第一对“数据结构”这个术语有精确理解。数据元素之间不是孤立的它们存在某种关系这种关系加上数据元素本身才是数据结构。第二能把“逻辑结构”“存储结构”“运算”三者严格区分开。逻辑结构是抽象的、与计算机无关的存储结构是具体的、依赖内存实现的运算是定义在逻辑结构上、但必须在存储结构上落地的。这个区分是全书的骨架后面每一种数据结构都要从这三方面去认识。第三熟悉这套术语体系。数据、数据元素、数据项、数据对象、结点、域、逻辑结构、存储结构……这些名词以后会在整本书、考研题、面试题里反复出现。你现在花一小时把它们搞清楚后面能省十小时。2. 基本概念和术语逐条拆解别让名词卡住你2.1 数据、数据元素、数据项从“人类视角”到“计算机视角”先看最底层的一组概念数据、数据元素、数据项。数据是能输入到计算机中并被程序处理的符号总称。换句话说数字、字母、汉字、图像、音频只要能被计算机识别和处理都能归到“数据”这个大筐里。这个定义的重点在于“能被计算机处理”这七个字不是所有信息都是数据得先数字化才行。数据元素是数据的基本单位在程序中通常作为一个整体来考虑和处理。比如一个学生信息表里“张三”这条记录就是一个数据元素一张成绩单里“数学成绩98分”这个单元格也可以是一个数据元素。在某些场景下一个数据元素由若干数据项组成。数据项又分两种初等项和组合项。初等项是不可再分割的最小单位比如学号、姓名组合项是可以再拆的比如“出生日期”还能拆成年、月、日。有同学会问数据元素和数据项哪个更接近编程里的概念可以这么对应数据元素通常对应结构体变量或者对象数据项对应结构体里的成员变量。比如定义了一个struct Student里面int id、char name[20]那么一个student变量就是数据元素id和name就是数据项。我在讲2.4线性表的时候也会反复用到这种“结点数据域指针域”的说法。2.2 数据对象带条件的集合数据对象这个概念教材里的定义是性质相同的数据元素的集合是数据的一个子集。注意“性质相同”这个词是核心。比如所有整数放在一起构成整数数据对象所有学生记录放在一起构成学生数据对象。它和“数据元素”不是一个层级的概念数据元素是个体数据对象是群体而且是按性质归类的群体。初学者最容易在这里犯迷糊数据对象和数据结构有什么区别一个简单的理解方式数据对象回答的是“有哪些数据”数据结构回答的是“这些数据之间是什么关系”。比如“全班同学的学号”是一个数据对象但“学号按从小到大排成一列”才谈得上结构。数据对象是原料数据结构是原料的摆法。我在整理笔记时习惯把“数据对象”类比成“货仓里的全部货物”“数据结构”类比成“货架上货物的摆放规则”。货仓里有100箱饮料这是数据对象饮料按生产日期从左到右、从早到晚排列这是数据结构。两者一起才构成一个完整的存储场景。2.3 数据结构一种结构三重理解教材对“数据结构”给出了一个包含逻辑结构、存储结构和数据运算三方面的定义。这也是我认为全书最重要的一句话建议直接背下来数据结构包括数据的逻辑结构、数据的存储结构和数据的运算。三者缺一不可。这里有个细节值得琢磨为什么“运算”也被归到数据结构的定义里因为脱离运算谈数据结构没有意义。比如你定义了一个线性表如果不提供插入、删除、查找这些操作那它只是一堆数据的排列不构成一个可用的抽象数据类型。反过来同样一种逻辑结构线性表可以有不同的存储结构顺序表或链表由此会带来运算实现方式和性能上的巨大差异。这一点在学到2.4节顺序表和链表对比时体会特别深。所以每学一种新的数据结构你都应该问自己三个问题它的逻辑结构是什么样的它用什么存储结构实现它支持哪些运算把这三个问题回答清楚这种数据结构你就掌握了七成。3. 逻辑结构、存储结构与运算理解数据结构的三把钥匙3.1 逻辑结构站在使用者的角度抽象看数据逻辑结构描述的是数据元素之间的逻辑关系与计算机的具体实现无关。你可以把它理解成“用户心中的数据组织方式”。教材把逻辑结构分成四种集合结构、线性结构、树形结构和图状结构。集合结构最自然数据元素之间“同属于一个集合”除此之外没有别的关系。线性结构是一对一的关系每个元素最多有一个直接前驱和一个直接后继典型的比如排队、字符串、数组。树形结构是一对多的关系一个结点可以有多个孩子但只有一个父亲典型的比如文件目录、公司组织架构。图状结构是多对多的关系任意两个结点之间都可能有关联典型的比如地铁线路图、社交网络好友关系。这四种结构从“关系约束强度”来看是递减的集合最松图最自由。这也是为什么后面安排学习顺序时先学线性表线性结构再学树再学图——关系越自由算法越复杂。教材在1.1里有句话很有启发逻辑结构是数据结构的抽象存储结构是数据结构的实现。先把抽象层面搞懂实现层面才能有的放矢。3.2 存储结构站在实现者的角度具体存数据存储结构解决的是“数据元素和逻辑关系在计算机内存里怎么表示”。同一个逻辑结构现实中有多种存储方案。教材重点讲了四种顺序存储、链式存储、索引存储和散列存储。顺序存储把逻辑上相邻的元素放到物理位置也相邻的存储单元里靠“物理相邻”来表达逻辑关系。优势是随机访问快按下标就能O(1)取到元素劣势是插入和删除需要移动大量元素。链式存储则不要求物理相邻每个结点额外用一个指针域存下一个结点的地址靠“指针指向”来表达逻辑关系。优势是插入删除效率高劣势是需要额外空间存指针而且无法快速随机访问。索引存储是在存储数据的同时额外建立一张索引表每个索引项指向一个数据元素这个在数据库场景里非常常见。散列存储则根据元素的关键字直接计算出存储地址也就是哈希表那一套。很多人在这一节会困惑既然顺序存储和链式存储差别这么大到底选哪个答案是看运算模式。查得多、改得少就用顺序存储增删多、且规模不定就用链式存储。2.4节里线性表的顺序表示和链式表示就是这两种存储结构最经典的对比案例。3.3 数据运算定义在逻辑结构上落实在存储结构上数据运算包括两大方面运算的定义和运算的实现。运算的定义是针对逻辑结构的指明运算的功能比如“在线性表中查找第i个元素”“在树中插入一个结点”运算的实现则是针对存储结构的要写出具体算法步骤比如顺序表里怎么移动元素、链表里怎么改指针。这个区分特别重要因为同一个逻辑运算在不同存储结构上的实现方式截然不同效率也不同。比如“删除第i个元素”顺序表需要把从i1到n的元素全部前移一位链表只需要改两个指针。反过来“取第i个元素”顺序表O(1)搞定链表需要从头结点开始往后走i次。这就是为什么考研题和面试题里经常出现“在顺序表和链表中分别完成某操作的时间复杂度是多少”这类题目。我自己的体会是理解“定义”和“实现”分离是数据结构学习中的一个分水岭。过不了这个坎的人总想着“一个操作该咋写”而过了这个坎的人会先想“我这个操作是基于什么逻辑结构、什么存储结构”然后才动手写代码。角度不同学习的效率差出好几倍。4. 这些术语不是孤立的它们如何撑起后面的2.4线性表4.1 用第一章的框架解构链表我这份笔记标题里带了“2.4”很多同学问是不是写错了。其实2.4是严蔚敏教材里“线性表的链式表示和实现”这一节。我想特别说明1.1和1.2的术语就是为2.4这类章节服务的。举个例子单链表这种结构用第一章的框架来拆解会特别清晰。逻辑结构方面单链表是线性结构结点与结点之间是“一对一”关系存储结构方面它是链式存储每个结点包含数据域和指针域运算方面它支持初始化、插入、删除、查找、遍历等基本操作。你看一个看似复杂的链表只要从这三个维度去理解马上就立体了。再拿“数据元素”和“结点”这两个术语来说。在链表场景里数据元素对应结点的数据域逻辑关系通过结点的指针域表达。很多初学者写链表代码时总搞不清楚“p-next到底指向什么”本质上是没理解“结点之间通过指针表达逻辑关系”这句话。如果你把1.2的存储结构概念吃透了链表指针操作根本不是问题。4.2 考研与面试里这些概念的常见考法过来人都知道408统考里数据结构选择第一题常常就是概念辨析题。比如给你四种说法问哪个是“数据的逻辑结构”或者问“以下哪种存储结构可以实现随机存取”。这些题目并不难但每年都有人丢分就是因为基础术语不扎实。常见考法大概有这么几类。第一类是概念归类题给你“学生学号”“文件目录”“地铁线路图”让你判断分别是哪种逻辑结构。第二类是存储结构判断题问“链式存储中结点间的逻辑关系是通过什么表达的”。第三类是运算与结构匹配题问“在顺序表中插入一个元素平均要移动多少个元素”这种就结合了运算实现和时间复杂度的知识。如果你在准备考研我建议把1.1、1.2的概念做成一张思维导图然后每学完一种新结构就往这张图里挂新分支。数据结构这门课越学到后面越依赖“框架感”而框架的根就在第一章这些看似不起眼的术语里。5. 新手最容易踩的坑与我的学习建议5.1 概念辨析速查表为了让这篇笔记有“速查”价值我把最容易混淆的概念整理成了一个表格你可以把它截图存下来或者打印贴在书桌前。易混概念核心区别一句话例子数据 vs 数据元素数据是集合数据元素是集合中的个体全班学生信息是数据单个学生记录是数据元素数据元素 vs 数据项数据元素是整体数据项是组成部分学生记录是数据元素学号/姓名是数据项数据对象 vs 数据结构对象是数据的集合结构是数据之间的关系所有学生记录是对象按学号排序是结构逻辑结构 vs 存储结构逻辑结构是抽象关系存储结构是物理实现线性关系是逻辑结构用数组还是链表存是存储结构顺序存储 vs 链式存储物理相邻表达逻辑关系 vs 指针表达逻辑关系数组 vs 单链表运算定义 vs 运算实现定义说明“做什么”实现说明“怎么做”“查找第i个元素”是定义遍历链表返回第i个是实现这张表我建议配合教材反复看每次看都试着在脑子里举一个新的例子。到你能自己随口举出例子而不卡壳基本概念这一关就过了。5.2 我的几点学习心得最后分享几条学了这么多年、踩了不少坑之后总结出的经验。第一不要跳过第一章去赶进度。数据结构所有的内容大到平衡二叉树、图的最短路径小到循环队列判空判满都离不开“逻辑结构、存储结构、运算”这个三位一体的框架。框架没搭起来学到后面一定散架。第二概念要“用例子学”不要“用定义背”。我见过太多人背住了“数据元素是数据的基本单位”但问他一个数组元素算不算数据元素他又犹豫。实际上数组元素是不是数据元素取决于你把它放在哪个层面讨论。学概念要带着场景比如学生管理系统、图书管理系统、订单系统都是最好的概念练习题。第三尽早把“逻辑”和“实现”分开思考。写代码前先问自己我这个数据的逻辑结构是什么用什么存储结构实现这样训练一两个月你在算法题上的分析能力会明显提升。王道数据结构里那些常考题型说到底都是在这两个概念之间做文章。第四把笔记做成“问题清单”而不是“抄书清单”。每学一节列出几个自己能回答的问题比如“为什么顺序表插入要移动元素”“单链表有没有长度属性”等。带着问题去写代码、去画图比单纯划线看书管用得多。数据结构的学习是一个先难后易的过程而1.1和1.2就是那个最陡的上坡路。把这一章啃下来后面的路会越走越顺。这套基本概念和术语往后不管是写C语言代码、刷Python算法题还是准备软考、408考研都会反复用到。如果你正卡在第一章别急把这些术语先理清再往后翻书你会发现自己突然“开窍”了。
返回列表