栈输入输出规律总结

栈输入输出规律总结

2016年09月18日 19:41:33

阅读数:1135

      我们都知道栈是先进后出的,最近总遇见这样的题型,原则是“先进后出”,但做题总漏掉

       现以四个为例:设链栈的输入序列为A B C D,试写出所得到的所有可能的输出序列。

      解:从A先出栈开始考虑所有情况,然后在A出的接触上接着考虑B出的情况,直到最后;然后考虑B先出的情况,在B先出的基础上剩余的按小到大的顺序考虑。

       (一)A先出

                (1)A先出基础上B出有:ABCD、ABDC

                (2)A先出基础上C出有:ACBD、ACDB、ADCB

                (3)A先出基础上D出有:ADCB

        同理有B先出:BACD、BADC、BCAD、BCDA、BDCA

               有C先出:CBAD、CBDA、CDBA

               有D先出:DCBA

 

      检查正误的规律:先出来的序号后面一定不能有比他本身小的从小到大排列的序列。

      例:在此题中ADBC不是解 ,如图:

             

同样的:

      BDAC不是解,因为AC都小于D,且AC是从小到大排列;

      CABD不是解,因为AB都小于C,且AB是从小到大排列;

      CADB不是解,因为AB都小于C,且AB是从小到大排列,(尽管他们中间隔着D;)

      CDAB不是解,因为AB都小于C,且AB是从小到大排列;

      DABC不是解,因为ABC都小于D,且ABC从小到大排列;

      DACB不是解,因为ACB都小于D,且AB从小到大排列;

      DBAC不是解,因为BAC都小于D,且AC从小到大排列;

      DBCA不是解,因为BCA都小于D,且BC从小到大排列;

      DCAB不是解,因为CAB都小于D,且AB从小到大排列。

      

#include //打开库文件#include #include #include #include #include #define error 0#define ok 1typedef struct{ int *base; int *top; int stacksize;}sqstack; class CExpression{public: CExpression(); ~CExpression();public: void initstack(sqstack &s); int gettop(sqstack &s); void push(sqstack &s,int e); int pop(sqstack &s,int &e); int setfind(char a,char b[]); //查找a在b中的位置 char precede(char op1,char op2,int &flag); //比较op1和op2的优先级 int numlink(int opd,int ops,int &flag); //数字与字符串的连接 int operate(int n1,char o,int n2,int &flag);//运算 /* flag为一个标志变量, 1为表达式有误!除数为0! 2为表达式的值过大或过小 3为未知类型的错误,可能没有这一点 但为了容错,还是要加上这一点 -*/public: sqstack opnd; sqstack optr;private: sqstack s;}; CExpression::CExpression(){ s.top=s.base;} CExpression::~CExpression(){} void CExpression::initstack(sqstack &s){ s.base=(int *)malloc(10*sizeof(int)); if(!s.base) exit(1); s.top=s.base; s.stacksize=100;} int CExpression::gettop(sqstack &s){ int e; e=*(s.top-1); return e;} void CExpression::push(sqstack &s,int e){ if(s.top-s.base>=s.stacksize) { s.base=(int*)realloc(s.base,(s.stacksize+10*sizeof(int))); if(!s.base) exit(2); s.top=s.base+s.stacksize; s.stacksize+=10; } *s.top++=e;} int CExpression::pop(sqstack &s,int &e){ if(s.top==s.base)return error; e=*--s.top; return ok;} int CExpression::setfind(char a,char b[]){ int i,j; i=-1,j=0; while(b[j]!='\0') if(a==b[j++]) {i=j-1;break;} return i;} char CExpression::precede(char op1,char op2,int &flag) //比较op1和op2的优先级{ int i,j; char st1[8]={"+-*/()#"}; //运算符初始化 char st2[7][8]={">><<>",">><<>",">>>>>", //比较操作初始化 ">>>>>","<<<<>>> >>","<<<<-1 && j>-1) //如果你所输入的运算符不在+-*/()#内,返回ERROR {return st2[i][j];flag=ok;} else flag=error; return error;} int CExpression::numlink(int opd,int ops,int &flag){ //数字与字符串的连接 int aa=ops; ops=ops*10+opd-48; if (ops0 || aa>214748364) flag=error; else flag=ok; //flag=0,说明ops已经过大, return ops;} int CExpression::operate(int n1,char o,int n2,int &flag){ //运算 /* flag为一个标志变量, 1为表达式有误!除数为0! 2为表达式的值过大或过小 3为未知类型的错误,可能没有这一点 但为了容错,还是要加上这一点 -*/ int result=0; switch (o){ case '+': //加法运算 flag=0;result=n1+n2; if (n1>=0 && n2>=0 && result<0 || n1<=0 && n20) //两个大于0的数相加,和小于0,或两个小于0的数相加,和大于0,返回错误 {flag=2;return error;} else {flag=0;return result;} break; case '-': //减法运算 flag=0;result=n1-n2; if (n1>=0 && n2<0 && result<0 || n10 && result>0) //一个大于0的数减一个小于0 的数,和小于0或一个小于0 的数减去一个大于0的数,返回错误 {flag=2;return error;} else {flag=0;return result;} break; case '*': //乘法运算 flag=0;result=n1*n2; if (n1>=0 && n2>=0 && result<0 || n1<=0 && n20) //两个大于0的数相乘,积小于0,或两个小于0的数相乘,积大于0,返回错误 {flag=2;return error;} else {flag=0;return result;} break; case '/': //除法运算 if(n2!=0) //如果被除数为0要返加ERROR {flag=0;return n1/n2;break;} else //除数为0,返回错误 {flag=1;return error;break;} } flag=3;return error;} void main(){ CExpression expression;// sqstack opnd; //用于存放运算数// sqstack optr; //用于存放运算符 int theta; //用于存放一个运算符 int a,b; //用于存放用于操作的两个数 int temp; //一个临时的变量 int flag2=0; //一个标志变量,用于判断是否要连接数字 int flag1; //一个标志变量,用于判断表达式是否是无效的 int cn=0; //用于存放字符的位置 int ops=0; //用于存放当前的操作数 char st1[255]; //表达式中最多有255个字符 char c; //用于表示当前的字符 for (a=0;a>st1; temp=strlen(st1); if (st1[temp-1]!='#') st1[temp]='#'; //对表达式的结尾加入一个# c=st1[0]; while(c!='#' || expression.gettop(expression.optr)!='#'){ //cout<<st1; c=st1[cn]; if(isdigit(c)) { ops=expression.numlink(c,ops,temp); if (temp==ok) { if (flag2) expression.pop(expression.opnd,temp); flag2=1; expression.push(expression.opnd,ops); cn++; continue; } else {cout<<"表达式的值过大,无法计算!"<<endl;return;} } else{ ops=0; flag2=0; temp=expression.precede(expression.gettop(expression.optr),c,temp); //temp为precede中的一个代号,为ok为正确的运算符比较,为error为错误的运算符比较 if (temp==error) {cout<<"表达式有误!无法求解!"<<endl;return;} //错误的运算符比较时,返回. switch (temp){ case '<': expression.push(expression.optr,c);cn++;break; //如果为': //如果为>,执行运算操作 expression.pop(expression.optr,theta); expression.pop(expression.opnd,b); expression.pop(expression.opnd,a); expression.operate(a,theta,b,flag1); if (flag1==1) {cout<<"表达式有误!除数不能为0!"<<endl;return;} else if(flag1==2) {cout<<"表达式的值过大或过小,无法计算!"<<endl;return;} else if(flag1==3) {cout<<"未知道类型的错误!"<<endl;return;} expression.push(expression.opnd,expression.operate(a,theta,b,flag1)); break; case ' ': cout<<"表达式有误!无法求解!"<<endl;return; } //end switch } //end if } //end while a=expression.gettop(expression.opnd); cn=0; while(st1[cn]!='#') cout<<st1[cn++]; //输出你所输入字符串 cout<<"="; cout<<a<<endl; //输出最终结果}
<think>好的,用户现在想了解如何在C语言中输出杨辉三角。之前他们问过冒泡排序,这次是杨辉三角,看来他们在学习基础的算法和编程题目。我需要先回顾一下杨辉三角的基本概念,然后考虑如何用C语言实现。 首先,杨辉三角是一个二维的数字排列,每一行的数字是组合数,也就是二项式系数。每一行的第一个和最后一个数都是1,中间的数等于它上方两个数之和。比如,第三行是1 2 1,第四行是1 3 3 1,依此类推。用户可能需要一个清晰的步骤来解释如何生成这样的结构。 接下来,我需要考虑如何在C语言中实现。可能的思路是使用二维数组来存储每一行的数值。首先确定要输出的行数,然后逐行计算每个位置的数值。对于每一行,第一个和最后一个元素设为1,中间的元素由上一行的两个相邻元素相加得到。 另外,用户可能对动态内存分配不太熟悉,所以使用静态数组可能更简单。不过要考虑到行数较大时可能导致的溢出问题,但作为示例代码,静态数组应该可以满足需求。 还需要注意输出的格式,让杨辉三角呈现为等腰三角形,这需要在每行前面添加适当的空格。空格的数量随着行数的增加而减少,通常是总行数减去当前行数来决定前面的空格数。 可能的步骤分解: 1. 定义变量和数组:声明一个二维数组来存储杨辉三角的数值,以及需要输出的行数。 2. 初始化数组:每一行的第一个和最后一个元素设为1。 3. 计算中间元素:从第三行开始,每个中间元素等于上一行的前一个元素和当前元素之和。 4. 输出格式控制:在每行前面添加空格,使数字居中显示,形成三角形。 5. 循环输出每一行的数值。 另外,需要考虑用户是否了解二维数组的使用,以及循环嵌套的结构。代码需要尽可能简洁,并加上注释,方便用户理解每一步的作用。 可能遇到的错误点包括数组索引越界,比如在计算中间元素时访问了不存在的上一行元素,或者在输出时空格的数量计算错误导致三角形不对称。需要确保循环的边界条件正确,比如行数从0开始还是从1开始,列数的范围等。 此外,用户可能希望看到优化后的代码,比如使用一维数组来节省内存,但作为初步示例,二维数组更容易理解。如果用户后续有更高要求,可以再介绍优化的方法。 最后,测试示例是否正确,比如输入5行,输出的杨辉三角是否符合预期,每一行的数值是否正确,格式是否美观。这可以帮助用户验证代码的正确性,并理解每个步骤的实际效果。</think>下面分步骤介绍如何用C语言输出杨辉三角: --- ### **1. 杨辉三角的基本规则** 杨辉三角是二项式系数在三角形中的几何排列,具有以下特点: - 每行第一个和最后一个数字为$1$(即$C(n,0) = C(n,n) = 1$) - 中间每个数等于它上方两个数之和(即$C(n,k) = C(n-1,k-1) + C(n-1,k)$) - 例如第4行:$1\quad 3\quad 3\quad 1$ --- ### **2. C语言代码实现** ```c #include <stdio.h> int main() { int rows = 5; // 定义要输出的行数(示例为5行) int coef = 1; // 存储当前计算的系数 for (int i = 0; i < rows; i++) { // 打印前导空格(形成三角形) for (int space = 1; space <= rows - i; space++) { printf(" "); } // 计算并打印每行数字 for (int j = 0; j <= i; j++) { if (j == 0 || j == i) { coef = 1; // 首尾元素为1 } else { coef = coef * (i - j + 1) / j; // 通过递推公式计算系数 } printf("%4d", coef); // 每个数字占4位宽度 } printf("\n"); } return 0; } ``` --- ### **3. 代码逐行解析** #### **(1) 前导空格打印** ```c for (int space = 1; space <= rows - i; space++) { printf(" "); } ``` - **作用**:为每行添加左侧空格,使数字居中形成等腰三角形。 - **逻辑**:第$i$行需要打印$rows-i$个空格(每空格占2字符宽度)。 #### **(2) 数字计算与打印** ```c for (int j = 0; j <= i; j++) { if (j == 0 || j == i) { coef = 1; } else { coef = coef * (i - j + 1) / j; } printf("%4d", coef); } ``` - **首尾元素**:直接赋值为$1$。 - **中间元素**:利用递推公式$C(n,k) = C(n,k-1) \times \frac{n-k+1}{k}$计算。 - **格式化输出**:`%4d`保证每个数字占据4字符宽度,对齐美观。 --- ### **4. 程序输出示例** 当`rows = 5`时,输出如下: ``` 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 ``` --- ### **5. 代码优化(二维数组法)** 若需直观体现“上方两数之和”的特性,可用二维数组存储: ```c #include <stdio.h> int main() { int rows = 5; int arr[10][10]; // 假设最多10行 for (int i = 0; i < rows; i++) { // 打印前导空格 for (int space = 0; space < rows - i - 1; space++) { printf(" "); } // 计算并存储数值 for (int j = 0; j <= i; j++) { if (j == 0 || j == i) { arr[i][j] = 1; } else { arr[i][j] = arr[i-1][j-1] + arr[i-1][j]; } printf("%4d", arr[i][j]); } printf("\n"); } return 0; } ``` --- ### **6. 关键点总结** - **数学基础**:理解二项式系数的递推关系。 - **格式化控制**:通过空格和数字宽度保证输出对齐。 - **算法选择**:直接计算法(省内存)或二维数组法(直观体现规律)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值