算法第四版读书笔记 - 背包、栈、队列

背包、栈和队列

前几天总算看完了大概一半的算法第四版。现在为了回顾一下知识,继续写完这个读书笔记的坑。

  • 背包
    背包是一种不支持从中删除元素的集合数据类型,他的用处就是帮助用例收集元素并迭代遍历所有收集到的元素。迭代的顺序不确定且与用例无关。
    背包的作用正如他的名字一样。但是取出的时候,相当于不看背包直接用手从里面抹黑取东西。背包的顺序是不固定的,所以背包的作用也就比较小,就我目前所学的知识来看,背包只能用作普通的数学统计计算,并且这种统计计算用其他的数据类型同样可以完成。根据我读算法第四版的经验来看,书中总是把用处较少的数据类型,结构和算法放在前面,在最后才把用处最多,使用最普遍的拿出来,给你惊艳的感觉。
    总结:背包的用处和真正的背包差不多,特点是无序,不可删除元素,但是相比之下,其他的数据类型,比如队列,就给人一种旅行包的便捷感。背包不能说无用,但是用处太少。以至于没有什么人用他。

  • 相比于前面的背包,栈可就是一种耳熟能详的数据结构。栈(也称下压栈),是一种基于后进先出(也叫先进后出,一回事)策略的集合类型,我们一般用桶来形容一个栈。在Java内存模型中,栈是一个很重要的组成部分。关于栈,算法第四版中从最初的只有几个方法,到一步步的完善整个栈数据集合。作为一个栈中的主要的方法有以下几个:1,添加一个新元素 push()。2,弹出最顶端元素(删除一个元素) pop()。3,检查栈是否为空 isEmpty()。4,栈中的元素数量 size()。而在Java中的Stack早已不是一个正常的Stack,jdk中Stack继承了Vector,而Vector又继承了AbstractList。导致Stack中的方法超级多,早已失去了他原本的样子和用处。当然,现在编程中也很少用到Stack了,只有在JVM中有很多他的影子。而我们现在只需要知道栈是一种先进后出的集合就已经足够了。
    总结:先进后出(桶)

扩展
以下内容是我在朋友给我的jvm虚拟机详解中摘抄下来的。如果找到作者请私信或评论告知。侵删。

Java虚拟机的栈有三个区域:局部变量区、运行环境区、操作数区。
局部变量区
每个Java方法使用一个固定大小的局部变量集。它们按照与vars寄存器的字偏移量来寻址。局部变量都是32位的。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址。(例如,一个具有索引n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的。虚拟机提供了把局部变量中的值装载到操作数栈的指令,也提供了把操作数栈中的值写入局部变量的指令。
运行环境区
在运行环境中包含的信息用于动态链接,正常的方法返回以及异常捕捉。
动态链接
运行环境包括对指向当前类和当前方法的解释器符号表的指针,用于支持方法代码的动态链接。方法的class文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接把符号形式的方法调用翻译成实际方法调用,装载必要的类以解释还没有定义的符号,并把变量访问翻译成与这些变量运行时的存储结构相应的偏移地址。动态链接方法和变量使得方法中使用的其它类的变化不会影响到本程序的代码。
正常的方法返回
如果当前方法正常地结束了,在执行了一条具有正确类型的返回指令时,调用的方法会得到一个返回值。执行环境在正常返回的情况下用于恢复调用者的寄存器,并把调用者的程序计数器增加一个恰当的数值,以跳过已执行过的方法调用指令,然后在调用者的执行环境中继续执行下去。
异常捕捉
异常情况在Java中被称作Error(错误)或Exception(异常),是Throwable类的子类,在程序中的原因是:①动态链接错,如无法找到所需的class文件。②运行时错,如对一个空指针的引用。程序使用了throw语句。
当异常发生时,Java虚拟机采取如下措施:
• 检查与当前方法相联系的catch子句表。每个catch子句包含其有效指令范围,能够处理的异常类型,以及处理异常的代码块地址。
• 与异常相匹配的catch子句应该符合下面的条件:造成异常的指令在其指令范围之内,发生的异常类型是其能处理的异常类型的子类型。如果找到了匹配的catch子句,那么系统转移到指定的异常处理块处执行;如果没有找到异常处理块,重复寻找匹配的catch子句的过程,直到当前方法的所有嵌套的 catch子句都被检查过。
• 由于虚拟机从第一个匹配的catch子句处继续执行,所以catch子句表中的顺序是很重要的。因为Java代码是结构化的,因此总可以把某个方法的所有的异常处理器都按序排列到一个表中,对任意可能的程序计数器的值,都可以用线性的顺序找到合适的异常处理块,以处理在该程序计数器值下发生的异常情况。
• 如果找不到匹配的catch子句,那么当前方法得到一个”未截获异常”的结果并返回到当前方法的调用者,好像异常刚刚在其调用者中发生一样。如果在调用者中仍然没有找到相应的异常处理块,那么这种错误将被传播下去。如果错误被传播到最顶层,那么系统将调用一个缺省的异常处理块。
操作数区
机器指令只从操作数栈中取操作数,对它们进行操作,并把结果返回到栈中。选择栈结构的原因是:在只有少量寄存器或非通用寄存器的机器(如 Intel486)上,也能够高效地模拟虚拟机的行为。操作数栈是32位的。它用于给方法传递参数,并从方法接收结果,也用于支持操作的参数,并保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数栈顶的两个字。这两个字是由先前的指令压进堆栈的。这两个整数将从堆栈弹出、相加,并把结果压回到操作数栈中。
每个原始数据类型都有专门的指令对它们进行必须的操作。每个操作数在栈中需要一个存储位置,除了long和double型,它们需要两个位置。操作数只能被适用于其类型的操作符所操作。例如,压入两个int类型的数,如果把它们当作是一个long类型的数则是非法的。在Sun的虚拟机实现中,这个限制由字节码验证器强制实行。但是,有少数操作(操作符dupe和swap),用于对运行时数据区进行操作时是不考虑类型的。
本地方法栈,当一个线程调用本地方法时,它就不再受到虚拟机关于结构和安全限制方面的约束,它既可以访问虚拟机的运行期数据区,也可以使用本地处理器以及任何类型的栈。例如,本地栈是一个C语言的栈,那么当C程序调用C函数时,函数的参数以某种顺序被压入栈,结果则返回给调用函数。在实现Java虚拟机时,本地方法接口使用的是C语言的模型栈,那么它的本地方法栈的调度与使用则完全与C语言的栈相同。

然而,数据结构中的栈和内存中的栈其实并不是一个东西,请区别对待。


  • 队列
    队列是一种基于先进先出策略的集合类型。而其特点就是先进先出,也是学习队列过程中唯一需要记住的东西。任何服务型策略的基本原则都是公平,而计算机中的公平的普通想法是优先服务等待最久的人,也就是队列的先进先出。队列中的主要方法有以下几个:1,添加一个新元素 enQueue() 也有叫add()的。2,删除最早添加的元素 deQueue() 同delete()或者del()。3,检查队列是否为空 isEmpty()。4,队列中的元素数量 size()。

数组和链表

  • 数组
    数组是用于储存多个相同类型数据的数据结构。因为每个人都经常使用数组,关于数组就不再过多的记录了。

  • 链表
    链表是一种递归的数据存储结构,他或者为空,或者是指向一个结点的引用,该结点含有一个泛型的元素和一个指向另一条链表的引用。

太多的语言解释太枯燥了,简单点说,数组在Java中的实现就是ArrayList,而链表在Java中的实现是LinkedList。LinkedList是一个双向链表,也就是可以查找当前元素的前一个元素和后一个元素。ArrayList和数组的区别主要就是使用ArrayList时,在空间不够的情况下ArrayList可以自动增长,增长为原来长度的1.5倍,Vector增长为原来长度的两倍。而数组和链表的主要区别,也就是ArrayList和LinkedList的主要区别就是,基于数组的ArrayList查快改慢,而链表则是查慢改快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值