程序员面试金典: 9.3栈与队列 3.6编写程序,按升序对栈进行排序(即最大元素位于栈顶)

#include <iostream>
#include <stdio.h>
#include <string>
#include <stack>

using namespace std;

/*
问题:编写程序,按升序对栈进行排序(即最大元素位于栈顶)。最多只能使用一个额外的栈存放临时数据,但不得将
      元素赋值到别的数据结构中(如数组)。该栈支持如下操作: push、pop、peek和isEmpty。
分析:栈后进先出,但是需要对栈排序,而且允许使用一个额外的栈。可以在每次压入时,如果当前元素大于临时栈中元素
      时,就将当前元素压入栈中;弹出元素时,获取栈顶元素如果和临时栈中元素相同,说明是最大元素,就弹出临时栈和
	  栈本身中元素。
	  那么这道题目本质和之前实现min函数为O(1)是相同的
输入:
3(栈中存放的元素个数)
3 6 5
3(指令个数)
push 8
push 2
pop 1

7
1 3 8 12 7 10 5
0
输出:
2 3 5 6(栈中元素按从小到大排序)
1 3 5 7 8 10 12

书上解法:
题目意思理解错了,题目是一定需要你排序的。
一个例子
S1  
5
10
7 
S2
12
8
3
1
将栈S2用于最终排序后结果存放。S1中弹出5,需要存放到S2中元素3的上面。
步骤:
1先保存5
2必须将S2中大于S1栈顶元素的所有元素,先保存到S1中,以便在S2中留下待插入位置。
3将S1中待插入元素插入S2中
4继续将S1中栈顶元素重复上述过程,直到S1为空,此时S2已经排好序

关键:
1 用两个栈,栈1用于存放原始输入元素,栈2用于保存排序后结果
2 将栈1的元素要移动到已经有序的栈2中(插入排序,在已经排好序的序列中插入一个新的元素),
  将栈2中所有大于栈1栈顶的元素全部移动到栈1中,栈1中栈顶元素移动到栈2中
  只要栈1不空,重复对栈1的栈顶元素执行上述操作就能排好序
*/

class SortStack : public stack<int>
{
public:
	//压入元素时,除了正常的栈压入外,额外成员最大栈判定如果待压入元素>=临时栈栈顶元素,就压入,导致里面都是拍好序的元素
	void push(int value)
	{
		stack<int>::push(value);
		//应该是一边插入一边排序,如果结果栈(排好序的栈中为空,说明这是首次有元素插入,应该将该元素插入到结果栈)
		if(resultStack.empty())
		{
			resultStack.push(value);
			stack<int>::pop();
		}
		//如果结果栈中已经有元素了,那么现在,比较栈与结果栈栈顶,如果栈顶元素<结果栈栈顶元素,说明应该将栈顶元素插入到结果栈中
		//因此将结果栈中凡是大于栈顶元素的元素都转移到栈中,然后将原栈顶元素插入到结果栈栈顶元素,
		else
		{
			//只要原先栈中元素不空,就一直直接这个操作
			while( !isEmpty() )
			{
				int temp = stack<int>::top();
				stack<int>::pop();
				//这边必须确保resultStack不为空,否则为空top会有问题
				while(!resultStack.empty() && temp < resultStack.top() ) // 将栈2中所有大于栈1栈顶元素的元素,转移到栈1中
				{
					int value = resultStack.top();
					resultStack.pop();
					stack<int>::push(value);
				}
				//全部转移完成后,是否需要直接继续把S1中所有元素拷贝过来,还是不弄,不做的话需要放在另外函数中做,所以还是要做一下
				resultStack.push(temp);
			}
		}
	}

	//弹出时,栈本身正常弹出,如果栈的栈顶元素=最大栈的栈顶元素,说明待弹出的元素是最大值,则最大栈也弹出。
	//由于每次压入的结果都会在结果栈中拍好序,每次弹出,肯定都是弹出排好序的结果栈中最大元素
	void pop()
	{
		//最大栈为空,直接弹出正常栈的元素
		if(resultStack.empty())
		{
			return;
		}
		resultStack.pop();
	}

	//弄清楚这里是要返回最大元素,因此,需要返回maxStack的元素
	int top()
	{
		if( resultStack.empty() )
		{
			return -1;
		}
		else
		{
			return resultStack.top();
		}
	}

	bool isEmpty()
	{
		return stack<int>::empty();
	}

	void print()
	{
		stack<int> stackTemp(resultStack);
		stack<int> stackData;
		while(!stackTemp.empty())
		{
			stackData.push( stackTemp.top() );
			stackTemp.pop();
		}
		while(!stackData.empty())
		{
			cout << stackData.top() << " ";
			stackData.pop();
		}
		cout << endl;
	}
private:
	stack<int> resultStack;
};

int main(int argc, char* argv[])
{
	int n;
	int commandNum;
	string command;
	int value;
	while(cin >> n)
	{
		SortStack maxStack;
		int* pArr = new int[n];
		for(int i = 0 ; i < n ; i++)
		{
			cin >> *(pArr + i);
			maxStack.push( *(pArr + i) );
		}
		cin >> commandNum;
		for(int j = 0 ; j < commandNum ; j++)
		{
			cin >> command >> value;
			if(command == "pop")
			{
				for(int k = 0 ; k < value ; k++)
				{
					maxStack.pop();
				}
			}
			else if(command == "push")
			{
				maxStack.push(value);
			}
		}
		//输出栈中元素
		maxStack.print();
		delete[] pArr;
	}
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值