数据结构与算法 ------ 表,栈,和队列

来源:互联网 发布:unity3d lua 热更新 编辑:程序博客网 时间:2024/05/22 17:13

抽象数据类型

抽象数据类型(abstract data type, ADT)是带有一组操作的一些对象的集合

表 ADT

形如A0,A1,A2,...,AN1的表。表的大小为N,将大小为0的表成为空表(empty list)。称Ai后继Ai1Ai1A_i$。

常用操作有
prinList,MakeEmpty,find,insert,remove,findKth
数组表长度固定,insert(插入)和remove(移除)操作的最坏情况为线性开销O(n),开销较大。

简单链表

为避免插入和删除的线性开销,设计了一种不连续存储的表,移动其中一个不用去修改全体。

链表由一系列节点组成,这些节点不必在内存中相连,每一个节点均含有表允许和到包含钙元素后继元的节点的链,我们称之为next链,最后一个单元的next链引用为null。
- remove方法可以通过修改一个next引用来实现。
- insert方法需要使用new操作符从系统取得一个新节点,此后执行两次引用的调整。

一个节点同时拥有前后节点的链,陈伟双链表


Java Collectios API中的表

Collection接口

位于 java.util包中

public interface Collection<E> extends Iterable<E> {    int size();    boolean isEmpty();    void clear();    boolean contains(Object o);    boolean add(Objeat o);    boolean remove(Object o);    Iterator<E> iterator();}

以上为Collection中一些重要的部分,方法名显而易见。

Collection接口扩展了Iterable接口。实现Iterable接口的类可以拥有for-each循环。

Iterator接口

实现Iterable接口的集合必须提供一个成为iterator的方法,此方法返回一个Iterator类型的对象

public interface Iterator<E> {    boolean hasNext;    E next();    void remove();}每个集合都可以创建一个实现Iterator接口的对象,并将当前位置在对象内部存储下来

- next 每次调用next方法都会得到集合下一项,第一次调用得到第一项。
- hasnext 判断是否存在下一项
- 下面,代码1会被编译器重写为代码2

//代码1for(Object item:coll){    System.out.println(item);}//代码2Iterator<Object> itr = coll.iterator();while(itr.hasNext()){    Object item = itr.next();    System.out.println(item);}
  • 正在被迭代的集合不能改变其结构,即不能对它使用add,remove,clear方法。在使用被改变的集合迭代器时会抛出ConcurrentModificationException异常。
  • 但是可以使用迭代器自己的remove方法,表示删除当前项,在下一次使用next方法之前只能调用一次remove方法。

List接口,ArrayList类,LinkedList类

list接口继承Collection接口。并在其基础上外加了一些方法。

public interface List<E> extends Collection<E>{    E get(int index);    E set(int index, E element);    void add(int index, E element);    E remove(int index);    ListIterator<E> listIterator(int index)}

以上为一些比较重要的方法 index索引为 0~n-1
ListIterator为更复杂一些的迭代器。

List有两种比较流行的实现方式
- ArrayList 一种可增长数组
- 其优点在于对get和set花费常数时间
- 其缺点为remove和add的代价较高
- LinkedList 双链表
- 其优点为插入和删除开销较小,其提供了addFirst,removeFirst,addLast,removeLast,getFirst,getLast等有效的添加删除访问表两端的项。
- 其缺点为不容易做索引,set,get代价较高

ListIterator接口

ListIterator扩展了Iterator的功能

public interface ListIterator<E> extends Iterator<E>{    boolean hasPrevious();    E previous();    void add(E x);    E set(int index, E element);}

部分重要方法


栈ADT

栈(stack)是限制插入和删除只能在表的末端的表。
末端叫叫做栈顶,基本的操作有push(进栈)和pop(出栈)。
栈又叫做LIFO(先进先出表)

ArrayList和Linkedlist都支持栈操作
所有它有两种流行的实现方式
- 链表实现
- 数组实现

栈的应用

  • 平衡符号
    检查语法错误,在纯文本写代码的情况下,经常会出现少写一个})]的情况,导致出现语法错误,一般的开发工具都支持语法检测,这里就会用到一个算法并用到栈,当然这只是一个简化的例子,实际的语法检测程序要复杂的多。
    做一个空战。读入字符知道文件结尾。如果字符是一个开放符号({,(,[),则将其推入栈中,如果字符是一个封闭符号,则当栈空时报错。否则,将栈元素弹出。如果弹出的符号不变时对应的开放符号,则报错。在文件末尾,如果栈非空时报错。

  • 后缀表达式
    在计算一个四则运算的时候,*和/的优先级要比+和-高,直接将我们日常所有的式子丢给计算机,他是无法直接理解的,比如 1+2*3+4/5,我们需要一个算法把它分解开再进行计算,例如后缀表达式,而相对应的我们日常所使用的叫做中缀表达式,当然也有前缀表达式。

  • 方法调用

队列ADT

像栈一样,队列(quene)也是表,然而使用队列时插入一段进行而删除则在另一端进行。叫做后进先出表(LIFO)

应用

有许多使用队列给出高效运行实际的算法,他们当中有些可以在图论中找到,我们在后面讨论他们。我们先举一些简单的例子
- 打印机任务
- 文件服务器

阅读全文
0 0