编程之美读书笔记-队列中取最大值操作问题

原创 2016年08月30日 21:28:07
题目:
假设有这样一个拥有3个操作的队列:
1. EnQueue(v):将v加入队列中
2. DeQueue():使队列中的队首元素删除并返回此元素
3. MaxElement:返回队列中的最大元素
设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低。
解析:设队列长度为N。利用一个数组或链表来存储队列元素,MaxElement时间复杂度为O(N);利用最大堆来存储队列元素,MaxElement时间复杂度为O(1),EnQueue和DeQueue时间复杂度为O(log2N)。按照最大堆的思路,寻找一种新的保存队列中元素相对大小关系的指针集合,并且使得更新这个指针集合的时间复杂度更低。由于栈是一个和队列及其相似的数据结构,我们不妨先看看栈。对于栈来讲,Push和Pop操作都是在栈顶完成的,所以很容易维护栈中的最大值,它的时间复杂度为O(1)。
#include<iostream>  
using namespace std; 
#define MAXN 1000

class MyStack
{
private:
	int stackTop;
	int maxStackItemIndex;
	//最大元素的位置
	int stackItem[MAXN];
	int link2NextMaxItem[MAXN];
	//link2NextMaxItem[i]表示仅小于i位置元素的元素所在位置
	//如果i位置的元素不是当前栈中最大的,这个值就为-1
public:  
	MyStack()
	{
		stackTop = -1;
		maxStackItemIndex = -1;
	}
	bool isEmpty()
	{
		return stackTop == -1;
	}
	bool isFull()
	{
		return stackTop == MAXN - 1;
	}
	void push(int x) 
	{
		if (this->isFull())
		{
			cout << "the stack is full now." << endl;
			return;
		}
		else
		{
			stackItem[++stackTop] = x; 
			if (x > Max()) 
			{
				link2NextMaxItem[stackTop] = maxStackItemIndex;
				maxStackItemIndex = stackTop;
			}
			else
				link2NextMaxItem[stackTop] = -1;
		}
	}
	int pop() 
	{
		int ret;
		if (this->isEmpty())
		{
			cout << "the stack is empty now." << endl;
			return INT_MIN;
		}
		else 
		{
			ret = stackItem[stackTop];  
			if (stackTop == maxStackItemIndex)
			{
				maxStackItemIndex = link2NextMaxItem[stackTop];
			}
			stackTop--;
		}
		return ret;
	}
	int Max() 
	{
		if (maxStackItemIndex >= 0) return stackItem[maxStackItemIndex];
		else return INT_MIN;
	}
};

int main() 
{
	MyStack mystack;
	mystack.push(3);
	mystack.push(4);
	mystack.push(8);
	mystack.push(1);
	mystack.pop();
	mystack.push(7);
	cout << mystack.Max() << endl;
	return 0;
}

如果能够用栈有效地实现队列,而栈的Max操作又很容易实现,那么队列的Max操作也就能有效地完成了。考虑用两个栈来实现一个队列,设为栈A和栈B。
#include<iostream>  
using namespace std; 
#define MAXN 1000

class MyStack
{
private:
	int stackTop;
	int maxStackItemIndex;
	//最大元素的位置
	int stackItem[MAXN];
	int link2NextMaxItem[MAXN];
	//link2NextMaxItem[i]表示仅小于i位置元素的元素所在位置
	//如果i位置的元素不是当前栈中最大的,这个值就为-1
public:  
	MyStack()
	{
		stackTop = -1;
		maxStackItemIndex = -1;
	}
	bool isEmpty()
	{
		return stackTop == -1;
	}
	bool isFull()
	{
		return stackTop == MAXN - 1;
	}
	void push(int x) 
	{
		if (this->isFull())
		{
			cout << "the stack is full now." << endl;
			return;
		}
		else
		{
			stackItem[++stackTop] = x; 
			if (x > Max()) 
			{
				link2NextMaxItem[stackTop] = maxStackItemIndex;
				maxStackItemIndex = stackTop;
			}
			else
				link2NextMaxItem[stackTop] = -1;
		}
	}
	int pop() 
	{
		int ret;
		if (this->isEmpty())
		{
			cout << "the stack is empty now." << endl;
			return INT_MIN;
		}
		else 
		{
			ret = stackItem[stackTop];  
			if (stackTop == maxStackItemIndex)
			{
				maxStackItemIndex = link2NextMaxItem[stackTop];
			}
			stackTop--;
		}
		return ret;
	}
	int Max() 
	{
		if (maxStackItemIndex >= 0) return stackItem[maxStackItemIndex];
		else return INT_MIN;
	}
};

class MyQueue
{
private:
	MyStack mystackA,mystackB;
public:
	int MaxValue(int x, int y)
	{
		if (x > y) return x;
		else return y;
	}
	int Max()
	{
		return MaxValue(mystackA.Max(), mystackB.Max());
	}
	void EnQueue(int v)
	{
		mystackB.push(v);
	}
	int DeQueue()
	{
		if (mystackA.isEmpty())
		{
			while (!mystackB.isEmpty()) mystackA.push(mystackB.pop());
		}
		return mystackA.pop();
	}
};

int main() 
{
	MyQueue myqueue;
	myqueue.EnQueue(8);
	myqueue.EnQueue(3);
	myqueue.EnQueue(4);
	myqueue.EnQueue(1);
	myqueue.DeQueue();
	myqueue.EnQueue(7);
	cout << myqueue.Max() << endl;
	return 0;
}
上述代码能够用栈来实现一个队列。出队的时候,如果A堆栈为空,那么把B堆栈的数据弹出并压入A堆栈这个操作不是O(1)的,虽然如此,但从每个元素的角度来看,它被移动的次数最多可能有3次。所以这种方法的平均时间复杂度是线性的。

《编程之美》——队列中取最大值操作的问题

问题: 假定有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement(): 返回...

队列中取最大值操作问题

队列中取最大值操作问题

[Java]包与包之间的调用

两个包,一个包中的类调用另一个包中的类: package packa; class PackageDemoA { void show() { System.out.println("De...
  • ghbfgb
  • ghbfgb
  • 2016年04月03日 15:08
  • 740

使用Java集合类实现队列

来源:来源works-application 1、要求实现一个FIFO队列;能够查看最大值、最小值、中位数;队列中的每个对象能够比较大小。 接口1: package jp.co.worksa...
  • memewry
  • memewry
  • 2012年09月17日 14:50
  • 4656

编程之美:第三章 结构之法 3.7队列中取最大值操作问题

/* 队列中取最大值操作问题: 假设有这样一个拥有3个操作的队列 1EnQueue(v):将v加入到队列中 2DeQueue():使队列中的队首元素删除并返回此元素 3MaxElement:返回队列中...

编程之美-队列中取最大值操作问题

这是一个要在队列中记录最大值的问题,但每次进队或出队又不能通过遍历去检测最大值的变化。用两个堆栈去实现一个队列是比较常见的方法,书中巧妙的用到了此方法,这样问题就转化为堆栈中取最大值操作问题。由于堆栈...

[编程之美] PSet3.7 队列中取最大值操作问题

问题描述:        假设有这样一个拥有3个操作的队列:       1. EnQueue(v): 将v加入队列中      2. DeQueue(): 使队列中的队首元素删除并返回此元...

编程之美3.7——队列中取最大值操作问题

编程之美3.7——队列中取最大值操作问题 标签: 编程数据结构classstruct算法优化 2012-07-19 23:39 3386人阅读 评论(5) 收藏 举报  分类...

编程之美3.7队列中取最大值操作问题Java版

/* * To change this license header, choose License Headers in Project Properties. * To change this...

编程之美--3.7 队列中取最大值操作问题

思考1 1 利用堆的原理来解决问题...
  • seawade
  • seawade
  • 2014年08月06日 00:01
  • 552
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编程之美读书笔记-队列中取最大值操作问题
举报原因:
原因补充:

(最多只允许输入30个字)