一,栈的基本定义
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
1、栈的操作
栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。(1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
(2)当表中没有元素时称为空栈。
(3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。
2,栈的示图
元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…,a1。
二,数组实现栈(C++模板)
1,stack.h的实现:
#include "iostream"
#include "windows.h"
using namespace std;
template<typename DataType>
class MyStack
{
public:
MyStack(int size)
{
maxSize = size; //设置最大容量
top = -1; //初始化为空栈
elements = new DataType[size]; //动态分配连续的数组空间,共size个数据
for (int i=0;i<maxSize;i++)
{
elements[i]=0;
}
}
~MyStack()
{
if (elements!=NULL)
{
delete[] elements;
elements=NULL;
}
}
//入栈操作
bool push(DataType data);
//出栈操作
DataType pop();
//判断栈是否为空
bool IsEmpty();
//获取元素个数
int GetNums();
//摧毁栈
void DestroyStack();
//求取栈中的最小值
DataType Min();
//求取栈中的最大值
DataType Max();
private:
DataType *elements; //数据域指针
int top; //栈顶,top=0,就表示有一个数据了
int maxSize; //栈的最大容量
};
/*****************入栈操作************************/
template<typename DataType>
bool MyStack<DataType>::push(DataType data)
{
if((top+1) == maxSize) //入栈前一定要先判断是否栈满
{
cout<<"已经满栈!此时栈顶为"<<data<<endl;
return false;
}
else
{
top++;
elements[top] = data; //从栈顶压入元素,并且top加一
}
return true;
}
/********************出栈操作(去元素)*******************/
template<typename DataType>
DataType MyStack<DataType>::pop()
{
if(IsEmpty()) //判断是否栈空
{
cerr<<"栈为空,注意检查"<<endl;
exit(1);
}
else
{
return elements[top--]; //返回当前栈顶元素,随后top减一
//top--;
}
}
/*************************栈判断是否空***********************/
template<typename DataType>
bool MyStack<DataType>::IsEmpty()
{
if(top == -1)
return true;
else
return false;
}
/*********************获取当前元素个数数********************/
template<typename DataType>
int MyStack<DataType>::GetNums()
{
if(top >= 0)
return top+1;
else
return 0;
}
template<typename DataType>
void MyStack<DataType>::DestroyStack()
{
maxSize = 0; //设置最大容量
top = 0; //初始化为空栈
delete[] elements ; //动态分配连续的数组空间,共size个数据
elements=NULL;
}
template<typename DataType>
DataType MyStack<DataType>::Min()//直接遍历的方法求最小值(或者最大值)
{
DataType temp=elements[0];
for (int i = 1;i < top+1;i++)
{
if (elements[i] < temp)
{
temp=elements[i];
}
}
return temp;
}
template<typename DataType>
DataType MyStack<DataType>::Max()
{
DataType temp=elements[0];
for (int i = 1;i < top+1;i++)
{
if (elements[i] > temp)
{
temp=elements[i];
}
}
return temp;
}
2,主测试代码:
// ConsoleAppStack.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Stack.h"
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//首先按顺序入栈
MyStack<int> s = MyStack<int>(10); //创建栈结构,这个栈可以容纳10个元素
//入栈
s.push(10);
s.push(15);
s.push(1);
s.push(6);
s.push(45);
s.push(9);
s.push(35);
cout<<"当前栈中元素个数为: "<<s.GetNums()<<endl;
int temp = s.pop();
cout<<"栈顶元素出栈: "<<temp<<endl;
cout<<"当前栈中元素个数为: "<<s.GetNums()<<endl;
cout<<"栈的最小值"<<s.Min()<<endl;
cout<<"栈的最大值"<<s.Max()<<endl;
s.DestroyStack();
cout<<"栈已经摧毁!"<<endl;
system("pause");
return 0;
}
3,测试结果:
三,链表实现栈(C++模板)
1,StackLink.h的实现:
#include "stdafx.h"
#include "iostream"
using namespace std;
template<class DataType> class Stack;
template<class DataType>
class LinkNode
{
public:
LinkNode()
{
next=NULL;
nData=0;
}
LinkNode(DataType newData)
{
next=NULL;
nData=newData;
}
~LinkNode()
{
}
private:
friend class Stack<DataType>;
LinkNode<DataType> *next;
DataType nData;
};
template<class DataType>
class Stack
{
public:
Stack(int size)
{
top=NULL;
count=0;
maxSize=size;
}
~Stack()
{
int len=getNum();
for ( int i=0;i< len;i++)
{
LinkNode<DataType> *p=top;
top=p->next;
delete p;
}
}
int getNum()
{
return count;
}
//进栈
bool InsertNode(DataType newData);
//出栈
bool outNode();
private:
LinkNode<DataType> *top;
int count;
int maxSize;
};
template<class DataType>
bool Stack<DataType>::InsertNode(DataType newData)
{
if (getNum() == maxSize)
{
cerr<<"栈已经满,请勿再进行插入操作!"<<endl;
return false;
}else
{
LinkNode<DataType> *newNode=new LinkNode<DataType>(newData);
if (top == NULL)
{
top=newNode;
count++;
return true;
}else
{
newNode->next=top;
top=newNode;
count++;
return true;
}
}
}
template<class DataType>
bool Stack<DataType>::outNode()
{
if (getNum() == 0)
{
cerr<<"数据已经全部出栈,请勿再继续操作!"<<endl;
return false;
}
else
{
LinkNode<DataType> *p=top;
cout<<"当前出栈数据为"<<p->nData<<endl;
top=p->next;
delete p;
count--;
return true;
}
}
2,主测试代码如下:
// ConsoleAppStackList.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "StackList.h"
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int len=10;
Stack<char> S(len);
char str='A';
for (int i = 0;i < len;i++)
{
S.InsertNode(str++);
}
cout<<"当前栈中数据个数为:"<<S.getNum()<<endl;
cout<<"--------------栈初始化已经完成---------------"<<endl;
for (int j=0; j<11;j++)
{
if (S.getNum() == 0)
{
cerr<<"数据已经全部出栈,操作即将停止!"<<endl;
break;
}
S.outNode();
}
system("pause");
return 0;
}
3,测试结果:
四,小试牛刀
1,括号匹配问题
-
题目描述:
-
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.
-
输入:
-
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
注意:cin.getline(str,100)最多只能输入99个字符!
-
输出:
-
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。
-
样例输入:
-
)(rttyy())sss)(
-
样例输出:
-
)(rttyy())sss)( ? ?$
#include "iostream"
#include "string"
#include "stack"
using namespace std;
void BracketMatch(const string srcStr);
int main()
{
string str;
while (cin >> str)
{
cout << str << endl;
BracketMatch(str);
}
return 0;
}
void BracketMatch(const string srcStr)
{
stack<int> s;
string ansStr(srcStr.length(),'0');
for (unsigned int i = 0; i < srcStr.length(); i++)//从左往右开始遍历
{
if (isalpha(srcStr[i]))
{
ansStr[i]=' ';
continue;
}
switch (srcStr[i])
{
//对左括号仅作压栈处理,也就是说栈中只可能是左括号
case '(':
if (i != (srcStr.length() - 1))//当是最后一个字符时已经没有必要输出空格了
ansStr[i] = ' ';
s.push(i);//注意,这里
break;
//对右括号做匹配判断
case ')':
if (!s.empty())
{//如果不为空,说明一定有左括号(实际上是其数组下标)
s.pop();
ansStr[i] = ' ';
}
else//如果为空
ansStr[i] = '?';
break;
default:
cerr << "错误的括号" << endl;
}
}
while (!s.empty())
{ //解决多余的左括号
ansStr[s.top()] = '$';
s.pop();
}
cout << ansStr << endl;
}
注:
本文部分文字学习并copy自网络,代码参考并改编自《算法导论》.
如果侵犯了您的版权,请联系本人tangyibiao520@163.com,本人将及时编辑掉!
参考资源:
【1】《百度文库》【2】《算法导论》