C++栈学习笔记

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中都有着其不同的应用场景,想要精通还有很长一段路要走,加油,读书人!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值