【ADT】第三章 表、栈和队列

抽象数据类型ADT是带有一组操作的对象的集合,诸如表、图以及它们各自的操作一起形成的对象等等


本章将讨论基于表ADT的实现,主要是数组与链表
是否重复:可重复存放的
是否有序:数组是无序的,链表是按插入顺序排序的



1 表ADT

大小为N的表 : A0,A1,A2,A3,……,A(N-1)
其中Ai 是 A(i-1)的后继元,A(i-1)是 Ai 的前继元

对表的实现主要是数组和链表
表是可重复的、无序或按插入顺序排列的。

1.1 数组

数组是由固定容量创建的,用来实现表ADT,不赘述。

1.2 链表

链表由一系列节点组成,这些节点不必在内存中相连。

1.2.1 单向链表

每一个节点含有表元素、指向该元素后继元节点的引用(next)
最后一个单元的next指向null

1.2.2 双向链表

每一个节点含有表元素、指向该元素后继元节点的引用(next)、指向该元素前继元节点的引用(prev)
最后一个单元的next指向null
第一个单元的prev指向next

1.2.3 编程实现

此处以双向链表为
1 首先定义节点类,存放数据、前节点、后节点

    private class Node<T>{ //节点
        public T data;
        public Node<T> prev;
        public Node<T> next;
        public Node(T t , Node<T> p, Node<T> n) {
            this.data = t;
            this.prev = p;
            this.next = n;
        }
    }

2 在链表类中,我们需要定义两个虚拟的节点:一个首节点作为一个链表的开头,一个尾节点作为链表的结尾
初始化时有首节点.prev = null ; 尾节点.next = null; 首节点.next = 尾节点; 尾节点.prev = 首节点;

public class MyLinkedList<T> {
    private int size;
    private Node<T> beginNode;
    private Node<T> endNode;

    public MyLinkedList(){
        this.size = 0;
        this.beginNode = new Node<T>(null,null,null);//Data null 
        this.endNode = new Node<T>(null,beginNode,null);
        this.beginNode.next = this.endNode;
    }

具体代码实现见GitHub

2 Collection API

2.1 基于数组:ArrayList、Vector(Stack)

2.1.1 ArrayList

ArrayList 和 Vector的唯一区别在于,Vector类中的方法都是带有synchronized关键字的,故用于多线程下线程安全,ArrayList类用于单线程下

2.1.2 Stack(栈ADT)

栈ADT是限制插入和删除只能在一个位置的特殊表,表头入栈,表头出栈,栈的顶端(top),具有后进先出(LIFO)的特性

Stack是Vector类的子类,基于数组实现,同样在List接口下,实现栈ADT
对栈的基本操作,同样Stack也是线程安全的

    public E push(E item) { // 1 把元素压入栈顶

    }

    public synchronized E pop() { // 2 返回栈顶的元素,并把这个元素删除
    }

    public synchronized E peek() { // 3 仅仅返回栈顶元素,不改变栈的结构
    }

    public boolean empty() { // 4 是否为空栈
    }

经典案例:

1 检查符号是否成对
2 后缀表达式
3 中缀转后缀
4 主方法调用其他方法时位置信息的存储

2.2 基于链表:LInkedList(实现List Queue两个接口)

2.2.1 队列ADT(Queue)

队列ADT和栈一样,同样是一种特殊的表ADT,队列要求插入在一端而删除在另外一端,表末入列,表头出列,具有先进先出(FIFO)的特性

2.2.2 LinkedList

LinkedLIst是一个比较特殊的类
基于双链表ADT实现
实现了List和Queue两种接口
在LinkedList类内部定义了push、pop等函数

所以它可以
当做一个List使用

        List list = new LinkedList();
        list.add(12);

当做一个队列使用
1 Queue中都定义了两种返回方式的方法(a抛出异常b返回特定值)
向队列中加入元素:a : add() b : offer()
返回队首元素,但不删除该元素:a : elelment() b : peek()
从队首移除一个元素:a: remove() b : poll()

// 向上转型Queue接口,调用Queue接口的方法
        Queue list1 = new LinkedList();
        list1.offer(123);//push
        list1.element();
        list1.remove();

2 我们还可以使用LInkedList本身自定义方法实现队列
表末入栈,表头出栈,先进先出

public void offer (Object o){//进队,在表末入列
      list.addLast(o);// addLast 与 add 无异
  }
  public Object remove()  {//出队,在表头出列
    return list.removeFirst();
  }
  public Object element() {
      return list.getFirst();
  }

当做一个栈使用
LinkedList本身实现了addFirst(),getFirst(),removeFirst()方法用来做当push,pop, peek方法
表头入栈出栈,先进后出

    public void push(String name){  //表头入栈
        linkedList.addFirst(name);  
    }  

    /**  (即取出链表linkedList的第一个元素) /  
    public String peek(){  // 表头出栈
        return linkedList.getFirst();  
    }  
    /**  (即移出linkedList的第一个元素) /  
    public String pop(){  
        return linkedList.removeFirst();  
    }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值