栈与队列的各种操作

栈与队列的各种操作

1.用两个栈实现队列
2.包含min函数的栈
3.栈的压入、弹出序列
4.栈的压入、弹出序列

5.仅用递归函数和栈操作逆序一个栈

6.用一个栈实现另一个栈的排序

7.滑动窗口的最大值


1.用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail 和 deleteHead,分别完成在队列尾部插入节点和在队列头部删除结点的功能。

template <typename T> class CQueue{
public:
    CQueue(void);
    ~CQueue(void);
    void appendTail (const  T& node);
    T deleteHead();
private:
    stack<T> stack1;
    stack<T> stack2;
}

template<typename T> void CQueue<T>::qppendTail(const T& element)
{
    stack1.push(element);
}
template<typename T>T CQueue<T>::deleteHead()
{
    if (stack2.size()<=0){
        while(stack1.size() >0)
        {
            T& data = stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }
    if (stack2.size() == 0)
        throw new exception("queue is empty");
    T head = stack2.top();
    stack2.pop();
    return head;
}

2.定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。
下面代码中,m_data是数据栈,而 m_min是辅助栈。

template<typename T>void StackWithMin<T>::push(const T& value)
{
    m_data.push(value);
    if (m_min.size() == 0 || value < m_min.top())
        m_min.push(value);
    else
        m_min.push(m_min.top());
}

template<typename T>void StackWithMin<T>::pop()
{
    assert(m_data.size() > 0 && m_min.size() > 0);
    m_data.pop();
    m_min.pop();
}

template<typename T>void StackWithMin<T>::min() const
{
    assert(m_data.size() > 0 && m_min.size()>0);
    return m_min.top();
}

3.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

bool IsPopOrder(const int *pPush, const int *pPop, int nLength)
{
    bool bPossible = false;
    if (pPush != NULL && pPop != NULL && nLength > 0)
    {
        const int *pNextPush = pPush;
        const int *pNextPop = pPop;
        stack<int>stackData;
        while (pNextPop - pPop < nLength)
        {
            while (stackData.empty() || stackData.top() != *pNextPop)
            {
                if (pNextPush - pPush == nLength)
                    break;
                stackData.push(*pNextPush);
                pNextPush++;
            }
            if (stackData.top() != *pNextPop)
                break;
            stackData.pop();
            pNextPop++;
        }
        if (stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }
    return bPossible;
}

4.栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

bool IsPopOrder(const int *pPush, const int *pPop, int nLength)
{
    bool bPossible = false;
    if (pPush != NULL && pPop != NULL && nLength > 0)
    {
        const int *pNextPush = pPush;
        const int *pNextPop = pPop;
        stack<int>stackData;
        while (pNextPop - pPop < nLength)
        {
            while (stackData.empty() || stackData.top() != *pNextPop)
            {
                if (pNextPush - pPush == nLength)
                    break;
                stackData.push(*pNextPush);
                pNextPush++;
            }
            if (stackData.top() != *pNextPop)
                break;
            stackData.pop();
            pNextPop++;
        }
        if (stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }
    return bPossible;
}

5.一个栈依次压入1,2,3,4,5,那么从栈顶到栈低分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈低为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。

int getAndRemoveLast(stack<int>&s) {
	int res = s.top();
	s.pop();
	if (s.empty())return res;
	else {
		int last = getAndRemoveLast(s);
		cout << last << endl;
		s.push(res);
		return last;
	}
}
void reverse(stack<int>&s) {
	if (s.empty())return;
	int i = getAndRemoveLast(s);
	reverse(s);
	s.push(i);
}

6. 一个栈中元素类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。

void stackSort(stack<int>&s) {
	stack<int>aux;
	while (!s.empty()){
		int res = s.top();
		s.pop();
		while (!aux.empty() && res < aux.top()) {
			s.push(aux.top());
			aux.pop();
		}
		aux.push(res);
	}
	while (!aux.empty()) {
		s.push(aux.top());
		aux.pop();
	}
}

7. 给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2 3 4 2 6 2 5 1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别是{4 4 6 6 6 5}。

vector<int>findMaxValue2(vector<int>v, int n) {
	vector<int>res;
	if (v.size() >= n && n >= 1) {
		deque<int>index;
		for (int i = 0; i < n; i++) {
			while (!index.empty() && v[i] >= v[index.back()])
				index.pop_back();
			index.push_back(i);
		}
		for (int i = n; i < v.size(); ++i) {
			res.push_back(v[index.front()]);
			while (!index.empty() && v[i] >= v[index.back()])
				index.pop_back();
			if (!index.empty() && index.front() <= i - n)
				index.pop_front();
			index.push_back(i);
		}
		res.push_back(v[index.front()]);
	}
	return res;
}

猜你喜欢

转载自blog.csdn.net/GUI1259802368/article/details/81459602