一.题目描述
通过两个栈及一个常数大小的额外空间,对输入序列进行排序
二.实现思路
1.声明两个栈,其中一个用来存放输入序列,是无序的,命名为random。另一个栈中的元素始终保持有序,命名为sorted。另外一个额外存储空间命名为temp
2.把temp值设为random当前的栈顶,若把temp值压入sorted中能够保持有序(temp大于等于栈顶),则直接压入,更新temp
3.若不能直接压入栈,则把sorted当前的栈顶元素弹出并压入random中,不断重复直至temp可以压入sorted。
4.循环执行第2步,直至random为空,且sorted的栈顶元素与temp相同
三.思考题
1.若将temp值压入sorted的条件由大于等于换为大于,会有什么影响?
答:排序算法由稳定的变为不稳定的
稳定的(stable):输入序列中相同的值的元素的相对位置不发生改变
2.算法中if语句的两个分支分别会跑多少次?最好最坏平均由什么决定?
答:与输入序列的逆序对个数有关系,逆序对数越多消耗的次数就越多
这说明这个算法具有输入敏感性(input sensitivity)— 输入会影响算法效率
四.代码实现
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
stack<int> stacksort(stack<int> r);
int main(){
int n;
cin >> n;
stack<int> random;
int x = 0;
for (int i = 0; i < n; i++)
{
cin >> x;
random.push(x);
}
stack<int> sorted=stacksort(random);
vector<int> answer;
int temp=0;
for (int i = 0; i < n; i++)//栈中的元素是降序存储的,因此声明一个向量用来存储结果,反向遍历得升序输出
{
temp = sorted.top();
answer.push_back(temp);
sorted.pop();
}
for (auto i = answer.rbegin(); i != answer.rend(); ++i)//反向迭代器,++i代表访问前一个元素
{
cout << *i << endl;
}
}
stack<int> stacksort(stack<int> random){
stack<int> sorted;
if (random.empty())
return sorted;
int temp = random.top();//把temp值设为未排序栈的第一个元素
random.pop();
while (!random.empty()||sorted.top()!=temp)//思考一下为什么需要后面哪个判断条件(边界情况)
{
if (sorted.empty() || sorted.top() <= temp)
{
sorted.push(temp); //将temp压入栈
if (!random.empty())//边界情况判断
{
temp = random.top();
random.pop();
}
}
else//将sorted的第一个元素放入random中
{
random.push(sorted.top());
sorted.pop();
}
}
return sorted;
}