您的位置:首页 > 其它

用链表实现双向队列

2016-03-02 21:42 489 查看
每个节点设置了指向前一节点与后一节点的引用pre与next,实现了队列两端增加删除元素的操作。

具体代码如下:

import java.util.Iterator;
import edu.princeton.cs.algs4.StdOut;

public class Dequeue<Item> implements Iterable<Item>{
private Node head;
private Node tail;
private int length;

/**
* constructor
*/
public Dequeue() {
// TODO Auto-generated constructor stub
head = new Node(null);
tail = new Node(null);
}

/**
* is this queue empty?
* @author Bjy_PC
*
* @param <Item>
*/
public boolean isEmpty() {
return head.next == null;
}

/**
*
* @return length of queue
*/
public int size() {
return length;
}

/**
* insert item from left
* @param item
*/
public void pushLeft(Item item) {
Node node = new Node(item);
Node oldnode = head.next;
head.next = node;
node.pre = head;
node.next = oldnode;
length++;
if (tail.pre == null) {
tail.pre = node;
node.next = tail;
}

}

/**
* insert item from right
* @param item
*/
public void pushRight(Item item) {
Node node = new Node(item);;
Node oldnode = tail.pre ;
node.next = tail;
node.pre = oldnode;
tail.pre = node;
oldnode.next = node;
length++;
if (head.next == null) {
head.next = node;
node.pre = head;
}
}

/**
*
* @return the item deleted from left
*/
public Item popLeft() {
Item item;
if (isEmpty()) throw new java.lang.NullPointerException("dequeue is empty");
else {
item = (Item) head.value;
head.next = head.next.next;
head.next.pre = head;
length--;
}
return item;
}

/**
*
* @return the item deleted from right
*/
public Item popRight() {
Item item;
if (isEmpty()) throw new java.lang.NullPointerException("dequeue is empty");
else {
item = (Item) tail.value;
tail.pre = tail.pre.pre;
tail.pre.next = tail;
length--;
}
return item;
}

@Override
public String toString() {
// TODO Auto-generated method stub
Node node = head.next;
String string = new String();
while (node.value != null) {
string += (String)node.value + "--->";
node = node.next;
}
return string;
}

@Override
public Iterator<Item> iterator() {
// TODO Auto-generated method stub
return new dequeueIterator();
}

private class dequeueIterator implements Iterator<Item> {
Node Cur = head;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return Cur != tail.pre;
}

@Override
public Item next() {
// TODO Auto-generated method stub
Item item = (Item) Cur.next.value;
Cur = Cur.next;
return item;
}

}
private class Node {
Item value;
Node next;
Node pre;
public Node(Item value) {
// TODO Auto-generated constructor stub
this.value = value;
this.next = null;
this.pre = null;
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Dequeue<String> dequeue = new Dequeue<String>();
dequeue.pushLeft("hello");
StdOut.println(dequeue);
dequeue.pushRight("good");
StdOut.println(dequeue);
dequeue.pushLeft("ok");
dequeue.pushRight("thanks");
dequeue.popRight();
dequeue.popLeft();
dequeue.pushLeft("all");
dequeue.pushRight("do");
dequeue.popLeft();
dequeue.popLeft();
dequeue.popLeft();
dequeue.popLeft();
for (String string : dequeue) {
StdOut.println(string);
}
StdOut.println(dequeue);
StdOut.println(dequeue.size());
}
}


运行结果:

ok—>hello—>good—>thanks—>

all—>hello—>good—>do—>

good—>do—>

size:2

算法分析:

从时间复杂度上来说,除了显示队列的toString方法外,其他所有的操作都是常数。

从空间复杂度上来说,每个node节点占用48字节(对象开销16字节,内部类的额外开销8字节,3个引用共24字节)。对于Dequeue类来说大约有(20 + (48 + sizeof(Item))*(N+2))(包含tail与head节点,未计算填充字节)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: