基础数据结构-栈

目录

1、栈的概念:

2、链栈

2.1、入栈

2.2、出栈

2.3、查询栈顶元素

3、顺序栈

3、1入栈

3、2 出栈

3、3查询栈顶元素

4、关于栈的力扣题

4、1第一题

4、2第二题

4、3第三题


1、栈的概念:

●栈是限定仅在表尾(即栈顶)进行插入删除线性表。表尾称栈顶,表头称栈底,不含元素的空表称为空栈。栈又称为后进先出的线性表。(如果你是学过车的朋友,可以联想一下倒车入库哟~ 后进去的车头是先出来的,先进去的车屁股是后出来的,这样可能更能理解后进先出喔)

 

2、链栈

2.1、入栈

栈有两种存储表示方法,分别称为顺序栈链栈

●利用链表来模拟栈(链栈):

//-------链栈的存储结构---------
typedef int DataType;
struct StackNode;
Struct StackNode{
    DataType data;       //数据域
    struct StackNode *Next;        //指针域
};




//--------初始化---------
struct Stack{
    struct StackNode *head;    //head指向栈顶
    int size;        //栈中元素个数
};





//--------入栈-------
void StackPushStack(struct Stack *str,DataType dt){
    struct StackNode *vtx =(struct StackNode *)malloc(size(struct StackNode));
    vtx->next = stk->head;
    vtx->data = dt;
    stk->head = vtx;
    ++stk -> size;
}
//*str 为目标栈,dt为需要在目标栈(即*str)的栈顶加入的元素
//生成一个栈元素结点vtx,将vtx的后继指向当前栈(stk)的栈顶。将vtx的数据域指向dt;然后将vtx作为新的栈顶对栈中元素计数+1。

2.2、出栈

出栈=栈元素的删除

//--------出栈-----
void StackPopStack(struct Stack *str){
    struck StackNode *temp = stk -> head;
    str ->head = temp -> next;
    free(temp);
    --stk -> size;
}

//将当前的栈顶存储在temp中,将新的栈顶指向栈顶的后继,释放temp的内存,对栈中元素计数减一。

2.3、查询栈顶元素

DataType StackGetTop(struct Stack*str){
    return str ->head ->data;
}

 

3、顺序栈

3、1入栈

//------顺序栈的存储结构-------
#define MAXSIZE 100        //顺序栈存储空间的初始分配量
typedef struct
{
    SElemType *base;        //栈底指针
    SElemType *top;        //栈顶指针
    int stacksize;        //栈可用的最大容量
}SqStack;




//------初始化-------
Status InitStack (SqStack &S)
{
    S.base = new SElemType[MAXSIZE];        //为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
    if(!S.base) exit(OVERFLOW);            //存储分配失败
    S.top = S.base;                          //top初始为base,空栈
    S.stacksize = MAXSIZE;                    //stacksize置为栈的最大容量MAXSIZE
    return OK;
}



//------入栈--------
Status Push(SqStack &S,SElemType e)        //插入元素e为新的栈顶元素
{
    if(S.top-S.base==S.stacksize) return ERROR;    //栈满
    *S.top++ =e;                                    //将元素e压入栈顶,栈顶指针加1
    return OK;
}

3、2 出栈

///-------出栈--------
Status Pop(SqStack &S , SElemType &e)     //删除S的栈顶元素,用e返回其值。
{
    if(S.top == S.base)    return ERROR;     //栈空
    e = *--S.top; //先自减           //栈顶指针减1,将栈顶元素赋给e
    return OK;
}

3、3查询栈顶元素

//-------查询栈顶元素-------
SElemType GetTop(SqStack S)        //返回S的栈顶元素,不修改栈顶指针
{
    if(S.top!= S.base)            //栈非空
        return *(S.top -1);        //返回栈顶元素的值,栈顶指针不变
}

 

4、关于栈的力扣题

4、1第一题

第一题:

书店店员有一张链表形式的书单,每个节点代表一本书,节点中的值表示书的编号。为更方便整理书架,店员需要将书单倒过来排列,就可以从最后一本书开始整理,逐一将书放回到书架上。请倒序返回这个书单链表。

示例 1:

输入:head = [3,6,4,1]

输出:[1,4,6,3]

提示:

0 <= 链表长度 <= 10000

思路:题目的简单意思就是把一组数据倒过来后进行输出。然后这组数据是由链表的形式进行存储的。那么我们就可以想到“倒车入库”(后进先出)的栈。

既然要用到栈,那么我们就需要先创建一个栈。然后将链表里的元素依次存放到栈里。再把栈里的元素一个一个弹出来。

int* reversePrint(struct ListNode* head, int* returnSize){
    int *stack =(int *)malloc( sizeof(int) * 10000);        //用数组来模拟一个栈
    int top=0;        //初始化 栈顶为0
    while(head)        //遍历head,将值存入栈中
    {
        stack[top++] =head ->val;
        head = head ->next;
    }
    int *ret =(int *)malloc( sizeof(int) * 10000);    //再申请一个数组,用于弹出元素
    *returnSize =0; //数组长度
    while(top--)
    {
        ret[(*returnSize)++] =stack[top]; 
        //这行代码举个栗子就是 ret[0] = stack[3] = 1,也就是原本的3,6,4,1 被倒过来存到ret里了
    }
    free(stack);    //stack不再需要了,就把它释放掉
    return ret;        //返回倒过来后的数组
}

4、2第二题

第二题:

如果字符串满足以下条件之一,则可以称之为 有效括号字符串(valid parentheses string,可以简写为 VPS):

  • 字符串是一个空字符串 "",或者是一个不为 "(" 或 ")" 的单字符。
  • 字符串可以写为 ABA 与 B 字符串连接),其中 A 和 B 都是 有效括号字符串 。
  • 字符串可以写为 (A),其中 A 是一个 有效括号字符串 。

类似地,可以定义任何有效括号字符串 S 的 嵌套深度 depth(S)

  • depth("") = 0
  • depth(C) = 0,其中 C 是单个字符的字符串,且该字符不是 "(" 或者 ")"
  • depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是 有效括号字符串
  • depth("(" + A + ")") = 1 + depth(A),其中 A 是一个 有效括号字符串

例如:"""()()""()(()())" 都是 有效括号字符串(嵌套深度分别为 0、1、2),而 ")(" 、"(()" 都不是 有效括号字符串 。

给你一个 有效括号字符串 s,返回该字符串的 s 嵌套深度 。

示例 1:

输入:s = "(1+(2*3)+((8)/4))+1"
输出:3
解释:数字 8 在嵌套的 3 层括号中。

示例 2:

输入:s = "(1)+((2))+(((3)))"
输出:3

提示:

  • 1 <= s.length <= 100
  • s 由数字 0-9 和字符 '+''-''*''/''('')' 组成
  • 题目数据保证括号表达式 s 是 有效的括号表达式

思路:简单的理解就是它要求的是字符最多被多少个括号包围。一左一右组成一对括号,所有当左括号遇到右括号的时候就是一层包围。(((2)))看2被几层括号包围也就是看在右括号出现之前有几个左括号。完了,我们就也可以用栈计算,看看留在栈里的左括号有几个。

int maxDepth(char * s){
    //在这里我们不用定义一个栈,只需要定义一个栈顶。我们不需要给个地址存放括号,我们只是用栈的思维去解决这个问题。
    int top =0;      //栈顶
    int ret =0;        //
    for(int i=0;s[i];i++)
    {
        if(s[i]=='(')    //当S[i]=='('的时候,把它存到栈内
        {
            ++top;
            if(top>ret)
            {
                ret=top;    //记录( 的个数
            }
        }
        else if(s[i]==')')         //等于右括号的时候,从栈里放出来一个左括号
        {
            --top;
        }
    }
    return ret;     //    返回个数即可
}

4、3第三题

第三题:

给定一个链表的 头节点 head ,请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

示例 1:

输入: head = [1,2,3,3,2,1]
输出: true

示例 2:

输入: head = [1,2]
输出: false

提示:

  • 链表 L 的长度范围为 [1, 105]
  • 0 <= node.val <= 9

思路:简单的理解题目就是要让我们判断这个链表里的第一个元素和最后一元素是否相等,第二个元素和倒数第二个元素是否相等。那么我们的想法就是把链表存放到一个栈里,完了去循环判断栈顶的元素和链表的元素是否相等。


bool isPalindrome(struct ListNode* head){
    int *stack =(int *)malloc(sizeof(int) *100000);    //定义一个栈
    int top =0;    //栈顶
    struct ListNode *now =head;
    while(now)    //把元素塞到栈里
    {
        stack[top++] =now ->val;
        now =now ->next;
    }
    while(top--)  //依次判断栈顶元素与head里的元素是否相等
    {
        if(stack[top]!=head ->val)
        {
            return false;
        }
        head =head->next;
    }
    return true;
}

上诉知识和解题思路学习自书籍《数据结构》严蔚敏版 和 英雄哥的知识星球。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值