数据结构--用链表栈实现括号的匹配问题

在结构化存储数据集是常常使用数组即顺序表,但当数据庞大时用数组往往比较繁琐,例如我需要在数组中间添加一个元素进去,则需要移动很多个元素,而且在定义数组大小时,小了会溢出,大了会浪费。

而链表正是代替数组解决了这些问题。

链表可以在O(1)的复杂度下处理删除,添加等问题,而且可以用指针来动态分配存储空间,不会出现空间浪费的情况

例子:

编写一个Stack的用例,从输入中读取一个文本流并使用栈判定其中的括号是否配对完整。

例如:对于[()]{}{[()()]()}程序应该打印true,对于[(])则打印false.

问题分析:

这是一道栈的典型问题,利用栈“先进后出”的特性,在这个[(){}{()}中从左到右遍历,遇到左括号“[”,“(”,“{”就一一放进栈里面,每遇到一个右括号“(”,“[”,“{”就把栈顶的元素取出来对比是否为它的“伴侣”。如果不是直接就是可以“false”。

用链表来建立栈图示:

●—●—●—●

      ↑  ↑

        next     栈顶

添加一个元素

●—●—●—●—●

          ↑  ↑

            原栈顶  栈顶

                next

●代表结点,->代表指向结点

 代码详解:

#include<iostream>
using namespace std;
template<class Item>//Item可以是任意数据类型
struct Node
{
	Item item;
	Node *next;//指向栈顶的前一个
};
template<class Item>//每次用都需要在模板前写上这个
class Stack
{
private:
	Node<Item> *first;//栈顶
	Item N;//数量
public:
	Stack()//构造函数
	{
		N = 0;
		first = NULL;
	}
	bool isEmpty()//判断栈是否为空
	{
		return  first == NULL ? 0 : 1;
	}
	//由于栈的先进后出,此处采用的是下压堆栈
	void push(int items)//添加元素
	{
		Node<Item> *oldfirst = first;//建立一个新的结点记录原来的栈顶
		first = new Node<Item>();//建议一个新的结点记录新加进来的元素
		first->item = items;
		first->next = oldfirst;//此时栈顶的前一个是原来的栈顶oldfirst
		N++;
	}
	Item pop()//删除元素
	{

		if (isEmpty())
		{
			Item item = first->item;
			first = first->next;
			N--;

			return item;
		}
		else
			return 0;
	}
	void setpop()
	{
		while (isEmpty())
		{
			first = first->next;
			N--;
		}
	}
};
int main()
{
	Stack <int>A;
	int a[126] = { 0 };
	int flag;
	//把每一个左括号都标志为1
	a[40] = 1;
	a[91] = 1;
	a[123] = 1;
	char s[100];
	while (cin >> s)
	{
		flag = 1;
		int len = strlen(s);
		for (int i = 0; i < len; i++)
		{
			if (a[s[i]])//如果是左括号就入栈
			{
				A.push(s[i]);
			}
			//如果是右括号就取出栈顶的位置来判断是否匹配
			else
			{
				int t = A.pop();
				if (s[i] == t + 1 || s[i] == t + 2)  continue;
				else
				{
					flag = 0;
					break;
				}
			}
		}
		if (!A.isEmpty() && flag)
			cout << "Yes" << endl;
		else
		{
			cout << "No" << endl;
			A.setpop();
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41676901/article/details/81516708