C++栈介绍
文章目录
提示:相关内容参考自《数据结构与算法分析c++描述》此书。(ps:书图书馆随便借来参阅的无任何种草含义)
一、栈模型
栈(stack)是限制插入和删除操作只能在一个位置上进行的表,该位置是表的末端,称为栈的顶。对栈的基本操作是push(进栈)和pop(出栈),前者相当于插入,后者则是删除最后插入的元素。
栈有时候又被称之为LIFO(后进先出)表,且由于栈是一个表,因此任何实现表的方法都可以实现栈。我们可以利用List和vector实现栈。(栈是一种ADT(抽象数据结构),但是和list和vector不同的是,它需要借助上述二者实现)
二、栈使用
注:由于c++的STL中提供了stack容器,因此在本文中直接使用stack容器实现相关的栈功能。
1.常见的函数接口
#include<stack> //头文件
stack<int> testStack; //定义一个类型为int名为testStack的栈,
//相关函数如下
testStack.empty(); //如果栈为空则返回true, 否则返回false;
testStack.size(); //返回栈中元素的个数
testStack.top(); //返回栈顶元素, 但不删除该元素
testStack.pop(); //弹出栈顶元素, 但不返回其值
testStack.push(XX); //将元素XX压入栈顶
2.代码实现
1)简单程序(直接利用STL中自带的Stack实现栈操作)
代码如下(示例):
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main()
{
stack<int> testStack;
int a[5] = { 1,2,3,4,5 };
vector<int> testVector(a, a + 5); //vector的一种定义方式,此时testVector的对应元素与aa相同
for (int i = 0; i < testVector.size(); i++) {
testStack.push(testVector[i]);
}
cout << "size is " << testStack.size() << endl;
cout << "the top number:" << testStack.top() << endl;
while (testStack.empty()!=true) {
cout << " " << testStack.top();
testStack.pop();
}
cout << endl;
system("pause");
return 0;
}
输出:
2)进阶程序(leetcode实战训练)
题目:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。(需要成对出现)
左括号必须以正确的顺序闭合。(即只能是{[()]},不能是({[]})或者其他违背大中小括号使用的情况)
并且空字符串可被认为是有效字符串。
说明:此题花了很长时间去解,简单思路无法面面俱到总有一些情况会遗漏,看了题解才豁然开朗,接下来代码实现一种解法(常用解法中有用到哈希表,学到哈希表后可以再次尝试解这道题。)
class Solution {
public:
bool isValid(string s) {
//先把字符串元素入栈,若是左括号则入栈正确退出此次循环
//若不是左括号则判断此时栈大小,小于2则代表此时栈中这个不是左括号的字符,说明原字符串不符合题意返回false
//不是左括号且栈的大小不小于2则继续判断此右括号是否在栈中存在对称的左括号
//ch2代表最后入栈的右括号,ch1为栈顶下面的一个字符
//判断是否存在对称的括号
//核心思想:无论括号怎么排列,若要满足题意,字符串数组中必然至少存在一对括号其中间没有任何其他括号,如{[()]},中间有()
//()中没有其他的括号,因此当我们把()剔除后[]就可以成对了
//一步步下来就可以判断整体的情况了
stack<char> testStack;
char ch1,ch2;
for(int i=0;i<s.size();i++)
{
testStack.push(s[i]);
if(s[i]=='(' || s[i]=='[' || s[i]=='{')
{
continue;
}
if(testStack.size() < 2) return false;
ch2 = testStack.top(), testStack.pop(), ch1 = testStack.top(), testStack.pop();
if(ch1 == '(' && ch2 == ')') continue;
if(ch1 == '{' && ch2 == '}') continue;
if(ch1 == '[' && ch2 == ']') continue;
return false;
}
if(testStack.empty()) return true;
else return false;
}
};
3)更低层的栈实现
1.leetcode中的简单题(利用vector实现)
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
class MinStack {
public:
/** initialize your data structure here. */
/** 利用vector实现栈的相关功能 **/
MinStack() {
Stack.resize(0);
}
void push(int x) {
Stack.push_back(x);
}
void pop() {
Stack.pop_back();
}
int top() {
return Stack[Stack.size()-1];
}
int getMin() {
int temp=0x7fffffff;;
for(int i=0;i<=Stack.size()-1;i++)
{
if(temp>=Stack[i])
{
temp=Stack[i];
}
}
return temp;
}
private:
vector<int> Stack;
};
/**
* Your MinStack object will be instantiated(举例) and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
2.其他实现方法(更低层,也更详细)
template<class T>
class stackNode
{
public:
stackNode() :next(NULL) {}
T data;//值
stackNode* next;//指向下一个节点的指针
};
template<class T>
class mystack
{
private:
unsigned int stacklength;
stackNode<T>* node;//临时节点
stackNode<T>* headnode;//尾结点
public:
mystack();//初始化
unsigned int length();//栈元素的个数
void push(T x);//入栈
bool isEmpty();//判断栈是否为空
void pop();//出栈
T top();//获得栈顶元素
void clear();//清空栈
};
template<class T>
mystack<T>::mystack()
{
node = NULL;
headnode = NULL;
stacklength = 0;
}
template<class T>
inline unsigned int mystack<T>::length() { return stacklength; }
template<class T>
void mystack<T>::push(T x)
{
node = new stackNode<T>();
node->data = x;
node->next = headnode;//把node变成头节点
headnode = node;
++stacklength;
}
template<class T>
bool mystack<T>::isEmpty()
{
return stacklength == 0;
}
template<class T>
void mystack<T>::pop()
{
if (isEmpty()) return;
node = headnode;
headnode = headnode->next;//头节点变成它的下一个节点
delete(node);//删除头节点
--stacklength;
}
template<class T>
T mystack<T>::top()
{
if (!isEmpty())
return headnode->data;
}
template<class T>
void mystack<T>::clear()
{
while (headnode != NULL)
{
node = headnode;
headnode = headnode->next;
delete(node);
}
node = NULL;
headnode = NULL;
stacklength = 0;
}
总结
简单学习了栈,明天看队列,每一种ADT中都有着其不同的应用场景,想要精通还有很长一段路要走,加油,读书人!