时间:2009-11-20 16:30
地点:JE群9770785 extjs群88403922 sm.net群75462710
三 基本数据结构
集合
上回我们讲了基本的数据类型和数组这个基本结构,今天开始我们讲常用的数据结构。
常用的简单数据结构有stack queue list等。
这三个数据结构都是最简单的线性结构,跟Array一样,用来保存一组一维的数据。
我们知道数组需要在初始化时就指定固定大小。并且一般都难以动态调整和扩展。而实际使用的数据,一般很可能随时间的流逝而不断的变化。向现有数据添加一个数据项,或是移除一个数据项,某个数据项被修改。
数组本身不太支持动态的扩展(直接修改是支持的),在我们不确定数据量的时候,使用数组一般都是不方便的。比如常见的一般c/c++语言基础教程,经常见到char[255]之类的东西。
对于固定的一个数组,当它已经满负荷的时候,再也装不下一个数据项了。我们需要扩张它的容量。一般是再new一个比它大一点的数组。然后把旧数组的数据复制到新数组,释放旧数组的资源。然后再将要添加的数据添加到新的数组里。
大家可以注意到,一个数组的扩容需要创建新数组,复制所有的旧数组数据,释放旧数组资源,这些如果频繁操作,系统的cpu和存储开销成本都远远比一般情况添加一个元素大的多。
这个过程还有一个值得注意的问题是,在我们往数组中插入元素时,我们都有意无意的使用了数组下标的跟踪计数。每次我们插入数据的时候,都在考虑下一个可用位置的下标号。在一个简单的for循环的数组赋值中,我们一般用的i++就是用来跟踪保存这个序号的,虽然更一般的说,出了这个for循环,i这个变量就没意义了。
特别是对一个数组,多次独立的给数组中的一部分赋值或是删除值的情况下,我们需要显示的记录元素的位置和空位置,以便操作。
从上面这些现象出发,我们把经验总结起来,常见的操作和技术封装起来,集合类就出现了
我们可以从一个简单的数组出发,创建一些新的结构,内部使用额外的变量或是指针记录位置,封装常见的插入、修改、删除数据的方法,甚至使用合理的设计技巧和策略,实在比较高效的动态扩张和压缩的方法。
比如一个简单的Stack, 我们可以用一个数组加一个表示位置的变量来实现。
ArrayList复杂一点,要考虑扩张。
Queue则可以用一个数组加两个表示位置的变量实现。
Stack
Stack的实现中,我们用一个固定大小的数组来存储数据。例如,我们用位置-1,表示栈底,用另一个变量p表示当前栈顶的元素,则,初始的时候,p =-1, 当一个新元素入栈的时候,在下个位置即p+1的地方存入这个新元素,并使p=p+1, 这样就往栈里添加了一个新元素。注意,栈的大小一般都是有限的,所以需要在插入数据前,检查p+1这个位置是不是已经超出了数组大小了。
数据的出栈就简单了,如果p==-1,说明是空栈,没有数据,否则就取出当然位置的数据,再令p=p-1(栈顶的位置下移)并返回这个数据。
这就是一个用数组实现的简单的栈。
Queue
用数组来实现Queue的原理跟上面说的栈的原理一样。
不过一般可以用两个指针来记录队列的起点和队尾。
为什么都是线性结构,栈需要记录一个位置,而队列需要两个呢?其实队列只要一个指针也可以,但是由于栈只需要移动一端,另一端是固定的,可以一直放在数组的一段不动。而队列是两头都要操作数据的。一头添加数据,另一头移除数据,如果也用数组0位置作为队列的一端,那么这个地方在插入或是移除数据时,就需要调整整个数据的所有数据位置。
多用一个记录位置的变量,就不需要调整数据了,大大提高了执行效率。同时,我们可以把数组的0位置和终点位置看做连续的,这样我们无论怎样都不用调整任何元素的位置,队列无论都操作了多少次,两个位置变动了多少次,在这两个位置上操作添加和移除数据的操作,还是正确的。
ArrayList
用数组实现的简单的list,一般叫ArrayList、
表是最常用的集合之一。他表示一批数据,并提供一系列的简单操作。
ArrayList内部也是用一个数组来实现。默认一般是长度是16,跟一般的栈和队列的固定大小和在首尾操作不同的是,list提供了添加任意个元素的功能(动态增加容量),在任意位置插入或是删除元素的操作。
一样的记录当前元素位置,每一次不指定位置的插入,都直接插在当前位置,指针加1,在指定的位置插入元素,需要先把此位置以后到表尾的所有元素后移一位。然后在这个腾出来的空位插入新元素。
删除元素一样的道理,不过是此元素到表尾所有的元素都向前移动一位。
同时表尾当前元素的指针加一(插入时)或是减一(删除时)。
当插入的数据量达到目前数组的最大容量的时候,装不下更多数据了,就需要扩容了。一般的扩容策略是当前的容量乘以2,以指数形式扩张。
我们知道,每次扩张容量时,都需要将旧数据如数的复制到新数组,然后释放旧数组的资源,如果每次扩张的幅度太小了,那么频繁增加数据时,系统创建新数组和复制旧数据的开销巨大。如果每次扩张的太大,那么如果新添加的数据较少,大量新添加的存储空间被浪费掉了。
所以,选择扩大1倍是个合理的数字。如果你的数据量比较大,并且是多次一个个的插入到ArrayList中的,最好再创建ArrayList时就指定容量。 如果你的数据的变化形式比较特殊,你可以通过简单的代码就实现有自己扩容形式的ArrayList结构。
从这里我们还可以知道,ArrayList中数据的中间插入或是移除数据,需要移动其后面的所有数据,这个成本虽然比扩容的成本小,但也是比较大的。
LinkedList
数组实现的线性的基本数据结构,最常见的就是这三种。list里还有一种常见的线性表,那就是链表,LinkedList
一般来说,各语言中的集合类的实现原理基本都一样。某些具体的策略和调整参数略有不同。
链表是一种线性表,其实本质上更是一棵光棍的树。
由于他不用数组实现,所以有一些数组没有的神奇性质。
借助数组实现的数据结构,一般都依靠数组下标的位置关系来维持元素的顺序。而树一般不需要这样。树是一些节点的集合。而这些节点本身保存其跟他们节点关系的描述。
我们一般把数组实现的结构中的数据项叫元素,而把树结构中的数据项叫节点。节点是一个包含有意义的数据以及数据间关系的结构。
这些关系常见的有父子关系,兄弟关系,前驱后继等等。其实叫什么名字无所谓,本质都是从一个节点,可以获取到其他的一些确定的节点。
例如,一个简单的单链表,每一个节点都直接指向下一个节点,一直到表尾的元素,其没有下个节点。
它跟ArrayList明显不同的是,
1、不需要扩容能直接在表尾或是中间添加任意个数据项
2、插入和删除都是不需要移动任何数据的。在某两个节点间插入,只需要将前一节点的后继指向新节点,并将新节点的后继指向下一节点即可。
LinkedList在扩展和动态的增删数据上,有很好的性能。
但是,应该指出的是,它不能像数组或是ArrayList那样直接获取指定序号的元素。
获取或是操作第几个元素,我们需要先从头来搜索每一个元素并计数。
搜索的问题,我们将在hash和tree的课程中详细讲。
今天到此为止,下课,下一节讲排序。
-----------------------
谢谢同步信息的Elementstorm的辛勤劳动。
分享到:
相关推荐
**UML讲座PART2** UML(统一建模语言)是一种在软件开发过程中广泛使用的图形化表示工具,它为系统分析、设计和实现提供了一种标准化的语言。在UML讲座PART2中,我们将会深入探讨UML的核心概念、扩展功能以及在实际...
Part 1:基本算法30H讲座01-讲座02-讲座03- 讲座04- 讲座05- 讲座06-Part 2:图算法和动态编程30H讲座07-讲座08-讲座09-第10课-讲座11-第12 -讲座13- 讲座14-教科书算法导论,托马斯·科门(Thomas H.Cormen) 带注释...
An Introduction to Recursion, Part 2.mht BFS - 参考框架.txt DFS - 参考框架.txt ID - 参考框架.txt n皇后问题位运算版.mht Search in a Graph.mht STL in Searching.mht USACO搜索策略.mht 递归分治课件 - from ...
Part 2:特征提取和选择 * 特征提取的基本概念 * 特征选择的方法 * Dimentionality reduction Part 3:聚类分析 * 聚类分析的基本概念 * 聚类算法 * 聚类分析在实际应用中的应用 Part 4:分类算法 * 分类算法的...
他的讲座内容通常涵盖并行计算的基础理论、编程模型、算法设计以及实际应用等方面。 首先,我们从“PC6--具体的算法设计方法.ppt”来看,这部分可能会深入探讨如何设计并行算法。并行算法设计的关键在于如何将任务...
《互联网搜索课程part2-MSRA》是微软亚洲研究院在清华大学开设的一门深入探讨互联网搜索与挖掘技术的课程。这门课程的第二部分涵盖了多个重要讲座,旨在为学生提供全面而深入的搜索引擎技术和网络数据挖掘知识。以下...
【标题】"上海交通大学程序语言与设计PYTHON课件 PART2" 涵盖了Python编程中的核心概念,这部分课程深入探讨了Python语言的关键元素,包括函数的使用、条件语句、循环结构、类的定义以及模拟设计。这些知识点是...
在Part1-4的讲座中,squareh4l可能详细讲解了这些基本概念,并通过实例展示了如何使用STL进行高效的编程。他可能会讨论容器的性能特性、迭代器的使用方法、常见算法的应用场景以及自定义函数对象的编写。此外,他还...
赵启阳教授的讲座“具体数学(part 2)”涵盖了两个重要的渐进分析技巧:自助法(Bootstrapping)和尾部替换(Tail Substitution)。这些技巧在处理复杂的数学问题和优化算法效率时具有重要的价值。 **自助法**是一种...
这些讲座最后描述了我们将如何在本课程中分析算法的几个指导原则。 ASYMPTOTIC ANALYSIS:本周的第二组讲座是对 big-oh 符号及其亲属的介绍,它属于每个严肃的程序员和计算机科学家的词汇表。 目标是确定用于算法...
赵启阳教授的《具体数学(part 1)_赵启阳.ppt》是针对这一主题的讲座材料,主要讨论了渐进分析(Asymptotics)的概念及其在处理数学问题中的重要性。 渐进分析源自古希腊数学,它关注的是函数或序列随着变量趋于无穷...
1. "Slides-Part1.pdf"、"Slides-Part2.pdf"、"Slides-Part3.pdf":这些可能是讲座的幻灯片,可能涵盖了Linux、PHP等主题的详细讲解。 2. "Effective_Vim.ppt":Vim是一个强大的文本编辑器,这个文件可能教你如何更...
【标签】"accp-ppt5[1].0.part2"暗示了这门课程可能使用了PowerPoint演示文稿作为教学辅助工具,"part2"可能表示这是系列讲座的第二部分,意味着在前面的部分中可能已经涵盖了accp5.0的基础知识,而这一部分则可能...
至于这样做的原因,在本书第 2章有比较详细的说明。当然,开发环境毕竟是第二位的,书中讲述的内容以及涉及的代码跟第一版都是一致的。本书的下篇全部都是新鲜内容,主要是增加了进程间通信、文件系统和内存管理。跟...
【标题】"MSc-Part-1-Sem-1" 暗示这是一门针对硕士研究生阶段第一部分第一学期的课程资料,可能涵盖了某个专业领域的基础或核心课程。在这个压缩包中,我们重点关注与“Jupyter Notebook”相关的学习内容。 【描述...
这个压缩包包含了一系列的讲座幻灯片,从M1到M8,以及一个名为"clean-architecture-demo-master"的项目演示,这些内容为我们揭示了Clean Architecture的核心概念、模式、实践和原则。 Clean Architecture是一种设计...
2. Octave/MATLAB使用: 文档建议学生观看视频讲座、完成相关主题的复习问题,并使用Octave或MATLAB编程。Octave和MATLAB都是数值计算环境,广泛应用于教学和工业界。它们具有强大的矩阵处理能力和易用的脚本语言,...
至于这样做的原因,在本书第 2章有比较详细的说明。当然,开发环境毕竟是第二位的,书中讲述的内容以及涉及的代码跟第一版都是一致的。本书的下篇全部都是新鲜内容,主要是增加了进程间通信、文件系统和内存管理。跟...
在开始这个编程练习之前,我们强烈建议您观看与相关主题相关的视频讲座并完成复习问题。 为了开始这个练习,您需要下载起始代码,并将其内容解压到您希望完成练习的目录。如果需要,可以使用 Octave 中的 `cd` 命令...
2. **分析编码结果**:观察不同参数设置下编码效率的变化,理解不同算法之间的差异。 3. **参与开源项目**:加入H.264相关的开源社区,参与讨论并贡献自己的力量。 #### 阶段三:兴趣驱动的研究 当对H.264有了较为...