数据结构是在计算机中排列和存储数据以便有效使用它的一种有意义的方式。
说到范围,现在也是放下期望的好时机:
数据结构提供了管理大型数据集(如数据库或互联网索引服务)的方法。
让我们来看看现实生活中的类比...
如果您在杂货店购物,您会期望相关物品位于同一区域,例如水果和蔬菜区域、肉类区域、乳制品区域等。这些项目可以根据其价格等进一步组织。
这种有意义的项目结构有助于企业高效运营。因为您(或任何人)永远不会访问(或重新访问)一家凌乱的商店,在那里需要很长时间才能找到您需要的每一件物品。😔
同样,您也不想使用慢速计算机,搜索旧照片大约需要一天的时间。这就是为什么我们有一个称为“文件系统”的高效数据结构,它将所述数据组织并存储到从根目录开始的层次结构中。
虽然文件系统是一种更高级的数据结构,但它确实试图解决任何数据结构试图解决的基本问题,即存储、组织和维护数据的有效方式。

现在,在继续之前,我们需要确保在谈论某些术语时我们在同一页面上。
需要注意的是,我们将主要讨论非原始数据结构;我的意思是你会看到的!😀
您可能听说过与数组或链表关联的数据结构。
但是是什么使数组成为数组,它与链表或树有什么不同?
野外有多少种不同的数据结构?🤨
好吧,我在这里告诉您,主要有两种类型的数据结构,即
基元数据结构(也称为内置数据类型)只能存储一种类型的数据。你知道整数,浮点数,字符,指针,诸如此类的东西。
另一方面,非原始数据结构可以存储多种类型的数据。例如,数组、链表、堆栈、队列、树、图形等。这些通常称为派生数据类型。
让我们来看看它的概貌

如您所见,非原始数据结构进一步分为线性和非线性。
线性数据结构再次根据它们是静态的还是动态的进行分类。
如果这还不够,堆栈和队列也可以互换地称为 ADT,而不是具体的数据结构!
等一下,什么!😯
让我们退后一步,首先讨论线性与非线性。

顾名思义,它的数据必须以线性顺序构建。这意味着没有层次结构,元素通过指针或连续的内存位置按顺序保存在一起。通俗地说,每个元素似乎都以线性方式相互连接。
让我们举一个场景,假设我们想存储我们购买的所有杂货的价格。因此,我们可以分配一个大小为“n”的连续内存块,其中“n”是指我们购买的物品数量。
在这里,数组可能是一个合适的数据结构,因为它只是类似数据类型(如 int、float、char 等)的集合。

由于价格可能是浮动的,我们可以将它们存储在一个数组中,如下所示:
float prices[4] = [20.4, 32.3, 4.5, 27.1];数组最酷的地方在于它通过从零开始的索引为您提供对每个元素的持续访问。 🙅🏻
为了获得第三个元素的价格,我们可以说价格[2]。
现在,如何存储我们将要购买但提前不知道数量的所有杂货的价格!
由于数组要求您提前指定大小,因此在这里这样的尝试将是徒劳的。
在前面的情况下,请注意,我们必须通过指定 n = 4 来声明大小。我的意思是,你可以争论创建一个足够大的数组,这样我们就永远不会用完空间。
例如,将数组的大小设置为商店中的项目总数或其他东西。然而,直觉表明这将非常低效。另外,请记住,数据结构的唯一目的是通过仔细组织数据来提高效率。
与其提前分配连续的内存块,不如将数据包装在一个节点中,该节点会吐出一个引用,我们可以用来指向下一个节点。
瞧,我们有一个链接节点列表与链表。唉,我们失去了索引!

我们谈论的数据结构越多,你就越会发现没有灵丹妙药,相反,一切都是权衡。
线性数据结构主要分为静态和动态两大类。
我认为,可以说,数组是静态数据结构,而链表是动态的!
非线性数据结构不是按顺序排列的,因为此类数据结构的每个元素都可以有多个路径来连接到其他元素或形成层次结构。
让我们回到文件系统的例子。可视化它给人的印象是一个颠倒的树状结构,它以父文件夹、子文件夹等的形式保留层次结构。
那么,我们如何使用数据结构构建这样的文件系统呢?
显然,通过使用树状数据结构(又名树)(双关语)。🌲

树确实是最重要的数据结构之一,其元素(即节点)之间具有层次结构关系,这些节点通过链接(又称边)连接。如果有帮助,请将树视为链表,但有两个或多个指针。
但是,与循环链表不同,树没有任何循环, ♻
因为如果我们可以像这样循环浏览我们的目录,那就没有任何意义了,
cd ./Desktop/myFolder/Desktop/...例如,首先搜索计算机中不存在的图片永远不会终止并崩溃整个系统。

例如,首先搜索计算机中不存在的图片永远不会终止并崩溃整个系统。
但在某些情况下,我们确实需要这样的循环,或者情况可能有点复杂。
在社交媒体的背景下,这样的表达方式似乎并非闻所未闻;
“我是阳光,小乔朋友的朋友,既然你也跟着小乔,我在想也许我们可以成为朋友,请接受我的请求......”
什么样的数据结构可以对这些错综复杂的关系进行建模?🔍
图形包含的节点和边很像树,但更优越和通用。它可以如此强大,以至于它在数学中有一个专门的分支,名为“图论”。😋
图形可以在树的顶部具有循环、不相交和各种灵活性。因此,重要的是要记住,一棵树属于一个特殊的图表类别。

呵呵,好多...
我希望您已经清楚地了解线性和非线性数据结构之间的主要区别。
但它并不止于此,我们可以通过实现通用对应物来混合匹配并进一步构建越来越多的利基数据结构。
例如,哈希映射可能是实现关联数组抽象数据类型的最有用(有争议的)数据结构,该结构可以将键映射到值。反过来,哈希映射通常建立在链表之上。👁
链表还可以直接实现其他抽象数据类型,例如堆栈和队列。
但是这种抽象数据类型是什么?🤨
在计算机科学中,我们经常谈论对接口的抽象和编程。
例如,您无需了解汽车工程即可将汽车开到杂货店。您只需要知道如何驾驶,因为制造商已经抽象出汽车发动机和其他内部机制的所有复杂性。对于驾驶,您确实可以获得方向盘和换档等接口,以便与汽车进行交互。
同样,每个数据结构都有一个相应的接口,称为抽象数据类型或 ADT。简单地说,抽象数据类型只寻址接口,数据结构实现该接口。
例如,队列是一个 ADT,它必须保持元素的先进先出 (FIFO) 顺序。它只是意味着,第一个进入队列的人将是第一个退出队列的人。
队列 ADT 的这种想法可能受到杂货店柜台前的真实站立队列或类似场景的启发。

另一方面,堆栈是符合元素后进先出(LIFO)顺序的ADT的另一个示例。
这个ADT的想法可能受到现实世界的一堆书的启发。📙

通过讨论数组、链表、堆栈、队列、树、图、哈希图等几种数据结构,我们已经涵盖了很多内容,并且可能暗示了它们各自的用例,但从未真正了解细节。
比如,他们是如何运作的?
好吧,事实证明几乎所有的数据结构都支持一些关键操作......我们接下来要探索的!
放下手,最有用的操作!如果你不能搜索一个元素,你怎么能做任何事情?
好吧,如果这听起来很模糊,可以这样想——你在杂货店(出于某种原因,我痴迷于杂货店),你正在把物品放入购物车。
在这里,像 50 卢比巧克力棒这样的项目将是您的数据,购物车本身就是一个数据结构。假设你后来忘记了你是否选择了巧克力棒。
你怎么能确定你是否无法搜索?🔎
现在,你可能会声称你的记忆力很敏锐(不像我),你记得把物品放在购物车里,但你怎么能把它展示给柜台呢?
如果您无法搜索它,您怎么能访问它?(周到的锻炼,试一试! 💡
遍历意味着以某种特定顺序循环访问数据结构。
在数组中,您可以在恒定时间内访问一个元素,即 O(1),前提是您事先知道它的位置!
但这并不意味着您可以在恒定的时间内搜索它。
您仍然需要从第一个索引开始并搜索它。因此,为了搜索,您需要遍历。🏃♂️
因此,我们得出结论,遍历也与搜索一样有用。
插入基本上意味着将一个或多个元素插入到数据结构中。元素可以插入到开头、结尾或任何指定位置。
在某些数据结构中,您甚至不需要指定位置,例如在堆中插入。
插入是一个基本操作,因为如果您无法在数据结构中插入任何内容,为什么还要费心呢?
购物车🛒的存在是有原因的,以帮助存储要购买的物品。为了存储它,您必须插入它。
完成购物后,我们需要从购物车中删除商品,将它们展示给柜台,然后将其放入我们的包中(另一种数据结构)。
现在,想象一下我们没有这个操作,所以我们永远无法从购物车中取出任何物品。
似乎是一个我不想生活的悲惨世界!
但是你可以争辩说,你不需要删除数组中的数字来使用它!
因为我们可以访问这样的元素:
float chocolate_bar = cart[35];
eat(chocolate_bar);好吧,你把我带到了那里!
因此,根据chocolate_bar的数据类型,有两种可能的情况:
第二种情况是实用的,但效率极低,这与数据结构的存在相矛盾。
我的意思是你可以这样做,但使用支持删除的购物车可能会更好,你可以使用其他数据结构,比如吃盘🍽子和垃圾箱🗑来处理包装纸。
这个建立在搜索和插入的基础上,例如,您突然意识到您购买了错误的巧克力棒,因此您在购物车中搜索了错误的巧克力棒并将其替换为正确的巧克力棒。
现在您可能会说,替换也可以被视为建立在删除和插入之上的操作。
但事实并非如此!
我知道这很奇怪,我的意思是左右谈论违反保护法!
但在这里,我们达到了将物理世界与二元世界类比的极限!
当我说替换时,我的意思是神奇地让旧酒吧消失并通过以下方式改变它的位置:
cart[35] = better_chocolate_bar;在这里,我们只是搜索了推车,然后发现它在位置 35 上,并用better_chololate杆代替了它。✍🏻
这是一个非常高级的数据结构操作,由于数组的恒定访问和线性排序,数组对于这种操作非常有效。
链表也可以通过操作指针进行排序,因此也可以是树。
一种称为二叉搜索树的特殊排序二叉树是最有用的数据结构之一。
我的意思是,您可以想象并可能欣赏一家杂货店根据价格从左到右将所有类似的商品分类在过道中。
所以,如果你渴望一个昂贵的巧克力棒,你确切地知道该看哪个方向!➡️
这不是一个基本的操作,事实上,它使用其他基本操作来帮助促进所述过程,例如通过操作指针将两个链表合并为一个,或将两个 BST 合并为一个。
从这个角度来看,将两个购物车中的物品放入一个较大的购物车中可能是合并的情况。🛒➕🛒= 🛒
合并也用于最著名的排序算法之一,即合并排序(多么原始)。
如果没有使用数据结构的固有好处,我以前的咆哮都没有意义。
但我必须告诉你,这些优点是通用的,并且符合每个数据结构,所以让我们检查一下:
这是一个合理的问题,因为生活中的许多事情都很重要,但并不是每个人都需要学习一切。 🤗
话虽如此,如果你渴望成为一名软件工程师、机器学习工程师、数据科学家或攻读计算机科学博士学位,你需要了解你的数据结构(以及处理这些数据结构的算法)。
了解数据结构的必要性也可能是一个自我实现的预言,尽管出于错误的原因,但每一点都在发生。
让我解析一下,以便于上下文理解 —
无论你选择哪个镜头都取决于你,但它并不能消除这样一个事实,即数据结构确实是最重要的主题之一,在软件和计算机科学(以及技术面试)中具有重大影响。