问题描述
我们要做的是,对一个字符串的左右括号进行匹配。例如,字符串(a*(b+c)+d)这个字符串的括号就是匹配的,没有多余的左括号或右括号。
这是数据结构中的一类很经典的问题。
解决思路
对于这个问题,思路上要正确。如果从左至右的扫描一个字符串,那么每一个右括号都和都与最近扫描的那个未匹配的左括号相匹配。这种观察结果促使我们在在从左至右的扫描的过程中,将扫描到的左括号都存在栈中,。每当扫描到一个右括号,就将它与栈顶的左括号相匹配(如果存在),并将匹配的左括号从栈中删除。
第一种实现办法
虽然现在C++中有现成的stack类可以供我们直接使用,但是我们必须要明白其中背后的工作原理。所以我给出的是没有使用stack类的代码(纯原创)
下面展示一些 内联代码片
。
int main()
{
int size = 0;
Node<char> *head,*p;
char a[10];
for(int i = 0;i<10;i++)
{
cin>>a[i];
}
for(int i = 0;i<10;i++)
{
if(a[i] == '(')
{
if(size == 0)
{
head = new Node<char> ;
p = head;
p->element = a[i];
size++;
cout<<size<<endl;
}
else if(size != 0)
{
p->next = new Node<char>(a[i]) ;
p = p->next;
size++;
cout<<size<<endl;
}
}
else if(a[i] == ')')
{
Node<char>* SearchPoint = head;
for(int j = 0;j < size-1;j++)
{
SearchPoint = SearchPoint->next;
}
delete SearchPoint;
size--;
cout<<size<<endl;
}
}
if(size == 0)
{
cout<<"hahaha成功了";
}
else if (size != 0)
{
cout<<"没成功";
}
}
在这个办法中,其实更偏向于C的一些用法和思路(因为C++里有直接可以使用的类嘛,所以我就根据思路自己写出来的类stack的背后工作原理)。主要展示的是入栈(压栈),出栈操作。
第二种解决方法
第二种解决方法其实就是模仿STL中的stack类,自己写出一个stack类,并且使用它。因为会用到类,所以这个方法比上一个方法的代码体量更大。但是这个方法只有可扩展性的,即我们可以在此基础上增添操作等。
#include<iostream>
using namespace std;
template<class T>
struct Node
{
T element;
Node<T>* next;
Node(){ }
Node(T& element)
{
this->element = element;
}
Node(Node<T>* next)
{
this->next = next;
}
};
template<class T>
class stackList
{
private:
Node<T>* firstNode;
int size ;
public:
stackList(){ }
stackList(int size,Node<T>* firstNode);
bool empty();
void insertfunction(T element,Node<T>* head,Node<T>* p);
void popfunction(Node<T>* head);
~stackList(){ }
};
template<class T>
void stackList<T>::popfunction(Node<T>* head)
{
Node<char>* SearchPoint = head;
for(int j = 0;j < size-1;j++)
{
SearchPoint = SearchPoint->next;
}
cout<<"111111111111111"<<endl;
size--;
cout<<size<<endl;
SearchPoint = NULL;
delete SearchPoint;
}
template<class T>
void stackList<T>::insertfunction(T element,Node<T>* head,Node<T>* p)
{
if(size == 0)
{
head = new Node<char> ;
p = head;
p->element = element;
size++;
cout<<size<<endl;
}
else if(size != 0)
{
p->next = new Node<char>(element) ;
p = p->next;
size++;
cout<<size<<endl;
}
}
template<class T>
stackList<T>::stackList(int size,Node<T>* firstNode)
{
this->size = size;
this->firstNode = firstNode;
}
template<class T>
bool stackList<T>::empty()
{
if(size == 0)
{
return true;
}
else return false;
}
int main()
{
Node<char> *head,*p;
head = new Node<char> ;
p = head;
stackList<char> m (0,p);
char a[10];
for(int i = 0;i<10;i++)
{
cin>>a[i];
}
for(int i = 0;i<10; i++)
{
if(a[i] == '(')
{
m.insertfunction(a[i],head,p);
}
else if(a[i] == ')')
{
m.popfunction(head);
}
}
if(m.empty() == true)
{
cout<<"成功了"<<endl;
}
else if(m.empty() == false)
{
cout<<"试败了"<<endl;
}
}
下面来讲一下,这个办法的话它其实就是从上面的方法派生出来额。有一个点我在写代码的时候卡了很久。就是
template
void stackList::popfunction(Node* head)
{
Node* SearchPoint = head;
for(int j = 0;j < size-1;j++)
{
SearchPoint = SearchPoint->next;
}
cout<<“111111111111111”<<endl;
size–;
cout<<size<<endl;
SearchPoint = NULL;---------------1
delete SearchPoint;-----------------2
}
这个函数中最后如果把1和2位置调换的话,整个程序是有问题的, delete SearchPoint这一步会卡住,走不动了。后面的程序就无法执行。如果按照上述顺序则没有任何问题。这个问题我卡了很久,但是至于原因我还没有找到,只找到了解决办法。如果有小伙伴晓得原理,欢迎评论区留言哈。