题目:假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,可以操作的序列称为合法序列,否则称为非法序列,写一个算法,判定所给的操作序列是否合法。
输入:一个一维的字符型数组(由I和O组成),以‘0’为结束。
输出:判断出入栈的序列是否合法,输出结果。
优化目标:无。
算法思想:依次逐一扫描入栈出栈序列(即由“I”和”O“组成的字符串),每扫描至任意位置均需检查出栈次数(即"O"的个数)是否小于入栈次数(即”I“的个数),若大于则为非法序列。扫描结束后,再判断入栈和出栈次序是否相同,若不等为非法序列,反之为合法序列。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
//判断出入栈操作序列是否合法
int Judge(char A[]){
int i = 0;
int j,k;
j = k = 0;
while(A[i]!='\0'){
switch (A[i]) {
case 'I':
j++;
break;
case 'O':
k++;
if(k>j){
printf("序列非法!");
return -1;
}
}
i++;
}
if(j!=k){
printf("序列非法!");
return -1;
}
else{
printf("序列合法!");
return 0;
}
}
//输入进出栈序列
void Input(char A[]){
printf("请输入进出栈的顺序(以0为结束):");
int i = 0;
char ch;
scanf("%c",&ch);
while(ch!='0'&&i<20){
A[i] = ch;
i++;
scanf("%c",&ch);
}
A[i] = '\0';
}
int main(){
char A[MAXSIZE];
Input(A);
Judge(A);
}
题目:设单链表的表头指针为L,结点结构为data和next两个域构成,其中data域为字符型,试设计计算算法判断该链表的全部n个字符是否中心对称。例如xyx,xyyx都是中心对称。
输入:带头结点的链表个元素的值,类型为char,以‘0’结束。
输出:判断该单链表是否是中心对称,输出结果。
优化目标:无。
算法思想:用栈来判断链表中的数量是否中心对称。让链表的前一半元素依次进栈。在处理链表的后一半元素时,当访问到链表的一个元素后,就从栈中弹出一个元素。两个元素比较,若相等则将链表中的下一个元素与栈中再弹出的元素比较,直至链表到尾。这时若栈为空栈,则得出链表中心对称的结论;否则当链表中的一个元素与栈中弹出元素不等时,结论为链表非中心对称。
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
char data;
struct LNode *next;
}LNode,*LinkList;
//判断单链表是否是中心对称
int dc(LinkList L,int n){
int i;
char s[n/2];
LNode *p = L->next;
for(i = 0;i<n/2;i++){
s[i] = p->data;
p = p->next;
}
i--;
if(n%2 == 1){
p = p->next;
}
while(p!=NULL&&s[i] == p->data){
i--;
p = p->next;
}
if(i == -1){
return 1;
}
else{
return 0;
}
}
//创建链表
void creatList(LinkList &L,int &n){
LNode *s,*r;
n = 0;
char x;
printf("请输入链表元素值(以0结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%c",&x);
while(x!='0'){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
n++;
scanf("%c",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%c ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
int n;
creatList(L,n);
PrintList(L);
printf("%d \n",n);
int k = dc(L,n);
if(k == 1){
printf("链表中心对称");
}
else{
printf("链表不中心对称");
}
return 0;
}
题目:假设一个算术表达式中包括圆括号,方括号和花括号3种类型的括号,编写一个算法来判别表达式中的括号是否配对,以字符’\0‘作为算术表达式的结束符。
输入:一个一维的字符型数组(含括号算术表达式),以‘0’为结束。
输出:判断该算术表达式的括号使用是否合法,输出结果。
优化目标:无。
算法思想:扫描每一个字符。遇到花、中,园的左括号时进栈,遇到花、中、圆的右括号时检查栈顶元素是否是对应的左括号,若是,退栈,否则配对错误。最后栈若不为空也为错误(即左括号多了)。
#include<stdio.h>
#include<stdlib.h>
#define Maxsize 20
//顺序栈
typedef struct{
char data[Maxsize];
int top;
}SqStack;
//初始化
void InitStack(SqStack &S){
S.top = -1;
}
//判空
int StackEmpty(SqStack S){
if(S.top == -1){
return 1;
}
else{
return 0;
}
}
//进栈
int Push(SqStack &S, char e){
if(S.top == Maxsize-1){
printf("栈已满!");
return 0;
}
S.data[++S.top] = e;
return 1;
}
//出栈
int Pop(SqStack &S, char &e){
if(S.top == -1){
printf("栈已空!");
return 0;
}
e = S.data[S.top--];
return 1;
}
//获取栈顶元素
int GetTop(SqStack S, char &e){
if(S.top == -1){
printf("栈已空!");
return 0;
}
e = S.data[S.top];
return 1;
}
//判断括号匹配是否成功
void BracketsCheck(char A[]){
SqStack S;
InitStack(S);
int i = 0;
char e;
while(A[i]!='\0'){
switch (A[i]) {
case '(':
Push(S,'(');
break;
case '[':
Push(S,'[');
break;
case '{':
Push(S,'{');
break;
case ')':
Pop(S,e);
if(e!='('){
printf("括号匹配失败!\n");
return;
}
break;
case ']':
Pop(S,e);
if(e!='['){
printf("括号匹配失败!\n");
return;
}
break;
case '}':
Pop(S,e);
if(e!='{'){
printf("括号匹配失败!\n");
return;
}
break;
default:
break;
}
i++;
}
if(!StackEmpty(S)){
printf("括号匹配失败!\n");
}
else{
printf("括号匹配成功!\n");
}
}
//输入算术表达式
void Input(char A[]){
printf("请输入算术表达式的顺序(以0为结束):");
int i = 0;
char ch;
scanf("%c",&ch);
while(ch!='0'&&i<20){
A[i] = ch;
i++;
scanf("%c",&ch);
}
A[i] = '\0';
}
int main(){
char A[Maxsize];
Input(A);
BracketsCheck(A);
}
题目:假设火车调度站的入口处有n节硬座和软座车厢(分别用H和S表示)等待调度,试编写算法,输出对这n节车厢进行调度的操作(即入栈和出栈操作)序列,以使所有的软座车厢都调整到硬座车厢之前。
输入:一个一维的字符型数组(由H和S组成),以‘0’为结束。
输出:将软座和硬座的车厢序列调整好后,输出调整好的车厢序列。
优化目标:无。
算法思想:所有的硬座车厢全部入栈,车道中的车厢均为软座车厢。此时将栈道内的车厢调度出来,调整到软座车厢之后。
#include<stdio.h>
#include<stdlib.h>
#define Maxsize 20
//顺序栈
typedef struct{
char data[Maxsize];
int top;
}SqStack;
//初始化
void InitStack(SqStack &S){
S.top = -1;
}
//判空
int StackEmpty(SqStack S){
if(S.top == -1){
return 1;
}
else{
return 0;
}
}
//进栈
int Push(SqStack &S, char e){
if(S.top == Maxsize-1){
printf("栈已满!");
return 0;
}
S.data[++S.top] = e;
return 1;
}
//出栈
int Pop(SqStack &S, char &e){
if(S.top == -1){
printf("栈已空!");
return 0;
}
e = S.data[S.top--];
return 1;
}
//将全部软座车厢调整到硬座车厢之前
void Train_Arrange(char A[]){
SqStack S;
InitStack(S);
char *p = A,*q = A,e;
while(*p){
if(*p == 'H'){
Push(S,*p);
}
else{
*(q++) = *p;
}
p++;
}
while(!StackEmpty(S)){
Pop(S,e);
*(q++) = e;
}
}
//输入当前软座和硬座的顺序
void Input(char A[]){
printf("请输入当前软座和硬座的顺序(以0为结束):");
int i = 0;
char ch;
scanf("%c",&ch);
while(ch!='0'&&i<20){
A[i] = ch;
i++;
scanf("%c",&ch);
}
A[i] = '\0';
}
//输出当前软座和硬座的序列
void Print(char A[]){
int i = 0;
printf("数组中数值为:");
while(A[i]!='\0'){
printf("%c ",A[i]);
i++;
}
printf("\n");
}
int main(){
char A[Maxsize];
Input(A);
Print(A);
Train_Arrange(A);
Print(A);
}
今日总结:今天做了几道栈的题,感觉栈的应用还是很广泛的,例如,洗干净的盘子总是逐个往上叠放在已经洗好的盘子上面,而用时从上往下逐个取用。在程序设计中,如果需要按照保存数据时相反的顺序来使用数据,则可以利用栈来实现。