出入栈简述

Posted 滴水穿石不是靠力,而是因为不舍昼夜。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了出入栈简述相关的知识,希望对你有一定的参考价值。

  

def greet(name):
    print(f\'hello name !\')
    greet2(name)
    print(f\'getting read to say bey...\')
    bey()

def greet2(name):
    print(f\'How are you, name\')
def bey():
    print(\'Ok bey\')

greet(\'旺财\')
\'\'\' 
greet(\'旺财\') 执行过程
首先调用 greet 函数,入参 name = \'旺财\', 
greet 函数和临时变量 name = \'旺财\' 被压入栈,此时栈顶是 greet函数
执行 greet 函数的 print 语句:print(f\'hello name !\')
接下来 直接调用 greet2 函数,入参 name = \'旺财\'
此时栈顶位置是 greet2,greet 位于次栈顶位置
注意此时 greet 函数并未执行完毕,而是处于暂停状态
当 greet2 函数执行完毕后,greet2 出栈,栈顶现在是 greet,greet 函数继续执行下一条指令
bey()  函数开始执行,此时栈顶是 bey ,greet 再次回归 次栈顶位置
当 bey 函数执行完内部的打印语句后, 执行完毕后,bey 从栈顶弹出,greet 函数回到栈顶执行
greet 完成执行,greet 也被弹出栈顶
\'\'\'

 

[剑指offer] 第二层

栈的压入与弹栈序列

题目描述:


回顾栈的基本结构:

栈的结构是先进后出,后进先出


入栈序列:[1,2,3,4,5] 出栈序列[4,5,3,2,1],否属于同一个栈出入序列?
提示 :入栈中可能有元素可能会栈


思路:

  • 用一个栈模拟实现入栈,且在入栈时和出栈序列比较是否该元素提前出栈

代码:

    bool IsPopOrder(vector<int> pushV,vector<int> popV)
    
        if(pushV.size()==0&&popV.size()==0)//特殊情况
        
            return false;
        
        int push_index=0,pop_index=0;
        while(push_index<pushV.size())//当入栈序列没有还有元素那么就该出结果了,因为模拟栈和出栈序列如果对不上就说明为假
        
            st.push(pushV[push_index++]);
            while(!st.empty()&&st.top()==popV[pop_index])//注意,一直相等出栈可能stack空导致越界访问
            
                st.pop();
                pop_index++;
            
        
        return st.empty();//空代表完全符合
    
    
private:
    stack<int>st;
;


链表的合并

题目描述:


思路:

  • 归并比较大小插入法

新开辟一个链表当作容器,在依次比较较小的值插入链表中

代码:

  ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    
        
        
         //特殊情况
        if(pHead1==nullptr)
        
            return pHead2;
        
        if(pHead2==nullptr)
        
            return pHead1;
        

        //开辟一个新的链表当作容器,带头链表(哨兵位置)
        ListNode* ret=new ListNode(0);
        ListNode* NewHead=ret;
        
        while(pHead1&&pHead2)//比较大小需要俩个链表有值才可以
        
        
            if(pHead1->val<pHead2->val)//链表1小于链表2
               
                   ret->next=pHead1;
                   pHead1=pHead1->next;
                   ret=ret->next;
               
            else//链表2小于链表1
            
                   ret->next=pHead2;
                   pHead2=pHead2->next;
                   ret=ret->next;
                        
        
 
        //特殊情况      
        if(pHead1)//当链表2全部节点插入容器时链表1还有元素
        
            ret->next=pHead1;
        
        if(pHead2)//反之
        
            ret->next=pHead2;
       
       
        return NewHead->next;//返回链表
    

哨兵位,带头链表的补充说明与解释

这个一个节点不算这个链表中得元素,他的作用就是方便删一个节点的元素,你就可以看作老鹰捉小鸡这个游戏中的老母鸡



二叉搜索树的后序遍历序列

题目描述:


知识补给:

二叉搜索树
左子树永远大于根节点,右子树永远都大于根节点
如图所示:



后续遍历:
左子树 右子树 根 上述图中的二叉搜索树的后续遍历为:
1->3->2->6->9->7->5


思路:

在知识补给中可以看到二叉搜索树的特点就是左子树比根节点大右子树比根节点大,那么我们只需要找到根在去判断左子树是不是比根节点小,右子树是不是比根节点大

那么现在就有一个问题就是如何找根呢?


依旧是知识补给中,后续遍历是先遍历左子树,在是右子树,然后是根,那么后续遍历最后一个节点就是这棵树的根(如果疑惑前看知识补给或这篇二叉树基础)



代码实现:

主逻辑

    bool VerifySquenceOfBST(vector<int> sequence) 
    
        
        if(sequence.empty())//特殊处理,小心有诈
        
            return false;
                
        
         return VerifySquenceOfBSTHelp(sequence,0,sequence.size()-1);//递归开始判断
    

判断部分

    bool VerifySquenceOfBSTHelp(vector<int>& sq,int start,int end)
    
        if(start>=end)//当你只有一个与元素的时候就说明了没有元素需要在比判断了
        
            return true;
        
        
        int root=sq[end];//序列最后一个元素为根
        
        //划分区间
        int i; 
        for(i =start; i<end;i++)//end为根所以少比一次
        
            if(sq[i]>root)//如果比根大就说明了i这个位置已经是右子树了
            
                break;
            
        
        
        for(int j =i;j<end;j++)//右子树
        
            if(sq[j]<root)//如果在右子树区间中有一个节点小于根那么就不是一个二叉搜索树树
            
                return false;   
            
        
        
        
        //递归
        return  VerifySquenceOfBSTHelp(sq, , )&&VerifySquenceOfBSTHelp(sq, , )    
    

区间分析

第一次遍历:

左子树 start

从第一次遍历中可以看出左子树的start还是这个序列的起始位置也就是当前节点的start

左子树end

从第一次遍历中可以发现左子树的end就是在i的前一个位置,那么左子树end 就是 i-1

右子树start

从第一次遍历中可以发现右子树的start 其实就是 i 当下的位置 所以 左子树的start 为 i

右子树end

第一次遍历之后那么当前的根节点对我们来说已经没有用了,所以右子树的end就是当前end-1

return  VerifySquenceOfBSTHelp(sq,start ,i-1 )&&VerifySquenceOfBSTHelp(sq,i ,end-1 );


题目链接

第一题
第二题
第三题



唠唠家常

最近天气有点冷呀,大家注意保暖,今天刚好是2022年1月1日,祝大家新年快乐,新年新气象,改掉上能的坏习惯,保留上年的好习惯

以上是关于出入栈简述的主要内容,如果未能解决你的问题,请参考以下文章

如何用栈实现队列

[剑指offer] 第二层

[剑指offer] 第二层

栈和队列知识点总结

数据结构复习--栈

(转)UCOSII在任务切换与出入中断时堆栈指针的使用