【算法导论】10.1-5单数组实现双端队列

28 篇文章 1 订阅
22 篇文章 27 订阅

算法导论第三版P131

题目:

10.1-5 栈插入和删除元素只能在同一端进行,队列的插入操作和删除操作分别在两端进行,与它们不同的,有一种双端队列(deque),其插入和删除操作都可以在两端进行。写出4个时间均为O(1)的过程,分别实现在双端队列插入和删除元素的操作,该队列使用一个数组实现的。


注意点:

1、左右端点指向的位置是类似于队列中的tail端点,是下一个插入操作的位置。

2、然后注意遍历的时候,左端点和右端点的位置关系,有两种可能,所以遍历的方式不一样。


代码:

/*
 * 使用单数组实现双端队列
 */
#include <iostream>

using namespace std;

class deque {
	int leftHead; //左端节点,指向下一个能操作的空位置
	int rightHead; //右端节点
	int len;
	int* array;
public:
	deque(int size) :
			leftHead(0), rightHead(0), len(size) {
		array = new int[size];
	}

	~deque() {
		delete []array;
		leftHead = rightHead = 0;
	}

	/*
	 * 获取上一个位置
	 */
	int pre(int pos) {
		if (pos == 0) {
			return len - 1;
		} else {
			return --pos;
		}
	}

	/*
	 * 获取下一个位置
	 */
	int next(int pos) {
		if (pos == len - 1) {
			return 0;
		} else {
			return ++pos;
		}
	}
	bool isEmpty() {
		return leftHead == rightHead ? true : false;
	}

	/*
	 * 左边节点的插入
	 */
	void leftInsert(int k) {
		int p = pre(leftHead);
		if (p == rightHead) {
			cout << "error:overflow" << endl;
			return;
		}

		//如果是空的情况,则左右节点都需要移动
		if (isEmpty()) {
			rightHead = next(rightHead);
		}
		array[leftHead] = k;
		leftHead = p;
	}

	void rightInsert(int k) {
		int n = next(rightHead);
		if (n == leftHead) {
			cout << "error:oveflow" << endl;
			return;
		}
		//如果是空的情况,则左右节点都需要移动
		if (isEmpty()) {
			leftHead = pre(leftHead);
		}
		array[rightHead] = k;
		rightHead = next(rightHead);
	}

	/*
	 * 左端删除
	 */
	int leftDelete() {
		if (isEmpty()) {
			cout << "error:underflow" << endl;
			return -1;
		}
		leftHead = next(leftHead);
		//如果只有一个元素,则删除完之后,右端点也要移动,因为这时队列为空了
		if (leftHead == pre(rightHead)) {
			rightHead = leftHead;
		}
		return array[leftHead];
	}

	/*
	 * 右端删除
	 */
	int rightDelete() {
		if (isEmpty()) {
			cout << "error:underflow" << endl;
			return -1;
		}
		rightHead = pre(rightHead);
		//如果只有一个元素,则删除完之后,左端点也要移动,因为这时队列为空了
		if (rightHead == next(leftHead)) {
			leftHead = rightHead;
		}
		return array[rightHead];
	}

	void printDeque() {

		cout << "leftHead=" << leftHead << ",rightHead=" << rightHead << endl;

		if (isEmpty()) {
			return;
		}
		//考虑leftHead和rightHead分别在左右的两种情况
		if (leftHead < rightHead) {
			for (int i = leftHead + 1; i < rightHead; i++) {
				cout << "array[" << i << "]=" << array[i] << ' ';
			}
			cout << endl;
		} else {
			//leftHead > rightHead时的情况
			for (int i = 0; i < rightHead; i++) {
				cout << "array[" << i << "]=" << array[i] << ' ';
			}
			for (int i = leftHead + 1; i < len; i++) {
				cout << "array[" << i << "]=" << array[i] << ' ';
			}
			cout << endl;
		}

	}

};

int main() {

	deque* dq = new deque(5);
	dq->leftDelete();
	dq->leftInsert(4);
	dq->rightInsert(6);
	dq->printDeque();
	cout << dq->leftDelete() << endl;
	dq->printDeque();

	return 0;
}


/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值