为什么我们在现实世界中需要Deque数据结构?

时间:2010-10-07 09:17:55

标签: data-structures deque

有人能举例说明需要Deque数据结构的情况吗?

注意 - 请不要解释deque是什么?

8 个答案:

答案 0 :(得分:27)

Deque是一个双端队列,允许从两端插入和删除。

在实际情况中,我们可以将它附加到票证购买行,它像队列一样执行但是有些时候发生了某些机构已经购买了机票并且突然他们回来在队列前面问了一些事情。在这种情况下,因为他们已经购买了票证,所以他们有权来请求任何进一步的查询。所以在这种情况下我们需要一个数据结构,根据需要我们从前面添加数据。在同样的情况下,用户也可以从后面离开队列。

因此它完全遵循Deque的数据结构。

答案 1 :(得分:21)

在对任何类型的现实等待线进行建模时:实体(位,人,汽车,单词,粒子等)以特定频率到达线的末端,并在开始时以不同的频率进行服务这条线。在等待一些实体可能决定离开线....等。 关键是你需要“快速访问”在行的两端插入/删除,因此是一个双端队列。

答案 2 :(得分:15)

  1. deque的一个很好的应用是存储网络浏览器的历史。最近访问过的URL被添加到双端队列的前面,并且在前面的一些指定数量的插入之后删除了双端队列后面的URL。
  2. deque的另一个常见应用是存储软件应用程序的撤消操作列表。
  3. 可以使用双端队列的一个例子是A-Steal作业调度算法。[5]该算法实现了多个处理器的任务调度。为每个处理器维护一个单独的deque,其中包含要执行的线程。为了执行下一个线程,处理器从deque中获取第一个元素(使用"删除第一个元素" deque操作)。如果当前线程分叉,则将其放回到双端队列的前面("在前面插入元素")并执行新线程。当其中一个处理器完成自己的线程的执行(即它的双端队列为空)时,它可以“偷”"来自另一个处理器的线程:它从另一个处理器的deque中获取最后一个元素("删除最后一个元素")并执行它。 - 礼貌维基百科

答案 3 :(得分:7)

Example in Wikipedia

  

可以使用双端队列的一个示例是A-Steal作业调度算法。该算法实现了多个处理器的任务调度。为每个处理器维护一个单独的deque,其中包含要执行的线程。为了执行下一个线程,处理器从deque中获取第一个元素(使用“remove first element”deque操作)。如果当前线程分叉,则将其放回到双端队列的前面(“在前面插入元素”)并执行新线程。当其中一个处理器完成自己的线程执行(即它的deque为空)时,它可以从另一个处理器“窃取”一个线程:它从另一个处理器的deque中获取最后一个元素(“删除最后一个元素”)并执行它

在最近的CLR via C# book里,Richter描述了.Net 4.0中对ThreadPool所做的改进。绝对值得一读,尤其是偷工作。 Richter描述的算法看起来与维基百科的例子非常相似,所以我怀疑Deque也在那里使用。

答案 4 :(得分:2)

http://en.wikipedia.org/wiki/Deque表示存在使用deques的作业调度算法。德国维基百科页面(http://de.wikipedia.org/wiki/Deque)提到模式匹配算法和非确定性有限状态机的实现作为deques的用例。

答案 5 :(得分:1)

一个deque可以模拟火车站,在那里汽车可以进入和离开一条线的左侧或右侧,但只有两端的汽车可以进出。这是因为里面的车不能撞到外面的车离开,所以他们只需要等待。

答案 6 :(得分:0)

“队列”可以使用两种数据结构之一来实现

  1. 链表 - 如果你只是专门处理目的而不关心内存分配开销(或者关于如何分配内存的限制),这是有道理的。
  2. deque - 如果你工作到最后,还需要定位访问(或者能够快速迭代队列中的项目)并且内存分配开销很重要(但不受约束),然后deque提供两者中的最佳功能(矢量像分配链接列表一样的功能 - 好吧,无论如何,在中间插入更昂贵)
  3. 通常,deque对优先级排队很有用,使用双端队列扫描队列的速度明显快于链表。

答案 7 :(得分:0)

链接迭代器时有一个实际的用法示例。我用它来实现extendable iterator

import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;

public class ExtendableIterator<T> implements Iterator<T> {

    public Deque<Iterator<T>> its = new ConcurrentLinkedDeque<Iterator<T>>();

    public ExtendableIterator() {

    }

    public ExtendableIterator(Iterator<T> it) {
        this();
        this.extend(it);
    }

    @Override
    public boolean hasNext() {
        // this is true since we never hold empty iterators
        return !its.isEmpty() && its.peekLast().hasNext();
    }

    @Override
    public T next() {
        T next = its.peekFirst().next();
        if (!its.peekFirst().hasNext()) {
            its.removeFirst();
        }
        return next;
    }

    public void extend(Iterator<T> it) {
        if (it.hasNext()) {
            its.addLast(it);
        }
    }
}