线性结构 - 栈

        栈是一种后进先出的数据结构。栈限定为只能从一端进行插入和删除操作。比如一个小桶,小桶的直径只能放一个小球,我们现在小桶内依次放入2、1、3号小球。假如你现在需要拿出2号小球,那就必须先将3号小球拿出,再拿出1号小球,最后才能将2号小球拿出来。在刚才取小球的过程中,我们最先放进去的小球最后才能拿出来,最后放进去的小球却可以最先拿出来。如下图所示:


图 栈示意图

        栈的实现很简单,只需要一个一维数组和一个指向栈顶的变量top就可以了。我们通过top来对栈进行插入和删除操作。

栈中插入元素x:
	top++;
	a[top] = x;
栈中删除元素:
	top--;

    栈有哪些作用呢?我们看一个例子。“xyzyx”是一个回文字符串,所谓回文字符串就是指正读反读均相同的字符序列,如“aha”,“席主席”等均为回文,但“ahah”就不是回文。我们通过栈这个数据结构判断一个字符串是否为回文。
        首先是读取这行字符串,并求出这个字符串的长度: 
        string s;
        int len;
        cin >> s;
        len = s.size();


        如果一个字符串是回文的话,那么它必须是中间对称的,我们需要求出中点,即:
        mid = len/2 - 1; 
        接下来就轮到栈登场了。
        我们先将mid之前的字符全部入栈。因为这里的栈是用来存储字符的,所以这里实现栈的数组类型是字符串s。初始化栈很容易: top=0;
        下面我们就将mid之前的字符全部入栈:
        for(i=0; i<=mid; i++){
                s[++top] = a[i];
        }

        接下来进入判断回文的关键步骤。将当前栈中的字符依次出栈,看看是否能与mid之后的字符一一匹配,如果都能匹配就是回文字符串,否则就不是回文字符串。
        for(i=mid+1; i<=len-1; i++){
                if (a[i]!=s[top]) break; 
                top--
        }
        if (top==0) cout << "YES\n";
        else cout << "NO\n";

    最后如果top的值为0,说明栈内所有的字符都被一一匹配了,那么这个字符串就是回文字符串。



【程序1】回文字符串 (用栈实现)

        输入一个字符串(长度≤10^5),判断是不是回文字符串。如果是回文字符串,输出“yes”,否则输出 “no”。 
        【样例输入】121
        【样例输出】yes

整个代码实现如下:

#include <iostream>
using namespace std;
int main(){
	string s;
	char a[1001];
	cin >> s;   //读入一行字符串
	int len = s.size();  //求字符串的长度 
	int mid = len/2-1;   //求字符串的中点 
	int top = 0, next;
	for(int i=0; i<=mid; i++) a[++top] = s[i];   //将mid前的字符依次入栈 
        //判断字符串的长度为奇数还是偶数,并找出需要进行匹配的初始下标 
	if(len%2==0) next = mid+1; 
	else next = mid+2;
	for(int i=next; i<=len-1; i++){   //开始匹配 
		if(s[i]!=a[top]) break;
		top--;
	}
	if(top==0) cout << "yes"; else cout << "no";
	return 0;
}



【程序2】括号匹配 

        给定一个算术表达式,检查其中的圆括号是否配对,给出适当信息(正好:Yes,左括号多:Left,右括号多:Right)。如果有多处不配对的情况,给出最早发生不配对时候的信息,例如:表达式())(,最早发生的不配对是在第三个字符())处,故输出Right。 
        【样例输入】3*(4-5)+9/2
        【样例输出】Yes

整个代码实现如下:

#include <iostream>
using namespace std;
int main(){
	string s;
	cin >> s;
	int top=0;
	for(int i=0; i<=s.size(); i++){
		if (s[i]=='(') top++;  //如果是左括号,进栈 
		if (s[i]==')') top--;  //如果是右括号,出栈 
		if (top<0) break;
	}
	if (top==0)  cout << "Yes\n";
	  else if (top>0) cout << "Left\n";
		 else cout << "Right\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]提供了一个朴素的解法,使用两个来存储字符串,一个用来存储普通字符,另一个用来存储特殊字符。遍历字符串,如果是普通字符则压入第一个,如果是特殊字符则弹出第一个顶元素。最后比较两个是否相同即可判断字符串是否有效。这个解法的时间复杂度是O(M + N),空间复杂度也是O(M + N)。\[1\] 引用\[2\]提供了另一个的应用场景,即判断括号是否有效。遍历字符串,如果是左括号则压入,如果是右括号则判断和顶元素是否匹配,不匹配则返回false,匹配则弹出顶元素。最后判断是否为空即可判断括号是否有效。\[2\] 引用\[3\]也提供了一个判断括号是否有效的解法,使用来操作。遍历字符串,如果是左括号则压入,如果是右括号则判断和顶元素是否匹配,不匹配则返回false,匹配则弹出顶元素。最后判断是否为空即可判断括号是否有效。这个解法使用了HashMap来存储括号的对应关系。\[3\] 综上所述,在解决字符串相关问题中有着广泛的应用,包括判断字符串是否有效、逆波兰表达式等。在解决这些问题时,可以帮助我们保存和处理字符的顺序,从而简化问题的处理过程。 #### 引用[.reference_title] - *1* *3* [Leetcode刷题03-](https://blog.csdn.net/weixin_47802917/article/details/123007699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] - *2* [leetCode-类型详解](https://blog.csdn.net/zhiyikeji/article/details/125508011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值