简体   繁体   English

函数返回堆栈的第二个元素而不改变C ++中的堆栈

[英]function that returns second element of a stack without altering the stack in C++

I am thinking that the best way to return the second element of a stack without popping the stack is to create a function is to uses peek but peek returns the top element. 我认为返回堆栈的第二个元素而不弹出堆栈的最好方法是创建一个函数是使用peek但peek返回顶部元素。 How would I override peek so that it returned the second element, or use peek in some other fashion to accomplish my goal? 我如何覆盖peek以便它返回第二个元素,或者以其他方式使用peek来实现我的目标?

This is java like pseudo algorithm. 这是java类似伪算法。 What you do is use a variable to store the top of the stack (pop if it exists), use another to store the second element of the stack (peek if it exists), push the top element back and then return the second element. 你要做的是使用一个变量来存储堆栈的顶部(如果存在则弹出),使用另一个来存储堆栈的第二个元素(如果存在则查看),将顶部元素推回然后返回第二个元素。

Object obj = stack.empty() ? null : stack.pop();
if(obj == null)
    return null;
Object ret = stack.empty() ? null : stack.peek();
stack.push(obj);
return ret;

But everything depends on how the stack is implemented. 但一切都取决于堆栈的实现方式。 In C++, you'll have to do something like this. 在C ++中,你必须做这样的事情。

if(stck.size() < 2) throw "Stack has no second element!";
Object obj = stck.top();
stck.pop();
Object ret = stck.top();
stack.push(obj);
return ret

According to the C++ Standard std::stack contains a protected member variable for the container named c . 根据C ++标准, std::stack包含一个名为c的容器的受保护成员变量。 Knowing this and using a little bit of magic you can gain access to it with a pointer to this member variable. 知道这一点并使用一点点魔法,您可以使用指向此成员变量的指针来访问它。 Once you have access to the underlying container ( std::deque by default) you can access the contained data. 一旦您有权访问底层容器(默认情况下为std::deque ),您就可以访问包含的数据。

template<class T /* value type */, class C /* container */>
typename std::stack<T, C>::container_type& GetContainer(std::stack<T,C>& adapter)
{
    struct AdapterAccessor : std::stack<T, C>
    {
        static std::stack<T, C>::container_type& Get(std::stack<T, C>& adapter)
        {
            return adapter.*&AdapterAccessor::c;
        }
    };

    return AdapterAccessor::Get(adapter);
}

This works because although AdapterAccessor does not have direct access to the contents of adapters it does have indirect access via the pointer-to-member. 这是有效的,因为虽然AdapterAccessor无法直接访问adapters的内容,但它确实通过指向成员的指针进行间接访问。

You can also make it usable with other container adapters. 您还可以使其与其他容器适配器一起使用。

template <template<class, class> class Adapter, class T, class... Args>
typename Adapter<T, Args...>::container_type&
GetContainer(Adapter<T, Args...>& adapter)
{
    struct AdapterAccessor : Adapter<T, Args...>
    {
        static Adapter<T, Args...>::container_type& Get(Adapter<T, Args...>& adapter)
        {
            return adapter.*&AdapterAccessor::c;
        }
    };

    return AdapterAccessor::Get(adapter);
}

Example usage: 用法示例:

int main()
{
    std::stack<char> st;
    st.push('1');
    st.push('2');
    st.push('3');
    st.push('4');

    auto& contents = GetContainer(st);
    std::cout << contents[0] << std::endl;
    std::cout << contents[3] << std::endl;
    std::cout << contents[1] << std::endl;
    std::cout << contents[2] << std::endl;
}

I'm not sure if it is possible, since a stack is based off of the principle last in first out. 我不确定它是否可能,因为堆栈基于最后一个原则。 All you have is a pointer to the stack, and from there you can pop off from the top of the stack, but you cannot pop off within the stack. 你所拥有的只是指向堆栈的指针,从那里你可以从堆栈的顶部弹出,但你不能在堆栈中弹出。 The only way I can think of to do it would be to create a function like. 我能想到的唯一方法是创建一个像这样的函数。

object returnSecond(stack<object> a){
 a.pop();
 return a.top();
}

or a more general one function like 或者更通用的一个功能就像

object peekN(stack<object> a, int n){
 for(int i = 0;i<n;i++){
  a.pop();
 }
return a.top();
}

Not to be restricted in "Stack". 不限制在“堆栈”中。 It is an abstract datatype, so you can define the datatype of yourself. 它是一种抽象数据类型,因此您可以定义自己的数据类型。 If you just don't want to define datatype and want to use some functions of stack. 如果您只是不想定义数据类型并希望使用堆栈的某些功能。 I advise you to define a function of yourself(like the answer of Sudo Andrew). 我建议你定义一个自己的功能(就像Sudo Andrew的答案)。 But it seems far-fetched and not like stack. 但它似乎很牵强,而不是像堆栈。

just use std::vector instead. 只需使用std :: vector。

std::vector<int>numbers;

numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);

int secondElem = *(nums.end() - 2);

cout << secondElem << endl;

prints 2 打印2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM