Chapter 3 | Stacks and Queues--实现数据结构模拟一个栈由几个子栈组成,并可以在指定子栈上进行出栈操作

3.3  Imagine a (literal) stack of plates. If the stack gets too high,it might topple. Therefore, in real life, we would likely start a newstack when the previous stack exceeds some threshold. Implement adata structure SetOfStacks that mimics this. SetOfStacks should be composed of several stacks, and should create a new stack once theprevious one exceeds capacity. SetOfStacks.push() andSetOfStacks.pop() should behave identically to a single stack(that is, pop() should return the same values as it would if therewere just a single stack).

FOLLOW UP

Implement a function popAt(int index) which performs a pop operationon a specific sub-stack.


译文:把栈想象成一碟盘子,如果盘子叠的太高,就会倾倒。因此,在实际生活中,在前面的栈超出一定高度时,我们就会开始另一个新栈。实现数据结构 SetOfStacks 来模拟这种情况,SetOfStacks 由几个栈组成,当前面一个栈超出容量时,需要创建一个新栈来存放数据。SetOfStacks.push() andSetOfStacks.pop() 的行为应该和只有一个栈时一样。

进一步的,实现函数 popAt(int index) 在指定子栈上进行 pop 操作。


这里用了 STL 中的 序列式容器vector,vector 内部实现则参见 vector 内部机制

#include<iostream>
#include<vector>  //STL
#include<assert.h>

using namespace std;

class SetOfStacks;

class Stack
{
public:
	Stack(int Size);
	~Stack(void);

	void push(int val);
	void pop(void);
	int top(void);
	bool isempty(void);
	bool isfull(void);
	friend class SetOfStacks;   //友元类

private:
	int *Data;
	int current;
	int capacity;
};

Stack::Stack(int Size)
{
	Data = new int[Size];
	current = -1;
	capacity = Size;
}

Stack::~Stack(void)
{
	if (Data)
		delete[] Data;
}

void Stack::push(int val)
{
	Data[++current] = val;
}

void Stack::pop(void)
{
	--current;
}

int Stack::top(void)
{
	return Data[current];
}

bool Stack::isempty(void)
{
	return (-1 == current);
}

bool Stack::isfull(void)
{
	return (current == (capacity - 1));
}

//SetOfStacks数据结构
class SetOfStacks   
{
public:
	SetOfStacks(Stack &s);
	~SetOfStacks(void);

	Stack* getLastStack(void);
	Stack* getStack(int index);

	void push(int val);
	void pop(void);
	int top(void);
	void popAt(int index);

private:
	vector<Stack*> Stacks;     //from STL
};

SetOfStacks::SetOfStacks(Stack &s)
{
	Stacks.push_back(&s);
}

SetOfStacks::~SetOfStacks(void)
{
}

/*返回最后一个栈*/
Stack* SetOfStacks::getLastStack(void)
{
	if (0 == Stacks.size())
		return NULL;
	else
		return Stacks.back();
}

/*返回指定栈*/
Stack* SetOfStacks::getStack(int index)
{
	if ((index < 0) || (index >= ((int)Stacks.size()-1)))
		return NULL;
	else
		return Stacks[index];
}

void SetOfStacks::push(int val)
{
	Stack* pStack = getLastStack();
	assert(NULL != pStack);

	if (pStack->isfull())     //栈满,则创建新栈
	{
		Stack* stack = new Stack(sizeof(Stack));
		stack->Data = new int[pStack->capacity];

		stack->current = -1;
		stack->capacity = pStack->capacity;
		stack->push(val);
		Stacks.push_back(stack);   //添加到vector
	}
	else
	{
		pStack->push(val);
	}
}

void SetOfStacks::pop(void)
{
	Stack* pStack = getLastStack();
	assert(NULL != pStack);

	pStack->pop();
	if (pStack->isempty())   //当前栈为空,则销毁
	{
		delete[] pStack->Data;  //释放空间
		Stacks.pop_back();      //vector 析构
	}
}

int SetOfStacks::top(void)
{
	Stack* pStack = getLastStack();
	assert(NULL != pStack);

	return pStack->Data[pStack->current];
}

//指定子栈进行 pop
void SetOfStacks::popAt(int index)
{
	Stack* pStack = getStack(index);
	assert(NULL != pStack);;

	pStack->pop();
	if (pStack->isempty())  //pop后指定栈为空
	{
		delete[] pStack->Data; 
		//销毁指定栈,并将后面子栈前移
		for (unsigned int i = index; i < (Stacks.size() - 1); ++i)  
		{
			if (Stacks[i + 1] != NULL)
				Stacks[i] = Stacks[i + 1];
		}
		Stacks.pop_back();   //前移后,销毁最后一个
	}
}
上面最指定子栈 pop 的函数 popAt 其功能是将指定位置的子栈元素弹出,当该子栈为空(没有元素)时,则将其后面的子栈前移,并销毁最后一个子栈,这样保证 pop 中间指定子栈后,其总栈在逻辑上还是连续的。

 如不借用STL中的 vector,也可自行设计一个链表用来存储子栈。

测试代码及结果:

int main()
{
	Stack stack(2);
	SetOfStacks setofstacks(stack);

	setofstacks.push(1);
	setofstacks.push(2);

	setofstacks.push(3);
	setofstacks.push(4);

	setofstacks.push(5);
	setofstacks.push(6);   //stack:1 2 3 4 5 6

	setofstacks.popAt(1);  //stack:1 2 3 5 6
	setofstacks.popAt(1);  //stack:1 2 5 6
	setofstacks.pop();     //stack:1 2 5
	setofstacks.pop();     //stack:1 2
	/*setofstacks.pop();
	setofstacks.pop();
	setofstacks.pop();*/

	cout << setofstacks.top() << endl;  //output:2
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值