下面是两道常见笔试题:
栈的原地排序。(注:所谓原地就是指不需要额外的辅助空间,或者只需要常数个额外空间)
栈的原地倒转。
但是在这里递归的思想非常抽象,但是又不得不让人叹服!(我也是看了别人的答案,简直太经典了!)另外,虽然不允许另外使用额外空间,但实际上递归本身就要很多空间。。。
【栈的原地倒转】
这里的递归思想用语言描述太复杂,但是您一看代码,加上那一点注释,很快就能明白的。相信你也会为这个递归的用法感到奇妙!
#include <iostream>
#include <stack>
using namespace std;
//display the stack
void printStack( stack<int> s );
//!!!!!!
void reverse( stack<int>& s )
{
/*
** if there is only one element pr no element in stack
** there is no need to reverse.
*/
if( s.empty() || s.size() == 1 )
return ;
/*
** GOOD!!!
** in the beginning, the stack is 1,2,,n-1,n
*/
int top_one = s.top(); s.pop();//1,2,,n-1
reverse( s ); //n-1,n-2,..,2,1
int bottom = s.top(); s.pop(); //n-1,n-2,,2
reverse( s ); //2,3,n-1
s.push( top_one ); //2,3,,n-1,n
reverse( s ); //n,n-1,,3,2
s.push( bottom ); //n,n-1,,2,1
}
int main()
{
stack<int> s;
s.push( 5 );
s.push( 6 );
s.push( 4 );
s.push( 8 );
s.push( 10 );
s.push( 11 );
printStack( s );
reverse( s );
printStack( s );
}
void printStack( stack<int> s )
{
stack<int> temp(s);
while( ! temp.empty() )
{
cout<<temp.top()<<" ";
temp.pop();
}
cout<<endl;
}
#include <stack>
using namespace std;
//display the stack
void printStack( stack<int> s );
//!!!!!!
void reverse( stack<int>& s )
{
/*
** if there is only one element pr no element in stack
** there is no need to reverse.
*/
if( s.empty() || s.size() == 1 )
return ;
/*
** GOOD!!!
** in the beginning, the stack is 1,2,,n-1,n
*/
int top_one = s.top(); s.pop();//1,2,,n-1
reverse( s ); //n-1,n-2,..,2,1
int bottom = s.top(); s.pop(); //n-1,n-2,,2
reverse( s ); //2,3,n-1
s.push( top_one ); //2,3,,n-1,n
reverse( s ); //n,n-1,,3,2
s.push( bottom ); //n,n-1,,2,1
}
int main()
{
stack<int> s;
s.push( 5 );
s.push( 6 );
s.push( 4 );
s.push( 8 );
s.push( 10 );
s.push( 11 );
printStack( s );
reverse( s );
printStack( s );
}
void printStack( stack<int> s )
{
stack<int> temp(s);
while( ! temp.empty() )
{
cout<<temp.top()<<" ";
temp.pop();
}
cout<<endl;
}
不过这里我犯了一个大错误:由于这里的函数需要对栈进行操作改变,所以需要传递一个引用(stack&),而不能只传一个值进去,否则是看不到结果的改变的。。。让我费了好久debug!
【栈的原地排序】
其实有了上面这道题,这部分代码也很容易。大致思想就是:每次从栈顶取出一个元素(记为A),都要递归的对剩下的元素排序。问题的关键在于,这个取出来的元素如何放回去,因为其余的元素都已经排好序了,不能随便放回去。我们这里实现的是最小栈(栈顶为最小元素,记为B),所以取出来的元素A需要跟当前栈顶的元素B作比较,如果它比当前栈顶B还小,那么A理所当然的应该放在栈顶;否则,就把栈顶元素B取出,把A放进去(因为B是所有元素中最小的,A比它大,当然要先入栈),递归排序,然后再把B入栈。
代码如下(只贴出了排序的函数,其余函数可以参照上面的):
//!!!!!!
void sortStack( stack<int>& s )
{
if( s.empty() || s.size() == 1 )
return;
int top_one = s.top(); s.pop();
sortStack( s );
int smallest = s.top(); s.pop();
if( smallest < top_one )//it's smallest overall
{
s.push( top_one );
//top_one may be very big
//need to sort the stack again
sortStack( s );
s.push( smallest );
}
else
{
//no need to sort again
s.push( smallest );
s.push( top_one);
}
}
void sortStack( stack<int>& s )
{
if( s.empty() || s.size() == 1 )
return;
int top_one = s.top(); s.pop();
sortStack( s );
int smallest = s.top(); s.pop();
if( smallest < top_one )//it's smallest overall
{
s.push( top_one );
//top_one may be very big
//need to sort the stack again
sortStack( s );
s.push( smallest );
}
else
{
//no need to sort again
s.push( smallest );
s.push( top_one);
}
}