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

表、栈和队列

抽象数据类型

概念

抽象数据类型( Abstract Data Type,ADT)是带有一组操作的一些对象的集合,是数学的抽象。

实例

表、图、集合以及他们各自的操作(添加、删除等)一起形成的对象。

表 ADT

数组实现

  • 连续存储、固定容量
  • 线性时间操作
    • 打印
    • 插入与删除
  • 常数时间操作
    • 查找

链表实现

  • 不连续存储
  • 线性时间操作
    • 查找
    • 打印
  • 常数时间操作
    • 插入与删除

* 删除最后一项时:

  1. 找到指向最后节点的项并将其 next 链修改为 null
  2. 更新持有最后节点的链

Java Collections API 中的表

Collection 接口

public interface Collection<T> extends Iterable<T> {
   
    int size();
    boolean isEmpty();
    void clear();
    boolean contains(T x);
    boolean add(T x);
    boolean remove(T x);
    java.util.Iterator<T> iterator();    
}
  • 接口并不规定集合如何决定某一元素是否属于集合,需要由实现该接口的具体类来确定

Collection 接口扩展了 Iterable 接口,实现了该接口的类可以拥有增强的 for 循环,该循环施加于这些类之上以观察它们所有的项。

public static <T> void print(Collection<T> coll) {
   
    for ( T item : coll ) {
   
        System.out.println(item);
    }
}

Iterator 接口

实现 Iterator 接口的集合需要提供 iterator 方法,通过该方法,每个集合均可创建并返回给用户一个实现了 Iterator 接口的对象并将当前位置的概念在对象内部存储下来。

public interface Iterator <T> {
   
    boolean hasNext();	// 判断下一项是否存在
	T next();			// 调用集合的下一项
    void remove();		// 删除由 next() 最新返回的项
}
  • remove() 在调用一次后不可再调用直至下一次调用 next() 完成。该方法与 Collection 接口的 remove() 方法相比,效率更高。
  • 若不使用该接口的 remove() 方法而是自定义操作使得集合结构改变则会导致迭代器不再合法,若继续使用则会抛出并发修改异常。
public static <T> void print(Collection<T> coll) {
   
    Iterator<T> itr = coll.iterator();
    while ( itr.hasNext() ) {
   
        T item = itr.next();
        System.out.println(item);
    }
}

List 接口及其具体实现类

public interface List<T> extends Collection<T> {
   
    T get(int index);
    T set(int index, T newVal);
    void add(int index, T x);
    void remove(int index);
    ListIterator<T> listIterator(int pos);
}
ArrayList 类

提供了 List ADT 一种可增长数组的实现,可在需要时自动增加基础数组的容量。

  • 优点:对 get 与 set 操作花费常数时间
  • 缺点:新项的插入与现有项的删除代价昂贵
LinkedList 类

提供了 List ADT 的双链表实现

  • 优点:假定变动项位置已知,新项的插入与现有项的删除均开销很小,常数时间
  • 缺点:不易作索引,对 get 的调用代价昂贵

对于搜索而言,Collection 的 contains() 与 remove() 方法对于上述两种实现均花费线性时间,低效。

ListIterator 接口
public interface ListIterator<T> extends Iterator<T> {
   
	boolean hasPrevious();
    T previous();
    void add(T x);
    void set(T newVal);
}

栈 ADT

概念

栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,记作栈顶(top),又称作后进先出表(LIFO)。

栈顶元素是整个模型中唯一可见的元素。

基本操作:

  • 进栈(push):插入元素
  • 出栈(pop):删除并返回最后插入的元素

实现

任何实现表的方法都能实现栈,其中多用 ArrayList 与 LinkedList。

  • 链表实现:利用单链表
  • 数组实现:模仿 ArrayList 实现

基于上述实现的操作可以非常快的常数时间运行

应用

平衡符号(括号的开闭)、后缀表达式、中缀到后缀的转换、方法调用(方法调用与方法返回基本上类似于开括号和闭括号)

队列 ADT

概念

队列也是表,使用时插入在一端进行而删除则在另一端进行,先进先出(FIFO)。

基本操作:

  • 入队(enqueue):在表的末端(队尾 rear)插入元素
  • 出队(dequeue):删除并返回在表的开头(队头 front)的元素

实现

与栈的情形类似。

数组实现

潜在问题:数组前部可能已经有元素出列,数据并未满位,此时 back 标识可能移动到数组的最后一个下标位置,下一次入队的元素则会存放失败。

解决:循环数组实现,只要 front 或是 back 到达数组的尾端则又将其放回开头。

应用

  • 文件服务器:使用其他计算机的用户是按照先到先得的原则访问文件,因此其数据结构是一个队列。

优先队列

根据元素的优先级值决定元素的弹出顺序,实质结构为堆结构,并不是线性结构。

相关的图遍历方式

深度优先遍历 DFS

在这里插入图片描述

宽度优先遍历 BFS

在这里插入图片描述

高频面试题

查询最值

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的 min 函数。
(时间复杂度应为 O(1))

思路

应用一个辅助栈</

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值