堆栈

目录:

9、【剑指Offer学习】【面试题09:用两个栈实现队列】

30、【剑指Offer学习】【面试题30:包含min函数的栈】

31、【剑指Offer学习】【面试题31:栈的压入、弹出序列】

9. 【剑指Offer学习】【面试题09:用两个栈实现队列】

	/*******************************************************************
	Copyright(c) 2016, Harry He
	All rights reserved.
	
	Distributed under the BSD license.
	(See accompanying file LICENSE.txt at
	https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
	*******************************************************************/
	
	//==================================================================
	// 《剑指Offer——名企面试官精讲典型编程题》代码
	// 作者:何海涛
	//==================================================================
	
	// 面试题9:用两个栈实现队列
	// 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail
	// 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。
	
	#include "Queue.h"
	
	// ====================测试代码====================
	void Test(char actual, char expected)
	{
	    if(actual == expected)
	        printf("Test passed.\n");
	    else
	        printf("Test failed.\n");
	}
	
	int main(int argc, char* argv[])
	{
	    CQueue<char> queue;
	
	    queue.appendTail('a');
	    queue.appendTail('b');
	    queue.appendTail('c');
	
	    char head = queue.deleteHead();
	    Test(head, 'a');
	
	    head = queue.deleteHead();
	    Test(head, 'b');
	
	    queue.appendTail('d');
	    head = queue.deleteHead();
	    Test(head, 'c');
	
	    queue.appendTail('e');
	    head = queue.deleteHead();
	    Test(head, 'd');
	
	    head = queue.deleteHead();
	    Test(head, 'e');
	
	    return 0;
	}

	/*******************************************************************
	Copyright(c) 2016, Harry He
	All rights reserved.
	
	Distributed under the BSD license.
	(See accompanying file LICENSE.txt at
	https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
	*******************************************************************/
	
	//==================================================================
	// 《剑指Offer——名企面试官精讲典型编程题》代码
	// 作者:何海涛
	//==================================================================
	
	// 面试题9:用两个栈实现队列
	// 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail
	// 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。
	
	#pragma once
	#include <stack>
	#include <exception>
	
	using namespace std;
	
	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> CQueue<T>::CQueue(void)
	{
	}
	
	template <typename T> CQueue<T>::~CQueue(void)
	{
	}
	
	template<typename T> void CQueue<T>::appendTail(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;
	}

30. 面试题30:包含min函数的栈

	//==================================================================
	// 《剑指Offer——名企面试官精讲典型编程题》代码
	// 作者:何海涛
	//==================================================================

	// 面试题30:包含min函数的栈
	// 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min
	// 函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。

	#pragma once

	#include <stack>
	#include <assert.h>

	template <typename T> class StackWithMin
	{
	public:
		StackWithMin() {}
		virtual ~StackWithMin() {}

		T& top();
		const T& top() const;

		void push(const T& value);
		void pop();

		const T& min() const;

		bool empty() const;
		size_t size() const;

	private:
		std::stack<T>   m_data;     // 数据栈,存放栈的所有元素
		std::stack<T>   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> const T& StackWithMin<T>::min() const
	{
		assert(m_data.size() > 0 && m_min.size() > 0);

		return m_min.top();
	}

	template <typename T> T& StackWithMin<T>::top()
	{
		return m_data.top();
	}

	template <typename T> const T& StackWithMin<T>::top() const
	{
		return m_data.top();
	}

	template <typename T> bool StackWithMin<T>::empty() const
	{
		return m_data.empty();
	}

	template <typename T> size_t StackWithMin<T>::size() const
	{
		return m_data.size();
	}

31. 面试题31:栈的压入、弹出序列

		/*******************************************************************
		Copyright(c) 2016, Harry He
		All rights reserved.

		Distributed under the BSD license.
		(See accompanying file LICENSE.txt at
		https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
		*******************************************************************/

		//==================================================================
		// 《剑指Offer——名企面试官精讲典型编程题》代码
		// 作者:何海涛
		//==================================================================

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

		#include <cstdio>
		#include <stack>

		bool IsPopOrder(const int* pPush, const int* pPop, int nLength)
		{
			bool bPossible = false;

			if(pPush != nullptr && pPop != nullptr && nLength > 0)
			{
				const int* pNextPush = pPush;
				const int* pNextPop = pPop;

				std::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;
		}

		// ====================测试代码====================
		void Test(const char* testName, const int* pPush, const int* pPop, int nLength, bool expected)
		{
			if(testName != nullptr)
				printf("%s begins: ", testName);

			if(IsPopOrder(pPush, pPop, nLength) == expected)
				printf("Passed.\n");
			else
				printf("failed.\n");
		}

		void Test1()
		{
			const int nLength = 5;
			int push[nLength] = {1, 2, 3, 4, 5};
			int pop[nLength] = {4, 5, 3, 2, 1};
			
			Test("Test1", push, pop, nLength, true);
		}

		void Test2()
		{
			const int nLength = 5;
			int push[nLength] = {1, 2, 3, 4, 5};
			int pop[nLength] = {3, 5, 4, 2, 1};
			
			Test("Test2", push, pop, nLength, true);
		}

		void Test3()
		{
			const int nLength = 5;
			int push[nLength] = {1, 2, 3, 4, 5};
			int pop[nLength] = {4, 3, 5, 1, 2};
			
			Test("Test3", push, pop, nLength, false);
		}

		void Test4()
		{
			const int nLength = 5;
			int push[nLength] = {1, 2, 3, 4, 5};
			int pop[nLength] = {3, 5, 4, 1, 2};
			
			Test("Test4", push, pop, nLength, false);
		}

		// push和pop序列只有一个数字
		void Test5()
		{
			const int nLength = 1;
			int push[nLength] = {1};
			int pop[nLength] = {2};

			Test("Test5", push, pop, nLength, false);
		}

		void Test6()
		{
			const int nLength = 1;
			int push[nLength] = {1};
			int pop[nLength] = {1};

			Test("Test6", push, pop, nLength, true);
		}

		void Test7()
		{
			Test("Test7", nullptr, nullptr, 0, false);
		}
		 
		int main(int argc, char* argv[])
		{
			Test1();
			Test2();
			Test3();
			Test4();
			Test5();
			Test6();
			Test7();

			return 0;
		}
posted @ 2019-12-11 20:29  风御之举  阅读(28)  评论(0编辑  收藏  举报