求个小算法,关于括号的⋯⋯

咸清 2011-10-11 06:10:51
有一个表达式,类似:1+(((((3-5))+((2)))))+2
改为:1+((3-5)+2)+2
...全文
999 69 打赏 收藏 转发到动态 举报
写回复
用AI写文章
69 条回复
切换为时间正序
请发表友善的回复…
发表回复
MoXiaopeng 2011-10-15
  • 打赏
  • 举报
回复
楼上的各位怎么把代码的格式保留,我的缩进全不见了
MoXiaopeng 2011-10-15
  • 打赏
  • 举报
回复
来晚了,还有分不?C++代码如下:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
bool IsOperation(char c)
{
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
{
return true;
}
break;
}
return false;
}
template<typename T>
T StackPop(stack<T> &s)
{
T t=s.top();
s.pop();
return t;
}
void ConvertExp(stack<char> &stackOperation,stack<std::string> &stackNum,bool bAddBracket)
{
if(stackOperation.empty()||stackNum.empty())
return;
char cOper=StackPop(stackOperation);
if(cOper=='(')
return;
string strNumB=StackPop(stackNum);
string strNumA=StackPop(stackNum);
char szExp[256];
if(!bAddBracket)
{
sprintf(szExp,"%s%c%s",strNumA.c_str(),cOper,strNumB.c_str());
}
else
{
sprintf(szExp,"(%s%c%s)",strNumA.c_str(),cOper,strNumB.c_str());
}
stackNum.push(szExp);
}
std::string ReduceBracket(const string &str)
{
stack<string> stackNum;
stack<char> stackOperation;
for(unsigned i=0;i<str.length();i++)
{
if(IsOperation(str[i]))
{
if(str[i]==')')
{
ConvertExp(stackOperation,stackNum,true);
}
else
{
stackOperation.push(str[i]);
}
}
else if(isdigit(str[i]))
{
std::string strNum;
do
{
strNum+=str[i++];
}while(isdigit(str[i]));
--i;//不是数字,回退一个字符
stackNum.push(strNum);
}
}
while(!stackOperation.empty())
{
ConvertExp(stackOperation,stackNum,false);
}
return StackPop(stackNum);
}
int main()
{
string str="1+(((((3-5))+((2)))))+2";
cout<<ReduceBracket(str)<<endl;
//运行结果:1+((3-5)+2)+2;
return 0;
}
wantalcs 2011-10-13
  • 打赏
  • 举报
回复
算法并不难,只要连续两个左括号的右边出现两个连续两个右括号,就去一层括号。如果用正则表达式工具,实现起来也不难。
另外,楼主问题有笔误,1+(((((3-5))+((2)))))+2去掉连续括号的结果是1+(3-5)+(2)+2,而不是1+((3-5)+2)+2
下面是C#代码:


string RemoveParenthesis(string pamam)
{
string result = pamam;
while (Regex.IsMatch(result, @"\(\(.+?\)\)"))
{
Match match = Regex.Match(result, @"\((\(.+?\))\)");
result = result.Replace(match.Groups[0].Value, match.Groups[1].Value);
}
return result;
}

string str = "1+(((((3-5))+((2)))))+2";
string result = RemoveParenthesis(str);
//result为:1+(3-5)+(2)+2

wjlazio 2011-10-13
  • 打赏
  • 举报
回复
看看,学习了。。。。
lixiaolongxuexi 2011-10-13
  • 打赏
  • 举报
回复
顶顶顶....
值得学习啊!
无·法 2011-10-13
  • 打赏
  • 举报
回复
[Quote=引用 65 楼 wallescai 的回复:]

用字符串解析的话, 从左到右扫描, 计数 "(" 就加一, 然后遇到一个 ")"就减一,这是判断括号是否成对.

然后从每一个")"左面的位置开始向左侧扫描, 一个"(",就将"()"之间的整段字符串用特殊字符替换.
当整段字符串统统替换完毕之后即可以将替换后的字符串中的所有"("和")"都去除.
然后再将字符串中的特殊替换字符替换回去.

代码不会太复杂.
[/Quote]我的那个函数就是用的这个方法,参考57楼的最终版。
熊孩子开学喽 2011-10-13
  • 打赏
  • 举报
回复
用字符串解析的话, 从左到右扫描, 计数 "(" 就加一, 然后遇到一个 ")"就减一,这是判断括号是否成对.

然后从每一个")"左面的位置开始向左侧扫描, 一个"(",就将"()"之间的整段字符串用特殊字符替换.
当整段字符串统统替换完毕之后即可以将替换后的字符串中的所有"("和")"都去除.
然后再将字符串中的特殊替换字符替换回去.

代码不会太复杂.

嗷嗷叫的老马 2011-10-13
  • 打赏
  • 举报
回复
算法啊,头痛...........
咸清 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 sysdzw 的回复:]
不过对于93*(-4)*599就处理成了93*-4*599,不知道在你看来是否合法
[/Quote]
最好保留那个括号


贝隆 2011-10-12
  • 打赏
  • 举报
回复
无·法 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 sysdzw 的回复:]

引用 43 楼 ybh37 的回复:

s = "1889/((((845-59)+((4999)()×((93(-)599)())+((62))())÷62))+666662)"
能验证通过吗?
那就用正则预先处理一遍吧,只能做到删除空括号和删除类似于“(非表达式)”这样的。

'此代码由“正则测试工具 v1.1.35”自动生成,请直接调用TestReg过程
VB code
……
[/Quote]发现正则表达式也是可以将空括号、括号里是一个数字、括号里是可以带正负的数字这几个情况统一起来的,用不着两个|,修改后为:
\(([\+\-]?\d*?)\)

1889/((((845-59)+((4999)+(-2)×((93(-)599)())+((62))())÷62))+666662) 通过正则处理后为:
1889/((((845-59)+(4999+-2×((93-599))+62)÷62))+666662)
无·法 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 43 楼 ybh37 的回复:]

s = "1889/((((845-59)+((4999)()×((93(-)599)())+((62))())÷62))+666662)"
能验证通过吗?
[/Quote]那就用正则预先处理一遍吧,只能做到删除空括号和删除类似于“(非表达式)”这样的。

'此代码由“正则测试工具 v1.1.35”自动生成,请直接调用TestReg过程
Private Sub TestReg()
Dim strData As String
Dim reg As Object

strData = "1889/((((845-59)+((4999)()×((93(-)599)())+((62))())÷62))+666662)"

Set reg = CreateObject("vbscript.regExp")
reg.Global = True
reg.Pattern = "\((.?|\d+)\)"

Do While reg.Execute(strData).Count > 0
strData = reg.Replace(strData, "$1")
Loop
Debug.Print strData
End Sub
输出:
1889/((((845-59)+(4999×((93-599))+62)÷62))+666662)

如果要支持(-22)这样的那么请将正则表达式改为:
\((.?|\d+|[\+\-*/]\d+)\)


不过对于93*(-4)*599就处理成了93*-4*599,不知道在你看来是否合法

咸清 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 lxq19851204 的回复:]

跟sysdzw和神马提个意见哈:
用FOR循环,括号数的实际个数<=字符串乘除的个数.
1/(8-5+(4×(3-5)+2)÷2+2)
另外(-1)的话也要应该考虑进去。
哈哈,增加你们的麻烦~~
[/Quote]好人
咸清 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 sysdzw 的回复:]

引用 41 楼 ybh37 的回复:

堪称经典
以后招聘,我就出这道题。我看几个能做出来
HR大人,什么时候招聘通知一声。
[/Quote]
给不起工资⋯⋯

我终于明白了⋯⋯
看懂了⋯⋯
lxq19851204 2011-10-12
  • 打赏
  • 举报
回复
跟sysdzw和神马提个意见哈:
用FOR循环,括号数的实际个数<=字符串乘除的个数.
1/(8-5+(4×(3-5)+2)÷2+2)
另外(-1)的话也要应该考虑进去。
哈哈,增加你们的麻烦~~
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 ybh37 的回复:]
堪称经典
以后招聘,我就出这道题。我看几个能做出来
[/Quote]你白啊,人家一下就搜到了。哈哈
咸清 2011-10-12
  • 打赏
  • 举报
回复
s = "1889/((((845-59)+((4999)()×((93(-)599)())+((62))())÷62))+666662)"
能验证通过吗?
无·法 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 ybh37 的回复:]

堪称经典
以后招聘,我就出这道题。我看几个能做出来
[/Quote]HR大人,什么时候招聘通知一声。
咸清 2011-10-12
  • 打赏
  • 举报
回复
堪称经典
以后招聘,我就出这道题。我看几个能做出来
无·法 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 sysdzw 的回复:]

引用 35 楼 yiguangqiang88 的回复:

VB code
Option Explicit

Private Sub Form_Load()
Dim s As String, a(255) As String, i As Integer, sTmp As String, sFind As String
s = "1/(((((8-5)+((4)()×((3(-)5)(……
[/Quote]晕,楼上的代码被误删了一行for语句,重发下,final release版
Private Sub Form_Load()
Dim s$, i%, isContinue As Boolean, i1%, i2%
s = "1/((((8-5)+((4)()×((3(-)5)())+((2))())÷2))+2)"
Do
isContinue = False
For i = 1 To Len(s)
If Mid(s, i, 1) = "(" Then
i1 = getMatch(s, i)
i2 = IIf(Mid(s, i + 1, 1) = "(", getMatch(s, i + 1), i1)
If i1 - i2 = 1 Or i2 - i <= 2 Then
s = Left(s, i - 1) & Mid(s, i + 1, i2 - i - 1) & Mid(s, i2 + 1)
isContinue = True
End If
End If
Next
Loop Until Not isContinue
Debug.Print s
End Sub
'得到匹配的括号的位置
Private Function getMatch(strKey$, intPos%) As Integer
Dim i%, intLCount%, intRCount%
For i = intPos To Len(strKey)
If Mid(strKey, i, 1) = "(" Then
intLCount = intLCount + 1
ElseIf Mid(strKey, i, 1) = ")" Then
intRCount = intRCount + 1
If intRCount = intLCount Then
getMatch = i
Exit Function
End If
End If
Next
End Function
加载更多回复(49)

7,764

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧