【算法 队列】Deque && RandomizedQueue 实现

一个人比较缓慢,大多数在于信息不全面、思维碰撞缺乏,在B站上也没有找到相关群体
故此,留一个群号,希望可以共同进步,相互监督,940774008

Deque.java

双端队列,还算是很简单的链式实现。
发现一个小有趣的地方,如果不 implements Iterable<> 直接写 内部类Iterator也是可以的
可以while next,但是无法使用 foreach 语法糖,虽然你实现了 Iterator,以前一直没注意到

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Deque<Item> implements Iterable<Item> {
    private Node first; // 8    8
    private Node last;  // 8    16
    private int size;   // 4    20

    private class Node {    // 16-object + 8-innerClass + 8 + 8 + 8 = 48 N
        private Item item;  // 8
        private Node next;  // 8
        private Node pre;   // 8
    }

    // construct an empty deque
    public Deque() {
    }

    // is the deque empty?
    public boolean isEmpty() {
        return first == null && last == null;
    }

    // return the number of items on the deque
    public int size() {
        return size;
    }

    // add the item to the front
    public void addFirst(Item item) {
        // 0.合法性检查
        isValid(item);
        // 1.存储旧的
        Node oldFirst = first;
        first = new Node();
        first.item = item;
        if (oldFirst != null) {
            first.next = oldFirst;
            oldFirst.pre = first;
        }
        else
            last = first;
        size++;
    }

    // add the item to the back
    public void addLast(Item item) {
        // 0.合法性检查
        isValid(item);
        // 1.存储旧的
        Node oldLast = last;
        last = new Node();
        last.item = item;
        if (oldLast == null) {
            first = last;
        }
        else {
            last.pre = oldLast;
            oldLast.next = last;
        }
        size++;
    }

    // remove and return the item from the front
    public Item removeFirst() {
        removeEmpty();
        Item item = first.item;
        if (size == 1) {
            first = null;
            last = null;
        }
        else {
            first = first.next;
            first.pre = null;
        }

        size--;
        return item;
    }

    // remove and return the item from the back
    public Item removeLast() {
        removeEmpty();
        Item item = last.item;
        if (size == 1) {
            first = null;
            last = null;
        }
        else {
            last = last.pre;
            last.next = null;
        }
        size--;
        return item;
    }

    // return an iterator over items in order from front to back
    public Iterator<Item> iterator() {
        return new ListIterator();
    }

    private class ListIterator implements Iterator<Item> {
        private Node current = first;    // first Node  16-object + 8-innerClass + 8 = 32

        public boolean hasNext() {
            return current != null;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

        public Item next() {
            if (!hasNext()) throw new NoSuchElementException();
            Item item = current.item;
            current = current.next;
            return item;
        }
    }

    private void isValid(Item item) {
        if (item == null)
            throw new IllegalArgumentException();
    }

    private void removeEmpty() {
        if (isEmpty())
            throw new NoSuchElementException();
    }

    // Target : 48n + 192 bytes || constant worst-case time(add/remove/iterator)

    // unit testing (required)
    public static void main(String[] args) {
        Deque<Integer> idq = new Deque<>();
        idq.addFirst(1);
        idq.addFirst(2);
        idq.addFirst(4);
        idq.addFirst(3);
        Integer integer = idq.removeFirst();
        Integer integer1 = idq.removeLast();
        System.out.println(integer + "|" + integer1);
        Iterator<Integer> iterator = idq.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

需要注意的点是:特殊情况的处理,比如 增加第一个,删除最后一个,这样的边界情况。
剩下的事情就是按部就班的实现就行了。

RandomizedQueue.java

虽然叫做随机队列,但它不符合 队列的FIFO规则,所以,只是习惯上称为 随机队列。
实现思想上,通过数组来作为核心操作对象,原因是:
随机队列实现必须在固定的摊销时间内支持每个随机队列操作
在最坏的情况下,对于常数c,任何m个随机队列操作的混合序列(从空队列开始)必须最多执行cm步
很显然,如果继续使用链式实现,就不是 c * m,而是 n * m

随机队列显然——不要求顺序的,这一点在实现上就会减少很多 搬移数组 的麻烦,所需要做的只有将deque的Item从target索引处取出,然后与最后size索引处的Item交换,然后将size处置空即可。

import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class RandomizedQueue<Item> implements Iterable<Item> {
    private Item[] rq;
    private int size;

    // construct an empty randomized queue
    public RandomizedQueue() {
        rq = (Item[]) new Object[8];
        size = 0;
    }

    // is the randomized queue empty?
    public boolean isEmpty() {
        return size == 0;
    }

    // return the number of items on the randomized queue
    public int size() {
        return size;
    }

    // add the item
    public void enqueue(Item item) {
        if (item == null)
            throw new IllegalArgumentException();
        if (size == rq.length)
            resize(2 * rq.length);
        rq[size++] = item;
    }

    // remove and return a random item
    public Item dequeue() {
        if (size == 0)
            throw new NoSuchElementException();
        if (size < rq.length / 4)
            resize(rq.length / 2);
        int target = StdRandom.uniform(0, size);
        Item item = rq[target];
        rq[target] = rq[size];
        rq[size] = null;
        return item;
    }

    // return a random item (but do not remove it)
    public Item sample() {
        if (size == 0)
            throw new NoSuchElementException();
        return rq[StdRandom.uniform(0, size)];
    }

    // return an independent iterator over items in random order
    public Iterator<Item> iterator() {
        return new RandomIterator();
    }

    private void resize(int capacity) {
        Item[] newrq = (Item[]) new Object[capacity];
        System.arraycopy(rq, 0, newrq, 0, size);
        rq = newrq;
    }

    private class RandomIterator implements Iterator<Item> {
        private int index;
        private Item[] iters;

        public RandomIterator() {
            index = size;
            iters = (Item[]) new Object[index];
            System.arraycopy(rq, 0, iters, 0, size);
        }

        public boolean hasNext() {
            return index != 0;
        }

        public Item next() {
            if (index == 0)
                throw new NoSuchElementException();
            int target = StdRandom.uniform(0, index);
            Item item = iters[target];
            iters[target] = iters[index];
            iters[index] = null;
            index--;
            return item;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    // unit testing (required)
    public static void main(String[] args) {

    }
}

Permutation.java

编写一个Permutation.java以整数k作为命令行参数的客户端程序;使用StdIn.readString(); 从标准输入读取字符串序列; 并精确地均匀地打印其中的k个。最多打印一次序列中的每个项目。
使用 RandomizedQueue 即可。写个 while 循环,很简单

public class Permutation {
    public static void main(String[] args) {
        RandomizedQueue<String> srq = new RandomizedQueue<>();
        int k = Integer.parseInt(args[0]);
        while (!StdIn.isEmpty()) {
            srq.enqueue(StdIn.readString());
        }
        while (k > 0) {
            System.out.println(srq.dequeue());
            k--;
        }
    }
}

评分结果

有时间再改进。主要目的过完整个课程

See the Assessment Guide for information on how to interpret this report.

ASSESSMENT SUMMARY

Compilation:  PASSED (0 errors, 3 warnings)
API:          PASSED

Spotbugs:     PASSED
PMD:          FAILED (1 warning)
Checkstyle:   PASSED

Correctness:  32/43 tests passed
Memory:       97/105 tests passed
Timing:       153/193 tests passed

Aggregate score: 79.74%
[Compilation: 5%, API: 5%, Spotbugs: 0%, PMD: 0%, Checkstyle: 0%, Correctness: 60%, Memory: 10%, Timing: 20%]

ASSESSMENT DETAILS

The following files were submitted:
----------------------------------
3.7K Jan 25 05:45 Deque.java
 612 Jan 25 05:45 Permutation.java
2.8K Jan 25 05:45 RandomizedQueue.java
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值