【括号匹配&洛谷&进制转换】栈的实战,包教包会

简介: 【括号匹配&洛谷&进制转换】栈的实战,包教包会

题目描述:


ae41027fa14e483ca2c95ca88891ed94.png

解题思路;


本题因为只用判断左右的()括号,如果遇到左括号就让他直接入栈,如果遇到右括号,则判断栈是否为空,如果栈为空,就说明右括号多余,扩号不匹配,;在所有字符都判断结束后,判断栈是否为空,如果栈不为空,那么就说明栈内还有左括号,左括号多余,括号不匹配。


解题步骤;


1.初始化一个栈


2.读取一个字符,如果ch!='@',则执行第三步,否则转向执行第五步


3.如果ch='(',入栈


4.如果ch=')',判断栈是否为空,不为空则让'('出栈,为空则括号不匹配


5.读完所有的字符后,判断栈是否为空,不为空则括号不匹配,为空则括号匹配


代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Stack
{
  char* a;
  int top;
  int capacity;
}Stack;
void StackInit(Stack* ps)
{
  ps->a = (char*)malloc(sizeof(char)*4);
  if (ps->a == NULL)
  {
    printf("malloc fail\n");
    exit(-1);
  }
  ps->capacity = 4;
  ps->top = 0;//ps->top初始化为0
}
void StackPush(Stack* ps,char ch)
{
    //判断是否要扩容
  if (ps->top == ps->capacity)
  {
    int newcapacity = ps->capacity * 2;
    char* temp = realloc(ps->a, sizeof(char)*newcapacity);
    if (temp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);
    }
    else
    {
      ps->capacity = newcapacity;
      ps->a = temp;
    }
  }
   //以上为判断是否要扩容并完成扩容
   //入栈
  ps->a[ps->top] = ch;
  ps->top++;
}
int StackIsEmpty(Stack* ps)
{
  return ps->top == 0;//空为真,返回1
}
void StackPop(Stack* ps)
{
    assert(!StackIsEmpty());
  ps->top--;//出栈
}
int main()
{
  char ch = 0;
  Stack ST;
   //初始化栈
  StackInit(&ST);
    //循环读入字符,不用再加一个getchar清理缓冲区,因为最后的回车时已经退出循环
  while ((ch=getchar())!='@')
  {
    //当遇到左括号
    if (ch == '(') StackPush(&ST, ch);
        //当遇到右括号
    else if(ch == ')')
    {
      if (StackIsEmpty(&ST)==0)//不为空
      {
        StackPop(&ST);
      }
      else
      {
        printf("NO\n");
        return 0;
      }
    }
  }
//ch=='@'退出循环
  if (StackIsEmpty(&ST))
  {
    printf("YES\n");
  }
  else
  {
    printf("NO\n");
  }
  return 0;
}

运行结果:026b49d6bcb94470939ebea4fe258483.png

我想说:


1.要明白右括号多余是没有左括号和他匹配了,也就是栈空了,判断的是另一个括号有没有;而左括号多余是没有右括号和他匹配,但是判断的是左括号自己有没有。


2.代码中的括号都是英文的,当你的输入法是中文的时候,输入的括号也是中文的,那么就和数字等字符一样是不会入栈和匹配的,只会简单忽略(也就是这里的if 和else if


会了洛谷这题?来试试力扣这题括号匹配这题吧【力扣】20. 有效的括号


4329b9956525417b8d75c9af107e2c6e.png

和上面洛谷那题类似, 不一样的是判断括号的种类多了,所以ch=='('||ch=='{'||ch=='['时要多加一个判断条件;


所以循环结束的标志就有:


1.输入右括号的时候,栈内没有左括号


2.输入右括号的时候,栈内右括号,但是不是对应的左括号,比如右括号为'}',左括号却为')'


3.遍历完字符串内所有的字符,也就是遇到'\0'


代码:(假如匹配输出YES,不匹配输出NO)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Stack
{
  char* a;
  int capacity;
  int top;
}Stack;
void StackInit(Stack* ps)
{
  ps->a = (char*)malloc(sizeof(char) * 4);
  ps->top = 0;
  ps->capacity = 4;
}
void StackPush(Stack* ps, int e)
{
  assert(ps);
  if (ps->capacity == ps->top)
  {
    int newcapacity = 2 * ps->capacity;
    char* temp = realloc(ps->a, sizeof(char) * newcapacity);
    if (temp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);
    }
    else
    {
      ps->capacity = newcapacity;
      ps->a = temp;
    }
  }
  ps->a[ps->top] = e;
  ps->top++;
}
void  StackPop(Stack* ps)
{
  ps->top--;
}
int StackIsEmpty(Stack* ps)
{
  return ps->top == 0;
}
char StackTop(Stack* ps)
{
  assert(!StackIsEmpty(ps));
  return ps->a[ps->top - 1];
}
void StackDestory(Stack* ps)
{
  free(ps->a);
  ps->a = NULL;
  ps->top = ps->capacity = 0;
}
int main()
{
  char str[] = "{}()[(]";
  Stack ST;
  StackInit(&ST);
  char* s = str;
  while (*s)//结束条件3
  {
    if (( * s == '(' )||( * s == '{') ||( * s == '['))
    {
      StackPush(&ST,*s);
      s++;
    }
    else
    {
      if (StackIsEmpty(&ST))//结束条件1
      {
        StackDestory(&ST);
        printf("NO\n");
        return 0;
      }
      char ch = StackTop(&ST);//栈内不空则取栈顶元素,因为有这行代码隔开,所以下面不能用else if和上面的if匹配
      if(( * s == ')' && ch != '(')||( * s == ']' && ch != '[')||(* s == '}' && ch != '{'))    //结束条件2
      {
        StackDestory(&ST);
        printf("NO\n");
        return 0;
      }
      else
      {
        StackPop(&ST);
        s++;
      }
    }
  }
//正常结束循环只能说明所有的右括号都有左括号和它匹配,这里还要排除左括号多余的情况
  if (StackIsEmpty(&ST))
  {
    printf("YRS\n");
  }
  else
  {
    printf("NO\n");
  }
  StackDestory(&ST);
  return 0;
}

运行结果:

bc77fe58ae51465ea1f9f56d6b8c53ed.png


题单二:

用栈实现十进制转换为八进制

举一个十进制1234转换为八进制2322的例子:因为栈的特性,先进后出,因此每一次对n%8的结果压入栈中,入栈顺序2232,做完取模运算后,出栈顺序就是2322.


20df8154cd734e11a19dc714c9d45448.png


代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Stack
{
  int* a;
  int capacity;
  int top;
}Stack;
void StackInit(Stack* ps)
{
  ps->a = (int*)malloc(sizeof(int) * 4);
  ps->top = 0;
  ps->capacity = 4;
}
void StackPush(Stack* ps, int e)
{
  assert(ps);
  if (ps->capacity == ps->top)
  {
    int newcapacity = 2 * ps->capacity;
    int* temp = realloc(ps->a, sizeof(int) * newcapacity);
    if (temp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);
    }
    else
    {
      ps->capacity = newcapacity;
      ps->a = temp;
    }
  }
  ps->a[ps->top] = e;
  ps->top++;
}
void  StackPop(Stack* ps)
{
  ps->top--;
}
int StackIsEmpty(Stack* ps)
{
  return ps->top == 0;
}
int StackTop(Stack* ps)
{
  assert(!StackIsEmpty(ps));
  return ps->a[ps->top - 1];
}
void StackDestory(Stack* ps)
{
  free(ps->a);
  ps->a = NULL;
  ps->top = ps->capacity = 0;
}
int main()
{
  Stack ST;
  StackInit(&ST);
  int n;
  scanf("%d", &n);
  while (n != 0)
  {
    StackPush(&ST, n % 8);
    n /= 8;
  }
  while (!StackIsEmpty(&ST))
  {
    printf("%d", StackTop(&ST));
    StackPop(&ST);
  }
  StackDestory(&ST);
  return 0;
}

5a653bf97fce47ea994f34c87fd1deb3.png


目录
相关文章
|
3月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
55 1
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
142 77
|
4天前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
1月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
44 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
46 9
|
1月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
38 7
|
3月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
99 5
|
3月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
116 21
|
3月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
3月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
73 0

热门文章

最新文章