算法学习笔记——利用栈解决实际问题- part 2

本文是算法学习笔记的第二部分,主要介绍了如何利用栈解决实际问题,包括编写栈、符号最大匹配子串、寻找水王、后缀表达式、中缀表达式转后缀表达式、直方图的最大子矩形和最大子矩阵问题。通过实例和代码详细解释了每个问题的解决思路和优化方法,展示了栈在算法中的应用。
摘要由CSDN通过智能技术生成

算法学习笔记:

part1 : http://blog.csdn.net/minghe_uestc/article/details/10416809

全文下载地址见part 1

1       利用栈解决实际问题

1.1     编写一个栈

         只要符合“后入先出”规则的数据结构都可以叫做栈,所以在实现栈的时候有很多方式:

Ø  可以利用数组、链表来组织数据;

Ø  使用链表也可以使用单向链表和双向链表;

Ø  存储的元素可以是指针、基本数据类型和复杂数据类型;

Ø  可以将栈抽象成一个复杂数据类型,也可以不抽象。

C++/Java中都提供了栈的抽象。提供的这些数据结构是十分好用的,个人觉得十分推荐。

C++中,stack底层使用dqueue数据结构,即stack是对dqueue的一个简单封装。dqueue其实是几段不连续的数组经过一个统一管理器管理后抽象出来的一个双向队列,参考《STL源码剖析》,书中给出了很详细的说明。

另外需要注意的就是,使用标准模板库的时候,不要在容器中存储复杂数据类型的“值对象”,因为这会引起大量的构造与析构,也不要试图用auto_ptr对容器中的指针进行自动堆管理,因为auto_ptr不能进行值传递。所以标准容器中一般是保存基本数据类型和指针,当然一些小的复杂数据也可以保存一下。但如果保存指针,那对这些对象就需要有效的堆管理机制。

16 C++中使用标准模板库中的栈

#include<iostream>
#include<assert.h>
#include<stack>
usingnamespacestd;
typedefintItem;
intmain(){
       
    stack<Item>s;
    Itema=10;Itemb=20;
    s.push(a);
    cout<<s.top();
    s.push(b);
    cout<<s.top();
    s.pop();
    cout<<s.top();
    return0;
}

         17是使用数组实现的栈,在看网上那些恶心的算法代码的时候,他们基本选择这种方式去做。还有很多其他的实现方式,只要最后符合“后入先出”的游戏规则就可以了。

17 使用数组实现栈

typedefintItem;
#defineMAXSIZE 100
Items[MAXSIZE];
inttop=-1;
intmain(){
       
    Itema=10;
    s[++top]=a;//将元素插入栈顶
    if(top>=0)//判断栈不为空
        cout<<s[top];//查看栈顶元素
    if(top>=0)
        top--;//将栈顶元素出栈
    top=-1;//清空栈
    return0;
}

1.2     符号最大匹配子串

1.2.1  问题描述

         给定一个字符串”[[(()]]{ {[[()()]]}}”,找到最长匹配子串,返回子串的起始位置与长度。

1.2.2  解决思路

         利用一个栈进行维护所有待考察的“左符号”,栈顶元素放置的是最当前考察的“左符号”,idx表示当前需要考察的符号,这时候的情况就有:

Ø  idx指向“左符号”,则将符号压入栈,然后idx右移。

Ø  idx指向“右符号”,这时候分成两种情况

n  如果栈为空,则什么都不做,idx右移

n  如果栈不为空,则比较栈顶元素与idx指向元素,这时候又分为两种情况

u  匹配,栈顶元素推出,idx右移

u  不匹配,清空栈

根据这个思路,不难得到表 18中的代码实现:

18 求解最长匹配子串

#defineleftSymbol(x)(x=='['||x=='('||x=='{')
boolmatch(charl,charr){
       
    if(l=='['&&r==']')returntrue;
    if(l=='('&&r==')')returntrue;
    if(l=='{'&&r=='}')returntrue;
    returnfalse;
}
#defineMAXSIZE100
charsk[MAXSIZE];
inttop=-1;
voidmaxMatch(charp[]){
       
    for(intidx=0;p[idx]!='\0';idx++){
       
        if(leftSymbol(p[idx])){
       
            sk[++top]=p[idx];
            continue;
        }
        if(top>=0&&match(sk[top],p[idx])){
       
            top--;
        }else{
       
            top=-1;
        }
    }
}

         然后开始维护答案,因为需要维护最长匹配子串的起始位置,新增一个栈skidx[]用于维护所有左符号的下标,这个栈与sk[]进行同步。

然后利用两个临时变量记录临时解,对比临时解与已知解的情况来更新最终的解。

19 最长匹配子串的答案维护

structAns{
       
    intidx;intlen;
    Ans():idx(0),len(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值