Example006

题目

假设以 I 和 O 分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅有 I 和 O 组成的序列,可以操作的序列为合法序列,否则称为非法序列。如 IOIIOIOOIIIOOIOO 是合法的;而 IOOIOIIOIIIOIOIO 不合法。写出一个算法,判定给定的操作序列是否合法。若合法则返回 1,否则返回 0(假定被判定的操作序列已存入一维数组 char 型数组 ch[] 中,操作序列以 “\0” 为结束符)。

分析

解法一算法思想:从头到尾扫描操作序列,如果是 I 操作则将 I 字符入栈,如果是 O 字符则判断是否栈空,如果栈空则表示此时 O 操作多于 I 操作,必然不是合法序列,如果栈非空则将栈顶元素出栈,IO 操作相互抵消。当扫描完操作序列后,如果栈空则 I 操作和 O 操作一一对应,表示是合法序列;如果栈非空则表示 I 操作多于 O 操作,那么一定是非法序列。

解法二算法思想:算法的基本设计思想:依次逐一扫描入栈出栈序列(即由 IO 组成的字符串),每扫描至任一位置均需检查出栈次数(即 O 的个数)是否小于入栈次数(I 的个数),若大于则为非法序列。扫描结束后,再判断入栈和出栈次数是否相等,若不相等则不合题意,为非法序列。

图解

解法一图解:

C实现

解法一核心代码:

/*** 判断指定操作序列是否合法* @param options 操作序列数组,由 I 和 O 组成* @param n 数组长度* @return 如果操作序列合法则返回 1,否则返回 0 表示不合法*/
int isLegal(char options[], int n) {// 0.声明栈并初始化栈,用来作为解题的辅助数据结构SeqStack stack;init(&stack);// 1.遍历字符数组 options 中所有字符for (int i = 0; i < n; i++) {// 局部变量,记录当前的数组元素char c = options[i];// 1.1 如果是 I 操作,则将其入栈if (c == 'I') {push(&stack, c);}// 1.2 如果是 O 操作,则需要根据不同情况进行处理else if (c == 'O') {// 1.2.1 如果是空栈,则表示此时 O 操作比 I 操作,那么一定不合法,返回 0if (isEmpty(stack)) {return 0;}// 1.2.2 如果不是空栈,则将栈顶元素出栈,即 O 操作与 I 操作相互抵消一次else {char top;pop(&stack, &top);}}}// 2.循环结束后,判断栈中是否还有元素,如果还有元素则表示 I 操作比 O 操作多,不合法;如果栈空则表示合法if (isEmpty(stack)) {return 1;} else {return 0;}
}

解法二核心代码:

/*** 判断指定操作序列是否合法* @param options 操作序列数组,由 I 和 O 组成* @param n 数组长度* @return 如果操作序列合法则返回 1,否则返回 0 表示不合法*/
int isLegal(char options[], int n) {int i = 0;// 表示 I 操作的个数int o = 0;// 表示 O 操作的个数for (int m = 0; m < n; m++) {if (options[m] == 'I') {i++;} else if (options[m] == 'O') {o++;// 如果出栈操作 O 的次数大于入栈操作 I 的次数,那么必然不是合法序列if (o > i) {return 0;}}}// 扫描完成后,比较 i 和 o 的次数,如果相等则表示序列合法,否则表示 I 操作的次数大于 O 操作的次数则不合法if (i != o) {return 0;} else {return 1;}
}

完整代码:

/*
假设以 I 和 O 分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为
仅有 I 和 O 组成的序列,可以操作的序列为合法序列,否则称为非法序列。如 IOIIOIOO、IIIOOIOO 是
合法的;而 IOOIOIIO、IIIOIOIO 不合法。写出一个算法,判定给定的操作序列是否合法。若合法则返回 1,
否则返回 0(假定被判定的操作序列已存入一维数组 char 型数组 ch[] 中,操作序列以 "\0" 为结束符)。
*/
#include <stdio.h>/*** 顺序栈最大存储的元素个数*/
#define MAXSIZE 100/*** 顺序栈结构体定义*/
typedef struct {/*** 数据域,数组,用来存储栈中元素*/char data[MAXSIZE];/*** 指针域,表示栈顶指针,实际上就是数组下标*/int top;
} SeqStack;/*** 初始化顺序栈,即将栈顶指针指向 -1 表示空栈* @param stack 顺序栈*/
void init(SeqStack *stack) {// 设定让栈顶指针指向 -1 表示为栈空stack->top = -1;
}/*** 判断顺序栈是否为空* @param stack 顺序栈* @return 如果顺序栈为空则返回 1,否则返回 0*/
int isEmpty(SeqStack stack) {// 只需要判断栈顶指针是否等于 -1 即可,如果是空栈则返回 1,不是空栈则返回 0if (stack.top == -1) {return 1;} else {return 0;}
}/*** 将元素入栈* @param stack 顺序栈* @param ele 元素值* @return 如果栈满则返回 0 表示入栈失败;如果插入成功则返回 1*/
int push(SeqStack *stack, char ele) {// 1.参数校验,如果栈满则不能入栈元素if (stack->top == MAXSIZE - 1) {// 如果栈满,则返回 0,表示不能入栈return 0;}// 2.先将栈顶指针加一,指向新空数组位置stack->top++;// 3.将新元素值填充到新位置中stack->data[stack->top] = ele;return 1;
}/*** 将元素出栈* @param stack 顺序栈* @param ele 用来保存出栈的元素* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功*/
int pop(SeqStack *stack, char *ele) {// 1.参数校验,栈空不能出栈if (stack->top == -1) {// 栈空,没有元素可出栈return 0;}// 2.用 ele 来保存顺序栈栈顶元素*ele = stack->data[stack->top];// 3.然后栈顶指针减一,表示出栈一个元素stack->top--;return 1;
}/*** 获取栈顶元素,但不出栈* @param stack 顺序栈* @param ele 用来保存出栈元素* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功*/
int getTop(SeqStack stack, char *ele) {// 1.参数校验,如果栈空则不能出栈if (stack.top == -1) {// 栈空,没有元素可出栈return 0;}// 2.保存栈顶元素返回*ele = stack.data[stack.top];return 1;
}/*** 判断指定操作序列是否合法* @param options 操作序列数组,由 I 和 O 组成* @param n 数组长度* @return 如果操作序列合法则返回 1,否则返回 0 表示不合法*/
int isLegal(char options[], int n) {// 0.声明栈并初始化栈,用来作为解题的辅助数据结构SeqStack stack;init(&stack);// 1.遍历字符数组 options 中所有字符for (int i = 0; i < n; i++) {// 局部变量,记录当前的数组元素char c = options[i];// 1.1 如果是 I 操作,则将其入栈if (c == 'I') {push(&stack, c);}// 1.2 如果是 O 操作,则需要根据不同情况进行处理else if (c == 'O') {// 1.2.1 如果是空栈,则表示此时 O 操作比 I 操作,那么一定不合法,返回 0if (isEmpty(stack)) {return 0;}// 1.2.2 如果不是空栈,则将栈顶元素出栈,即 O 操作与 I 操作相互抵消一次else {char top;pop(&stack, &top);}}}// 2.循环结束后,判断栈中是否还有元素,如果还有元素则表示 I 操作比 O 操作多,不合法;如果栈空则表示合法if (isEmpty(stack)) {return 1;} else {return 0;}
}int main() {int result;char arr1[] = "IOIIOIOO";int n1 = 8;result = isLegal(arr1, 8);printf("%s 是否是合法的操作序列:%d\n", arr1, result);char arr2[] = "IIIOOIOO";int n2 = 8;result = isLegal(arr2, 8);printf("%s 是否是合法的操作序列:%d\n", arr2, result);char arr3[] = "IOOIOIIO";int n3 = 8;result = isLegal(arr3, 8);printf("%s 是否是合法的操作序列:%d\n", arr3, result);char arr4[] = "IIIOIOIO";int n4 = 8;result = isLegal(arr4, 8);printf("%s 是否是合法的操作序列:%d\n", arr4, result);
}

执行结果:

IOIIOIOO 是否是合法的操作序列:1
IIIOOIOO 是否是合法的操作序列:1
IOOIOIIO 是否是合法的操作序列:0
IIIOIOIO 是否是合法的操作序列:0

Java实现

核心代码:

    /*** 判断给定由 'I' 和 'O' 组成的字符序列是否合法** @param options 由 'I' 和 'O' 组成的字符序列* @return 如果合法则返回 1,否则返回 0 表示不合法* @throws Exception*/public static int isLegal(char[] options) throws Exception {// 0.声明栈并初始化栈,用来作为解题的辅助数据结构SeqStack stack = new SeqStack();stack.init();// 1.遍历字符数组 options 中所有字符for (int i = 0; i < options.length; i++) {// 局部变量,记录当前的数组元素char c = options[i];// 1.1 如果是 I 操作,则将其入栈if (c == 'I') {stack.push(c);}// 1.2 如果是 O 操作,则需要根据不同情况进行处理else if (c == 'O') {// 1.2.1 如果是空栈,则表示此时 O 操作比 I 操作,那么一定不合法,返回 0if (stack.isEmpty()) {return 0;}// 1.2.2 如果不是空栈,则将栈顶元素出栈,即 O 操作与 I 操作相互抵消一次else {stack.pop();}}}// 2.循环结束后,判断栈中是否还有元素,如果还有元素则表示 I 操作比 O 操作多,不合法;如果栈空则表示合法if (stack.isEmpty()) {return 1;} else {return 0;}}

完整代码:

public class Test {public static void main(String[] args) throws Exception {int result;String str1 = "IOIIOIOO";result = isLegal(str1.toCharArray());System.out.println(str1 + " 是否是合法操作序列:" + result);String str2 = "IIIOOIOO";result = isLegal(str2.toCharArray());System.out.println(str2 + " 是否是合法操作序列:" + result);String str3 = "IOOIOIIO";result = isLegal(str3.toCharArray());System.out.println(str3 + " 是否是合法操作序列:" + result);String str4 = "IIIOIOIO";result = isLegal(str4.toCharArray());System.out.println(str4 + " 是否是合法操作序列:" + result);}/*** 判断给定由 'I' 和 'O' 组成的字符序列是否合法** @param options 由 'I' 和 'O' 组成的字符序列* @return 如果合法则返回 1,否则返回 0 表示不合法* @throws Exception*/public static int isLegal(char[] options) throws Exception {// 0.声明栈并初始化栈,用来作为解题的辅助数据结构SeqStack stack = new SeqStack();stack.init();// 1.遍历字符数组 options 中所有字符for (int i = 0; i < options.length; i++) {// 局部变量,记录当前的数组元素char c = options[i];// 1.1 如果是 I 操作,则将其入栈if (c == 'I') {stack.push(c);}// 1.2 如果是 O 操作,则需要根据不同情况进行处理else if (c == 'O') {// 1.2.1 如果是空栈,则表示此时 O 操作比 I 操作,那么一定不合法,返回 0if (stack.isEmpty()) {return 0;}// 1.2.2 如果不是空栈,则将栈顶元素出栈,即 O 操作与 I 操作相互抵消一次else {stack.pop();}}}// 2.循环结束后,判断栈中是否还有元素,如果还有元素则表示 I 操作比 O 操作多,不合法;如果栈空则表示合法if (stack.isEmpty()) {return 1;} else {return 0;}}}

SeqStack

public class SeqStack {/*** 常量,顺序栈所能容纳的最大元素个数*/private final int MAXSIZE = 100;/*** 声明一个顺序栈*/private Stack stack;/*** 初始化顺序栈*/public void init() {// 实例化栈对象stack = new Stack();// 为数据域分配空间stack.data = new int[MAXSIZE];// 将顺序栈的栈顶指针指向 -1 表示空栈stack.top = -1;}/*** 判断顺序栈是否为空** @return 如果顺序栈为空则返回 true,否则返回 false*/public boolean isEmpty() {// 规定了 -1 表示空栈,所以只需要判断栈顶指针是否等于 -1 即可return stack.top == -1;}/*** 将指定元素入栈** @param ele 指定元素* @throws Exception 如果栈满则不能入栈,抛出此异常*/public void push(int ele) throws Exception {// 1.参数校验,如果栈满则不能入栈,抛出异常if (stack.top == MAXSIZE - 1) {// 因为栈顶指针 top 存储的是数组下标,所以判断是否等于 MAXSIZE-1throw new Exception("栈已满,不能再插入!");}// 2.先栈顶指针加 1,因为原栈顶指针处已经存储了元素,所以加一指向新的空位置stack.top++;// 3.在新的空位置处插入新元素,即为指定下标的数组元素赋值stack.data[stack.top] = ele;}/*** 将栈顶元素出栈** @return 栈顶元素* @throws Exception 如果栈空则不能出栈,抛出此异常*/public int pop() throws Exception {// 1.参数校验,如果栈空则不能出栈,抛出异常if (stack.top == -1) {// 因为栈空的定义是栈顶指针为 -1,所以如果栈顶指针为 -1 那么就是空栈,就不能出栈元素throw new Exception("栈为空,不能出栈元素!");}// 2.记录栈顶元素,因为要将该元素返回,即要出栈的元素int result = stack.data[stack.top];// 3.栈顶指针减一,因为原栈顶元素已经出栈了,栈中元素个数减一stack.top--;return result;}/*** 获取栈顶元素,但不出栈** @return 栈顶元素* @throws Exception 如果栈空则不能出栈,抛出此异常*/public int getTop() throws Exception {// 1.参数校验,如果栈空则不能出栈,抛出异常if (stack.top == -1) {throw new Exception("栈为空,不能获取栈顶元素!");}// 2.直接返回栈顶元素,但不出栈return stack.data[stack.top];}/*** 顺序栈中元素个数** @return 栈中元素个数*/public int size() {// top 表示栈顶指针,实际上就是数组 data 的下标,所以实际元素个数就是下标加一// 即使是空栈 top=-1,那么最后也会返回 0 表示元素个数为零个return stack.top + 1;}/*** 打印顺序栈中所有元素,从栈顶到栈底*/public void print() {System.out.print("[");for (int i = stack.top; i >= 0; i--) {if (i != stack.top) {System.out.print(", ");}System.out.print(stack.data[i]);}System.out.print("]\n");}/*** 清空顺序栈*/public void clear() {// 直接将栈顶指针指向 -1 即可表示空栈,不用重置栈中已有元素的值,因为顺序栈操作只跟栈顶指针有关stack.top = -1;}
}/*** 栈定义*/
class Stack {/*** 顺序栈用来存储元素的数组*/int[] data;/*** 记录顺序栈的栈顶指针,即数组下标*/int top;
}

执行结果:

IOIIOIOO 是否是合法操作序列:1
IIIOOIOO 是否是合法操作序列:1
IOOIOIIO 是否是合法操作序列:0
IIIOIOIO 是否是合法操作序列:0

栈练习之Example006-判定给定的由 I 和 O 组成的入栈和出栈组成的操作序列是否合法相关推荐

  1. 详解+G - 数据结构实验之栈与队列七:出栈序列判定

    理解: 出入栈规律之一,如果前面有一个比较大的数,后面有连续的递增顺序,递增顺序>=2个小于前面比较大的数,那么此出栈顺序不可能实现.比如4,1,2,3,5. 思路:输入一个数,然后不断按照顺序 ...

  2. (24) 不可能的出栈顺序

    一.问题描述 给定两个数组,一个进栈顺序,一个出栈顺序.判定出栈数组的出栈顺序是不是有可能的. 二.Code 1 package algorithm; 2 3 import java.util.Arr ...

  3. 21. 栈的压入、弹出序列

    题目 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...

  4. C++实现栈的基本操作(入栈,出栈,取栈顶)

    C++实现栈的基本操作(入栈,出栈,取栈顶) 参考资料:王道数据结构考研复习指导:王道C语言督学营 #include<stdio.h> #include<stdlib.h> # ...

  5. 1.若元素的进栈序列为:A、B、C、D、E,则:运用栈操作,能否得到出栈序列B、C、A、E、D和D、B、A、C、E?为什么?

    初学数据结构,有一些有意思的东西就写出来记录一下 这个是上课的时候老师出的课堂考试题目,觉得很有意思,分享给大家. 初看题目的时候,第一反应是栈是先进后出,那出栈顺序不就只有一种(E.D.C.B.A) ...

  6. 【数据结构与算法】栈的介绍及基本运算(出栈、入栈、销毁栈等)

    一.栈的介绍 栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表. 允许插入和删除运算的一端称作栈顶(top). 不允许插入和删除的另一端称作栈底(bottom). 在栈顶进行的插入操作称 ...

  7. 【数据结构与算法】栈的基本运算(出栈、入栈、销毁栈等)及源码(顺序栈和链式栈)

    一.顺序栈 .h文件 #include <iostream> using namespace std;#define STACKSIZE 100 typedef int DataType; ...

  8. java顺序栈_顺序栈的基本操作(入栈和出栈)

    顺序栈的基本操作(入栈和出栈) 顺序栈,即用顺序表实现栈存储结构.通过前面的学习我们知道,使用栈存储结构操作数据元素必须遵守 "先进后出" 的原则,本节就 "如何使用顺序 ...

  9. 假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。

    ①下面所示的序列中哪些是合法的? A. IOIIOIOO B. IOOIOIIO C. IIIOIOIO D. IIIOOIOO ②通过对①的分析,写出一个算法,判定所给的操作序列是否合法.若合法,返 ...

最新文章

  1. 源码实战 | 本地可跑,上线就崩?慌了!
  2. [剑指offer] 27. 字符串的排列
  3. SpringSecurity授权(访问控制)
  4. 使用python 创建快捷方式
  5. spring学习笔记(六)
  6. python表白代码大全-python表白代码
  7. usb扩展坞同时接键盘鼠标_iPadOS 13.1连接鼠标键盘扩展坞用法说明
  8. 32/64位处理器、操作系统、应用程序和库之间有什么关系?
  9. linux离线安装postgresql,离线安装PostgreSQL
  10. C++输入一串数值,逗号隔开,回车结束
  11. Ubuntu1804 使用mondorescue 进行系统备份iso制作
  12. JSD-2204-RESTful-Service-SpringMVC-Day06
  13. 通过evel将字符串作为函数执行函数
  14. 孔庆东nbsp;--nbsp;一个DEAD-LEFTIST
  15. 【Python】DS的基础学习笔记3:组合数据类型
  16. 工控前辈经验之谈 | 编写PLC程序我从做Excel表开始
  17. 华夏基金X袋鼠云:基金业数字化转型,为什么说用户才是解题答案?
  18. 微信服务商和渠道商区别
  19. <Java>根据身高体重计算BMI指数
  20. yyf学习JavaScriptTypeScript

热门文章

  1. 安卓Edge浏览器的一些用法
  2. 油卡充值接口源码分享
  3. uniapp 动态 tabbar
  4. 如何在Windows 10上用cmd批量重命名多个文件
  5. chrome扩展程序知识点
  6. 科学家发现神秘星球:物理规律要重写了
  7. IT的你该干什么就干什么
  8. gitbash登录码云报错_git之sourceTree操作流程
  9. 进阶92 表达式求值
  10. 使用Bert模型进行多标签分类