C++ 数据结构与算法------栈

1 栈的定义

栈,zhan,从木从。牲口棚,马棚。栈的结构是很简单的,简单来说就是一个先入后出的列表。

2 栈的实现

程序源码: 

#pragma once
#include <exception>
#include <iostream>
#include <string>
using namespace std;

class illegalParameterValue :public exception
{
public:
	illegalParameterValue(string _str)
	{
		cout << _str << endl;
	}
	~illegalParameterValue() {}
};

class stackIsEmpty :public exception
{
public:
	stackIsEmpty(string _str)
	{
		cout << _str << endl;
	}
	~stackIsEmpty() {}
};

template<typename T>
class CStack
{
public:
	virtual ~CStack() {}
	virtual bool empty() const = 0;
	virtual int size() const = 0;
	virtual T& top() const = 0;
	virtual void pop() = 0;
	virtual void push(const T& e) = 0;
};

template<typename T>
class ArrayStack :public CStack<T>
{
public:
	ArrayStack(int length = 10);
	~ArrayStack();

	int size() const;
	bool empty() const;
	T& top() const;
	void pop();
	void push(const T& e);
	friend ostream& operator<<(ostream& os, const ArrayStack<T>& sk)
	{
		for (int i = 0; i < sk.size(); i++)
		{
			os << sk.element[i] << "\t";
		}
		return os;
	}

private:
	T* element;
	int stackTop;
	int length;
};

template<typename T>
inline ArrayStack<T>::ArrayStack(int _length)
{
	if (_length < 1)
	{
		throw illegalParameterValue("_length must > 0");
	}
	length = _length;
	stackTop = -1;
	element = new T[length];
}

template<typename T>
inline ArrayStack<T>::~ArrayStack()
{
	delete[] element;
}

template<typename T>
inline int ArrayStack<T>::size() const
{
	return stackTop + 1;
}

template<typename T>
inline bool ArrayStack<T>::empty() const
{
	return stackTop == -1;
}

template<typename T>
inline T & ArrayStack<T>::top() const
{
	if (stackTop == -1)
	{
		throw stackIsEmpty("Stack is empty");
	}
	return element[stackTop];
}

template<typename T>
inline void ArrayStack<T>::pop()
{
	if (stackTop == -1)
	{
		cout << "Stack is empty" << endl;
		return;
	}
	element[stackTop].~T();
	stackTop--;
}

template<typename T>
inline void ArrayStack<T>::push(const T & e)
{
	if (stackTop == length - 1)
	{
		cout << "Stack is full" << endl;
		T* temp = new T[2 * length];
		copy(element, element + length, temp);
		length = 2 * length;
		delete[] element;
		element = temp;
	}
	stackTop++;
	element[stackTop] = e;
}

3 栈的实例

3.1 括号匹配 

3.png

凡遇 (,则进栈;凡遇 ),则出栈 。

 程序源码:

#include "CStack.h"

// 括号匹配
/* 函数:printMatchedPairs
 * 功能:打印括号的匹配关系
 * Input:string expr, 含有括号的表达式
 * Output:void
 * */
void printMatchedPairs(string expr);

int main()
{
	cout << "*******************括号匹配**********************" << endl;
	printMatchedPairs("s(ds)(dsd(ds)ds(ds(ds(ds)ds)s");

	system("pause");
	return 0;
}

void printMatchedPairs(string expr)
{
	cout << "原始字符串: " << expr << endl;
	ArrayStack<int> sk(30);
	int length = expr.size();
	for (int i = 0; i < length; i++)
	{
		if (expr.at(i) == '(')
		{
			sk.push(i);
		}
		if (expr.at(i) == ')')
		{
			if (sk.empty())
			{
				continue;
			}
			else
			{
				cout << sk.top() << " 与 " << i << " 匹配" << endl;
				sk.pop();
			}
		}
	}
	cout << "end!!!" << endl;
	cout << endl;
}

 3.2 汉诺塔问题

汉诺塔是一个发源于印度的益智游戏,也叫河内塔。相传它源于印度神话中的大梵天创造的三个金刚柱,一根柱子上叠着上下从小到大64个黄金圆盘。大梵天命令婆罗门将这些圆盘按从小到大的顺序移动到另一根柱子上,其中大圆盘不能放在小圆盘上面。当这64个圆盘移动完的时候,世界就将毁灭。 

算法原理参照:https://blog.csdn.net/xb2355404/article/details/79144451 

程序源码:

#include "CStack.h"

// 汉诺塔问题
/* 函数:towerOfHanoi
 * 功能:打印汉诺塔问题的过程
 * Input:int n, 圆盘的个数
 *       int x, 柱子x
 *       int y, 柱子y
 *       int z, 柱子z
 * Output:void
 * */
ArrayStack<int> ask[3];
void move(int x, int y);
void towerOfHanoi(int n, int x, int y, int z);

int main()
{
	cout << "*******************汉诺塔问题**********************" << endl;
	for (int i = 2; i >= 0; i--)
	{
		ask[0].push(i);
	}
	towerOfHanoi(3, 0, 1, 2);
	
	system("pause");
	return 0;
}

void move(int x, int y)
{
	int temp = ask[x].top();
	ask[x].pop();
	ask[y].push(temp);
	cout << "移动: " << x << "-->" << y << endl;
	for (int i = 0; i < 3; i++)
	{
		cout << i << ": " << ask[i] << endl;
	}
}

void towerOfHanoi(int n, int x, int y, int z)
{
	if (n == 1)
	{
		move(x, z);
	}
	else
	{
		towerOfHanoi(n - 1, x, z, y);
		move(x, z);
		towerOfHanoi(n - 1, y, x, z);
	}
}

 3.3 混栈洗甄别

所谓地栈混洗,就是根据某种约定地规则,对栈内元素进行重新排序。 

考查栈:A = < a1, a2, ..., an ]、B = S = Ø,左端为栈顶

只允许:将 A 的顶元素弹出并压入 S(S.push(A.pop())),或将 S 的顶元素弹出并压入 B(B.push(S.pop()))

若经过一系列以上操作后,A 中元素全部转入 B 中,B = [ a(k1), ..., a(kn) >,右端为栈顶

则称之为 A 的一个栈混洗(stack permutation)
原文:https://blog.csdn.net/u014027680/article/details/84888012 

1. 对任意的i, j, k有[...,[k],...,[j],...,[i],...>必非栈混洗;

2. 不存在...,[k],...,[j],...,[i],...的栈一定可由栈混洗得到。 

程序源码: 

#include "CStack.h"

// 混栈洗
/* 函数:IsPermutation
 * 功能:判断B是否是A的混栈洗
 * Input:string _A, 栈A中元素组成的字符串
 *       string _B, 栈B中元素组成的字符串
 * Output:bool ret,B是否是A的混栈洗
 * */
bool IsPermutation(string _A, string _B);

int main()
{
	cout << "*******************混栈洗甄别**********************" << endl;
	if (IsPermutation("12345", "35412"))
		cout << "Y!" << endl;
	else
		cout << "N!" << endl;

	system("pause");
	return 0;
}

bool IsPermutation(string _A, string _B)
{
	cout << "原始栈:" << _A << endl;
	cout << "测试栈:" << _B << endl;

	// 判断参数
	if (_A.size() != _B.size())
	{
		cout << "error: _A and _B should have the same size." << endl;
		return false;
	}

	// A:原始栈,B:待测栈,C:输出栈,S:中转栈
	// 若BC相等,则B是A的一个栈混洗
	ArrayStack<char> A, B, C, S;

	for (int i = 0; i < _A.size(); i++)
	{
		A.push(_A.at(i));
		B.push(_B.at(i));
	}

	for (int i = 0; i < _A.size(); i++)
	{
		while (S.empty() || S.top() != _B.at(i))
		{
			if (!A.empty())
			{
				S.push(A.top()); // 将A.top()取出,压入S
				A.pop();
			}
			else
				return false;
		}
		C.push(S.top());
		S.pop();
	}
	cout << "A = " << A << endl;
	cout << "B = " << B << endl;
	cout << "C = " << C << endl;
	return true;
}

 4 输出结果

*******************括号匹配**********************
原始字符串: s(ds)(dsd(ds)ds(ds(ds(ds)ds)s
1 与 4 匹配
9 与 12 匹配
21 与 24 匹配
18 与 27 匹配
end!!!

*******************汉诺塔问题**********************
移动: 0-->2
0: 2    1
1:
2: 0
移动: 0-->1
0: 2
1: 1
2: 0
移动: 2-->1
0: 2
1: 1    0
2:
移动: 0-->2
0:
1: 1    0
2: 2
移动: 1-->0
0: 0
1: 1
2: 2
移动: 1-->2
0: 0
1:
2: 2    1
移动: 0-->2
0:
1:
2: 2    1       0

*******************混栈洗甄别**********************
原始栈:12345
测试栈:35412
N!
请按任意键继续. . .

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值