您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记之表、栈、队列

2013-03-17 01:42 351 查看
转载请注明出处:http://blog.csdn.net/droyon/article/details/8682633

1、抽象数据类型是带有一组操作的一些对象的集合。它是数学抽象,大体包含了操作和数据两部分。

2、表:对于任何非空表,除了第一个元素,其后的每个元素都有一个前驱,除了最后一个元素,其前的每一个元素都有一个后继。对表上的数据,可以有查找、插入、删除、打印,查找某个元素是否在数组中包含等操作。

对于表这种结构,采用不同的实现方式,对于上述操作的时间复杂度也就是运行性能会有影响。

如果采用数组实现表结构:

优点:打印、查找是否包含操作花费线性时间,查找固定位置数组内容花费常数时间。时间复杂度依次为:O(N),O(1)

缺点:插入和删除潜藏着昂贵的开销。最坏情况,在数组位置0处插入元素,那么首先需要将整个数组向后移一个元素,然后在位置0插入元素。删除位置0的元素,需要将整个数组前移一位。时间复杂度为O(N)。

对于数组这种实现方式,在许多情况下,数组大都是在数组高端通过插入操作构建,其后进行指定位置查找操作,在这种情况下数组是一个好的选择。如果对数组的插入和删除操作发生在表的前端,那么数组就那么高效。

3、表结构,链表实现:为了避免数组插入和删除的线性开销,我们可以保证表的不连续存储,否则表的每个部分都可能需要整体移动。

链表有一系列节点组成,这些节点不必在内存中相连,每一个节点都含有节点内容和到包含该元素后继节点的链。这个链成为next链,最后一个节点的链为null。

优点:插入、删除操作花费常数时间。典型的节点可以拥有到表两端的链。

缺点:查找,需要花费线性时间,由于节点是不连续存储的。删除最后一个节点比较复杂,因为需要更新指向最后一个节点的节点next指向为null。

总结:打印操作,查找包含操作等需要从一个节点开始,根据next指向遍历所有的节点,时间复杂度为O(N)

为了解决删除最后一个节点的复杂操作,可以使用双链表,每个节点保存前驱和后继两个指向,第一节点没有前驱,最后一个节点没有后继。

4、迭代器:如果对正在被迭代的集合进行结构上的改变(增加,删除,clear等操作),可能会引发ConcurrentModificationException异常。所有建议使用迭代器自身的remove等方法。

5、ArrayList表,其实现方式抽象结构为数组,提供了一种可增长的数组的实现,那么它就具备数组的优点。get和set操作花费常数时间,缺点在于新项的插入和现有项的删除效率低下。

LinkedList表,其实现方式抽象为链表,这意味着,在表的前端,新项的插入和现有相的删除开销小,因此它提供了addFirst,removeFirst等和前端有关的操作。缺点在于不容易做索引,因此get效率低下。

6、栈:限制插入和删除只能在一个位置进行的表。表的末端叫栈顶。基本操作为push入栈,pop出栈,栈是先进先出。

栈的应用:

用于检查平衡符号,在变成中 小括号(),大括号{},中括号[]等是要配对存在的,我们在编译前需要进行错误检查,检查符号是否配对。

实现:做一个空栈,读入字符知道文件结尾。如果字符是一个开放符号,则将其推入栈中。如果字符是一个封闭符号,则当栈空时报错。否则将栈元素弹出。如果弹出的符号不是对应的开放符号,则报错。在文件的结尾,如果栈非空,则报错。

后缀表达式:当见到一个数时,就把他推入栈中;在遇到运算符号时就让该运算符作用于该栈弹出的两个数上,在把所得结果推入栈中。

中缀到后缀的转换:当读到一个操作数时,立即把他放到输出中,操作符存入一个空栈中。左括号也放入空栈中。如果见到一个游括号,那么就将栈元素弹出,掏出的符号写出直至遇到对应的左括号。左右括号均不输出。如果见到其他符号,那么我们从栈中弹出栈元素,直到发现优先级更低的元素为止。

中序表达式:a+b*c+(d*e+f)*g  转换成后序表达式为:abc*+de*f+g*+。

7、队列:使用队列时,插入在一端进行,而删除在另一端进行。基本操作:enqueue入列,是在表的末端插入一个元素。dequeue出列,实在表的开头返回一个元素。

队列有时有空间限制,只有10个空间,前端执行5,后端指向10,那么下次入列会造成溢出,解决这个问题,我们可以使用循环数组来实现队列。再次入列,我们将后端指向第1位。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息