美文网首页
背包、队列和栈

背包、队列和栈

作者: 进击的勇士 | 来源:发表于2017-03-03 14:44 被阅读0次

API介绍


背包

public class Bag<Item> implements Iterable<Item>
{
            Bag()              // 创建一个空背包
    void    add(Item item)     // 向背包中添加一个元素
    boolean isEmpty()          // 背包是否为空
    int     size()             // 背包中的元素数量
}         

队列

public class Queue<Item> implements Iterable<Item>
{
            Queue()            // 创建空队列
    void    enqueue(Item item) // 添加一个元素
    Item    dequeue()          // 删除最早添加的元素
    boolean isEmpty()          // 队列是否为空
    int     size()             // 队列中的元素数量
}

public class Stack<Item> implements Iterable<Item>
{
            Stack()             // 创建一个空栈
    void    push(Item item)     // 压入一个元素
    Item    pop()               // 推出最后压入的元素
    boolean isEmpty()           // 栈是否为空
    int     size()              // 栈中的元素数量
}

特点及用例


背包

  • 不支持从中删除元素
  • 迭代的顺序不确定且与用例无关
// 用于计算平均数和标准差
public class Stats
{
    public static void main(String[] args)
    {
        Bag<Double> numbers = new Bag<Double>();
        while (!StdIn.isEmpty())
            numbers.add(StdIn.readDouble());
        int N = numbers.size();

        double sum = 0.0;
        for (double x : numbers)
            sum += x;
        double mean = sum/N;  // 平均数

        sum = 0.0;
        for (double x : numbers)
            sum += (x - mean)*(x - mean);
        double std = Math.sqrt(sum/(N-1));  // 标准差

        StdOut.printf("Mean: %.2f\n", mean);
        StdOut.printf("Std: %.2f\n", std);
    }
}

队列

  • 先进先出(FIFO)
  • 入列顺序和出列顺序相同
// 将队列的中数字拷贝到数组当中
public static int[] readInts(String name)
{
    In in = new In(name);
    Queue<Integer> q = new Queue<Integer>();
    while (!in.isEmpty())
        q.enqueue(in.readInt()); // 从文件中读入整数, 加入队列(自动装箱)

    int N = q.size();
    int[] a = new int[N];  // 数组定义初始化
    for (int i = 0; i < N; i++)
        a[i] = q.dequeue();  // FIFO: 顺序保持不变
    return a;
}

  • 后进先出(LIFO)
  • 可是使用双栈来求解数学运算
public class Evaluate
{
    public static void main(String[] args)
    {
        Stack<String> ops = new Stack<String>();  // 操作符栈
        Stack<Double> vals = new Stack<Double>();  // 操作数栈
        while (!StdIn.isEmpty())
        {
            String s = StdIn.readString();
            if      (s.equals("("));
            else if (s.equals("+"))      ops.push(s);
            else if (s.equals("-"))      ops.push(s);
            else if (s.equals("*"))      ops.push(s);
            else if (s.equals("/"))      ops.push(s);
            else if (s.equals(")"))
            {
                String op = ops.pop();  // 弹出操作符
                double v  = vals.pop(); // 弹出操作数
                if      (op.equals("+")) v = vals.pop() + v;  
                else if (op.equals("-")) v = vals.pop() - v;  
                else if (op.equals("*")) v = vals.pop() * v;
                else if (op.equals("/")) v = vals.pop() / v;
                vals.push(v);
            }
            else vals.push(Double.parseDouble(s));
        }
        StdOut.println(vals.pop());
    }
}

集合类数据类型的实现


动态变容量的栈(数组实现)

  1. 需要resize方法动态扩展栈的容量
  2. push的时候,需要检查栈和数组的大小,合适的时候进行扩容
  3. pop的时候,当栈的大小小于数组的1/4的时候,数组缩减为原来的1/2
  4. pop的时候,将不使用的对象置为null,方便垃圾回收
  5. 实现iterable接口,方便遍历
import java.util.Iterator
public class ResizeingArrayStack<Item> implements Iterable<Item> {
  private Item[] a = (Item[]) new Object[1]; // 栈元素  
  private int N = 0; // 元素数量  
  public boolean isEmpty() {return N == 0;}
  public int size() {return N;}
  private void resize(int max) {
    // 将一个数组移动到一个新的数组当中
    Item[] temp = (Item[]) new Object[max];
    for (int i = 0; i < N; i++)
      temp[i] = a[i];
    a = temp;
  }

  public void push(Item item) {
    if (N == a.length) {resize(2 * a.length)}
    a[N++] = item;
  }

  public Item pop() {
    Item item = a[--N];
    a[N] = null;// 避免对象游离
    if (N > 0 &&N < a.length / 4) 
      resize(a.length / 2);
  }
 
  public Iterator<Item> iterator() {
    return new ReverseArrayIterator()
  }

  private class ReverseArrayIterator implements Iterator<Item>{
    // 实现后进先出的迭代顺序
    private int i = N;
    public boolean hasNext() { return N > 0; }
    public Item next() { return a[--i]; }
    public void remove() {}
  }
} 

动态变容量的栈(链表实现)

import java.util.Iterator
public class Stack<Item> implements Iterable<Item> {
    private Node first;
    private int N;
    private class Node {
        Item item;
        Node next;
    }
    
    public boolean isEmpty(){
        return N == 0;
    }
    
    public int size() {
        return N;
    }
    
    public void push(Item item) {
        Node oldFirst = first;
        first = new Node();
        first.item = item;
        first.next = oldFirst;
        N++;
    }
    
    public Item pop() {
        Item item = first.item;
        first = first.next;
        N--;
        return item;
    }
}

动态变容量的队列(链表实现)

由于实现队列需要使用两个指针(first/last), 所以需要考虑一些特殊情况。

  1. 入队列的时候,如果只有一个元素,需要将first和last都指向第一个元素
  2. 出队列的时候,如果是最后一个元素,需要将last置为null
import java.util.Iterator
public class Queue<Item> implements Iterable<Item> {
    private Node first;
    private Node last;
        private int N;
    private class Node {
        Item item;
        Node next;
    }
    
    public boolean isEmpty(){
        return N == 0;
    }
    
    public int size() {
        return N;
    }
    
    public void enqueue(Item item) {
        Node oldLast = last;
        last = new Node();
        last.item = item;
        last.next = null;
        if(isEmpty())
            first = last;
        else 
            oldLast.next = last;
        N++;
    }
    
    public Item dequeue() {
        Item item = first.item;
        first = first.next;
        if(isEmpty())
            last = null;
        N--;
        return item;
    }
}

相关文章

  • 背包、栈和队列

    介绍 背包是一种不支持从中删除元素的集合类型,它的目的是帮助用例收集元素并迭代遍历所有收集到的元素,迭代的顺序不确...

  • 背包、队列和栈

    背包、队列和栈 ApI 背包 队列 栈 泛型 集合类的抽象数据类型的一个关键特性是我们应该可以用他们存储任意类型的...

  • 背包、队列和栈

    API介绍 背包 队列 栈 特点及用例 背包 不支持从中删除元素 迭代的顺序不确定且与用例无关 队列 先进先出(F...

  • 栈与队列和背包

    栈 (Stack) 后进先出的策略的集合类型(LIFO) 栈的接口抽象如下: 一些特点: 后进先出(LIFO) p...

  • 背包、队列和下压栈

    排着队,背着包,一个一个向下压。 没错,今天就来讲一讲我们的三种数据结构类型,分别是背包、队列和下压栈。 首先向大...

  • 算法学习笔记-基础开篇

    算法定义 基础问题 三种基础的抽象数据类型:背包、队列、栈 用数组、变长数组、链表实现背包、队列、栈的api。 数...

  • Java 之背包、队列和栈

    夜深了,宿舍里,桌子上的杯子和勺子开始攀谈起来…… 「杯子杯子,我看主人今天一直在忙着写程序啊!」勺子说道。 「是...

  • 数据结构——栈和队列

    用数组实现栈和队列 用栈实现队列 用队列实现栈 栈和队列的经典算法题最小间距栈宠物收养所 数组实现栈和队列 用数组...

  • 栈和队列

    用栈定义队列(出入栈) 用队列定义栈(数据队列和辅助队列)

  • 算法与数据结构:栈,队列,包及其链表实现

    栈 , 队列 , 背包 **栈 : **栈 , 在之前的一篇文章里面已经讲过了 , 遵从先入后出原则 (FILO)...

网友评论

      本文标题:背包、队列和栈

      本文链接:https://www.haomeiwen.com/subject/tpvlgttx.html