栈排序(空间复杂度O(1))

如果要将空间复杂度为O(1),那么就不能够声明数组来申请空间了

只有两个堆栈可以使用。

那么我们该怎么去实现排序了,因为堆栈是后进先出,只有一端能进入和出去,这就使得问题复杂了。

其实我们可以不再另申请空间也能完成排序。

比如,一个输出栈S,输入栈R,我们每次将输入栈的元素push进入输出栈S,但是因为我们的输出栈元素需要排序,假定从栈底到栈顶按照从小到大的顺序排列,那么我们如果输入的栈的元素比输出栈中的栈顶元素小,按理说,应该排在这个栈顶元素的下面。所以,我们这时候需要先将输出栈中的栈顶元素pop出来,然后再将输入栈的栈顶元素push进入输入栈,这时候我们在将之前pop出来的栈顶元素在按照原有的排序push进入输出栈。

那么,问题是我们将输出栈中pop出去的那一部分元素怎么保存呢,当然,通常情况下我们可以使用数组保存啊,但是空间复杂度为O(1)的时候,很显然我们不能在定义数组申请空间,其实我们可以将pop出去的元素push进入输入栈的栈顶,等之前输入栈push进入输出栈的元素找到位置后,再依次push到输出栈,这样既可以不开辟空间,也可以完成栈的排序。

例:

栈排序
时间限制:1 sec

空间限制:256 MB

问题描述
给定一个序列 A,请你将它升序排序。

输入格式
第一行一个正整数 n,表示序列长度。

第二行 n 个用空格隔开的非负整数,描述这个序列。

输出格式
n 行,每行一个非负整数,表示排序后的序列。

样例输入
4
1 3 2 10
样例输出
1
2
3
10
数据范围
保证 n<=1000,保证序列中的数不超过 32767,以及时间复杂度为O(1)

我们其实就可以使用刚刚说的方法,借助输入栈存放一些元素的方法。

代码:因为输出要求是升序输出,我这里用的栈排序是降序压进栈中。所以我这里使用的输出方式是vector逆迭代器

#include<iostream>
#include<stack>
#include<vector>

using namespace std;

stack<int> Stack_Sort(stack<int> myStack)
{ 
	stack<int> output;     //最后需要输出的堆栈 
	
	if(myStack.empty())   //输入堆栈为空 ,若为空,就没有元素压入栈中 
	  return output;
	
	int t = myStack.top();  //要压入output的元素
	
	
	myStack.pop();  //弹出元素 
	
	//! myStack.empty()这是一个边界条件,意味着输入栈的元素压完后,就结束排序操作了
	// (!output.empty() && output.top()>t) 这一个式子有一点复杂
	// !output.empty()如果输出栈为空或者是 output.top()>t输出栈栈顶指针比最后的t(存放的是输入栈所有元素压完进入输出栈,但是t变量还是存了一个元素) 
	//然后我们必须把t在压入输出栈中,但是因为会考虑到乱序,那么通过 output.top()>t考虑到是否再重新排序 
	while(!myStack.empty() || (!output.empty() && output.top()>t))
	{
		if(output.empty() || output.top()<=t)
		{
			output.push(t);
			t = myStack.top();   //更新元素 
			myStack.pop();
		}
		else
		{
			myStack.push(output.top());
			output.pop();
		}
	} 
	output.push(t);
	return output;
}


int main()
{
	
	stack<int> R;    //乱序的堆栈,将从该堆栈一直pop元素到堆栈S 
	int nums;
	int n;
	cin>>n;
	for(int i = 1;i<n;i++)
	{
		cin>>nums;
		R.push(nums);
	} 
	
	stack<int> result = Stack_Sort(R);
	
	vector<int> answer;   
	
    while(!result.empty())
    {
    	answer.push_back(result.top());  //将堆栈里的内容从尾部一个一个添加到vector 
    	result.pop();
    }
    //反向迭代器 ,因为我们需要输出升序,就需要将容器逆序输出 
    for(vector<int>::reverse_iterator i = answer.rbegin();i!=answer.rend();++i)
    {
    	cout<<*i<<endl;
    }
     
	
	return 0;
}

这里的输出边pop()边输出,便于理解

#include<iostream>
#include<stack>
using namespace std;

stack<int> Stack_sorting(stack<int> input)
{
	stack<int> output;
	
	if(input.empty())
	return output;
	
	int temp = input.top();
	input.pop();
	
	while(!input.empty() || (!output.empty() && output.top()>temp))
	{
		if(output.empty() || output.top()<=temp)
		{
			output.push(temp);
			temp = input.top();
			input.pop();
		}
		else
		{
			input.push(output.top());
			output.pop();
		}
	}
	output.push(temp);
	return output;
}

int main()
{
	stack<int> R;  //输入栈
	int n;
	int nums;
	cin>>n;
	
	for(int i = 0;i<n;i++)
	{
		cin>>nums;
		R.push(nums);
	} 
	
	stack<int> reslut = Stack_sorting(R);
	stack<int> fuzhu;
	
	for(int j = 0;j<n;j++)
	{
		fuzhu.push(reslut.top());
		reslut.pop();
	}
	
	for(int k = 0;k<n;k++)
	{
		cout<<fuzhu.top()<<endl;
		fuzhu.pop();
	}
	
	return 0;
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页