数据结构总结

本文总结了常用数据结构,如线性表、栈、队列、二叉查找树、散列、堆和图,以通俗易懂的方式阐述,并提及参考书籍。作者强调理解数据结构的重要性,而非仅限于实现。
摘要由CSDN通过智能技术生成

 前言

      学习数据结构也有一段时间了,今天就想总结一下我们平常常用到的一些数据结构,包括表、栈、队列、树、散列、堆、图等。关于算法,本篇博客介绍的很少,尽量的以通俗易懂的方式来让大家理解数据结构吧,因为我本人在最初学习代码的时候是很受其困扰的,相信和我一样的人不在少数吧。关于算法的博客,后续应该会在专栏里陆续更新吧,谁知道呢。

        参考书籍:《算法图解》

《数据结构与算法分析》

《大话数据结构》程杰

1.表、栈和队列

什么是表?

        可以很简单地理解成相同数据类型的n个数据元素的有限序列。比如:小朋友有序排队出教室(线性表)

        又或者,家长散乱地在外面等(散列表)

                                        ​ 

        他们个体并不相同,但又存在一定联系,可以使用该联系将他们串联起来,这就是表。我们初学编程时学到的数组,便是一种表,有头有尾,各自排序。当然,表也包括了很多类型,例如:线性表(链表),散列表,队列、栈等,他们都是表的一种特殊情况,而他们各自又可以根据情况不同,而使用不同的类型,比如说链表在不同的情况下可使用链表、双链表,循环链表

因为链表与数组类似,所以我们不做详细的介绍,这里我们的重点是介绍一下栈和队列。  

什么是栈?      

        栈的由来应该可以涉及到寄存器的内容,这里不做详述,感兴趣的朋友可以自己去搜一下。

       栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈的顶(top)。对栈的基本操作有Push(进栈)和Pop(出栈),前者相当于插入,后者则是删除最后插入的元素。最后插入的元素可以通过使用Top例程在执行Pop之前进行考查。对空栈进行的Pop或Top一般被认为是栈ADT的错误。另一方面,当运行Push时空间用尽是一个实现错误。我知道这段话可能有点难以理解,那我们用图来说明吧。

        它的特殊之处就在于限制了这个线性表的插入和删除位置′它始终只在栈顶进行。 这也就使得:栈底是固定的,最先进栈的只能在栈底。所以栈也叫后进先出表。
什么是队列?

        你们在用电脑时有没有经历过,机器有时会处于疑似死机的状态,鼠标点什么似乎都没用,双击任何快捷方式都不动弹。就当你失去耐心打算reset时,突然它像酒醒了一样,把你刚才单击的所有操作全部都按顺序执行了一遍,这是因为操作系统在当时可能CPU一时忙不过来,等前面的事忙完后,后面多个指令需要通过一个通道输出,按先后次序排队执行造成的结果。队列类似于栈,你不能随机地访问队列中的元素。队列只支持两种操作:入队出队。下面是一个示意图:

        关于栈和队列的区别,我觉得可以用这张图表示,很容易理解:

        同样地,队列也可以使用数组的方式来实现,这里不做具体实现方式的介绍了。队列除了线性队列以外,还有循环队列等方式。        

2.树

什么是树?

树的一种实现

        对于树,我们介绍一个常见的形式,二叉查找树。二叉查找树类似于下面这样。

        对于其中的每个节点,左子节点的值都比它小 ,而右子节点的值都比它

        假设你要查找Maggie 。为此,你首先检查根节点。

        Maggie排在 David 的后面,因此你往右边找。

        Maggie排在 Manning 前面,因此你往左边找。

        终于找到了Maggie !这几乎与二分查找一样!在二叉查找树中查找节点时,平均运行时间为
O (log n ) ,但在最糟的情况下所需时间为 O ( n ) ;而在有序数组中查找时,即便是在最糟情况下所
需的时间也只有 O (log n ) ,因此你可能认为有序数组比二叉查找树更佳。然而,二叉查找树的插
入和删除操作的速度要快得多。

        二叉查找树也存在一些缺点,例如,不能随机访问,就像不能这么说:“给我第五个元素。”
在二叉查找树处于平衡状态时,平均访问时间也为 O (log n ) 。假设二叉查找树像下面这样处于不
平衡状态。

3.散列

散列是什么?

        关于散列,与我们所理解的映射、或者函数十分相似。就像是在数组上做了一个映射,散列函数是这样的函数,即无论你给它什么数据,它都还你一个数字。

        如果用专业术语来表达的话,我们会说,散列函数“将输入映射到数字”。你可能认为散列函数输出的数字没什么规律,但其实散列函数必须满足一些要求。
        ①它必须是一致的。例如,假设你输入apple 时得到的是 4 ,那么每次输入 apple 时,得到的都
必须为 4 。如果不是这样,散列表将毫无用处。
        ②它应将不同的输入映射到不同的数字。例如,如果一个散列函数不管输入是什么都返回1
它就不是好的散列函数。最理想的情况是,将不同的输入映射到不同的数字。
散列的实例
        这里我们给出一个散列表,用以理解上文所提到的“在数组上做了一个映射”

        在这里,数值[0]所对应的便是milk,数值[3]所对应的便是apple,当我们查找apple时,它便会立马定位到数值[3],而不是通过遍历的方式从数值[0]一直往后遍历,因此它的时间复杂度仅为O(1)。当然,这里只做简单地介绍,散列表的实际应用情况可能比上面的要复杂,并且有时可能发生冲突,那就由到时候再深入学习吧。

4.堆(优先队列)

这里有一些相关知识,讲的很好【【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆】https://www.bilibili.com/video/BV1AF411G7cA?vd_source=14baf41e0673d9a1ce16edd12323c3b6

堆是什么?

        程序执行的优先级并不总是相同,重要的程序总该在计算机里优先运行,因此,便衍生出堆这一概念。

        优先队列是允许至少下列两种操作的数据结构:Insert(插入),它的工作是显而易见的,以及DeleteMin(删除最小者),它的工作是找出、返回和删除优先队列中最小的元素。Insert操作等价于Enqueue(入队),而DeleteMin则是队列中Dequeue(出队)在优先队列中的等价操作。DeleteMin函数也变更它的输入。堆可以分为大根堆和小根堆。

堆的实现方式

        有几种明显的方法实现优先队列。我们可以使用一个简单链表在表头以O(1)执行插入操作,并遍历该链表以删除最小元,这又需要O(N)时间。另一种方法是,始终让表保持排序状态;这使得插入代价高昂(O(N))而DeleteMin花费低廉(O(1))。基于DeleteMin的操作次数从不多于删除操作次数的事实,因此前者恐怕是更好的想法。
        再一种实现优先队列的方法是使用二叉查找树,它对这两种操作的平均运行时间都是O(log N)。尽管插入是随机的,而删除则不是,但这个结论还是成立的。记住我们删除的惟一元素是最小元。反复除去左子树中的节点似乎损害树的平衡,使得右子树加重。然而,右子树是随机的。在最坏的情形,即DeleteMin将左子树删空的情形下,右子树拥有的元素最多也就是它应具有的两倍。这只是在其期望的深度上加了一个小常数。注意,通过使用平衡树,可以把界变成最坏情形的界,这将防止出现坏的插入序列。

        注意:堆必须是完全二叉树。


堆的一种实现方式——二叉堆

        我们将要使用的这种工具叫做二叉堆(binary heap),它的使用对于优先队列的实现是如此的普遍,以至于当堆(heap)这个词不加修饰地使用时一般都是指该数据结构的这种实现。在本小节,我们把二叉堆只叫做堆。同二叉查找树一样,堆也有两个性质,即结构性和堆序性。

建堆的方法

①自顶向下法:将新元素放到堆的最后一位,然后对他进行上浮操作。

②自下而上法:先把数组变成一个堆,再对父节点进行下沉操作。

5.图

图是什么?

        图(Graph)是由顶点的有穷非空集台和顶点之间边的集台组成的,通常表示为G(V,E) ,图中, G表示—个图,V 是图G中顶点的集台,E 是图G中边的集合。
        不好理解是吧?那我们来看看简单的。假设你居住在旧金山,要从双子峰前往金门大桥。你想乘公交车前往,并希望换乘最少。可乘坐的公交车如下。

        为找出换乘最少的乘车路线,你将使用什么样的算法?
        一步就能到达金门大桥吗?下面突出了所有一步就能到达的地方。

        金门大桥未突出,因此一步无法到达那里。两步能吗?

        金门大桥也未突出,因此两步也到不了。三步呢?

        金门大桥突出了!因此从双子峰出发,可沿下面的路线三步到达金门大桥。、

        这上面车站这种两两之间的关系就是图。看到了吧,有边、节点、甚至边还有方向。
         至此,关于数据结构的简要介绍就完毕了。此篇文章只是帮助大家理解各个数据结构,而不涉及到具体的实现,因为我一直认为理解一个抽象的东西有时候比实现它更重要。有机会再更新深入的吧(主要是我也不懂)。
  • 34
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值