1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
| /*这是一个可执行文件,直接粘贴代码就可以执行示例1,修改main函数就可以实现其他的示例。大家如果感兴趣,可以自己修改试试,同时欢迎大家把修改后的main函数放在评论区,供大家参考,谢谢。*/ #include <bits/stdc++.h> using namespace std; //任何一种存储结构都可以写成顺序存储和链式存储 //入栈:Push:*(S.top)++,出栈:Pop:*--S.top;栈顶元素top,从 /*栈的顺序表结构*/ #define STACK_INIT_SIZE 100 //初始分配量 #define STACK_INCREMENT 10 //存储空间分配增量 typedef char ElemType; typedef struct { ElemType *base; //栈底指针,位置不变 ElemType *top; //栈顶指针,top = base 时,栈为空 int stacksize; //栈空间大小 } SqStack; //初始化栈 void intStack(SqStack &S) { if (!(S.base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType)))) exit(OVERFLOW); //存储分配失败 S.top = S.base; S.stacksize = STACK_INIT_SIZE; }
//销毁栈 void DestroyStack(SqStack &S) { free(S.base); //首地址 S.base = NULL; //置空 S.top = NULL; S.stacksize = 0; }
//进栈操作 void Push(SqStack &S, ElemType e) { if ((S.top - S.base) >= S.stacksize) { //动态扩充空间 S.base = (ElemType *)realloc(S.base, ((S.stacksize) + STACK_INCREMENT) * sizeof(ElemType)); if (!S.base) exit(OVERFLOW); //判断上一步是否分配成功 S.top = S.base + S.stacksize; S.stacksize += STACK_INCREMENT; } *(S.top)++ = e; //Push }
//出栈 int Pop(SqStack &S, ElemType &e) { if (S.top == S.base) //如果栈空,返回0 return 0; e = *--S.top; return 1; }
//取出栈顶元素值,这里并没有对S.top进行修改,因为只是 int GetTop(SqStack S, ElemType &e) //取出的值通过e返回,但是对S不进行修改 { if (S.top > S.base) { e = *(S.top - 1); //传出栈顶值 return 1; } else return 0; }
//判断栈是否为空 int StackEmpty(SqStack S) { //当栈为空的时候,返回值为1,否则为0; if (S.top == S.base) return 1; else return 0; }
/*栈的应用,对概念的理解和数据结构有关的数理逻辑分析 1,判断Pop和Push是否合法: 定义I为进栈操作,O为出栈操作,已知栈的初始和末尾状态都是空 请设计程序,使得对于任意的IO序列,都可以判断是否符合要求*/ //先写出顺序表产生的栈的算法: int Right_Not(SqStack &st, char str[]) { int i; ElemType x; int n = strlen(str); //计算一下输入的字符串的长度 for (i = 0; i < n; i++) //循环遍历,给栈填充字符 { if (str[i] == 'I') //I代表入栈 Push(st, str[i]); else if (str[i] == 'O') //O代表出栈, if (!Pop(st, x)) { //判断进行Pop操作之后,栈是否为空,这里其实进行了两步, //先Pop一次,然后判断是否成功,成功Pop返回1,就继续循环, //如果Pop不成功,也就是Pop返回为0,那么!Pop为1,执行销毁栈,然后返回0; DestroyStack(st); return 0; } } if (StackEmpty(st)) //判断经过入栈和出栈操作后,栈是否为空 { DestroyStack(st); //为空时说明操作合法,返回1 return 1; } else { DestroyStack(st); return 0; } } int main() { SqStack st; char str[3] = "IO"; int e; e = Right_Not(st, str); printf("%d", e); }
//2,利用顺序栈的基本操作,设计算法,判断任意给定的字串是否为回文 /*思路,因为栈的先进后出的特点,可以很容易想到,先将字符串如数Push 然后再依次Pop,同时每Pop一次,就和字符串的第一个字符比较一次,依次 进行,直到栈为空,如果出现任意一次不符合,就返回0,否则,返回1;*/ int Palindrome(char str[], int n) { SqStack st; intStack(st); int i; char ch; for (i = 0; i < n; i++) //将字符串压入栈 Push(st, str[i]); //这里要重新定义i= 0,使得字符串从头遍历,当然,再定义一个j = 0也行, //但是基于程序设计的思想,最好少设置变量 i = 0; while (!StackEmpty(st)) //只要栈部位空,就进行比较 { Pop(st, ch); //将st的栈顶元素依次Pop给ch if (ch != str[i++]) //比较ch和str中对应的字符是否匹配 return 0; //如果不匹配,返回0; } }
//选择合适的存储结构,来判断对于任意表达式中的括号是否匹配 /*思路: 比如1*(10+1{10+1})),就不匹配,显然末尾的)没有与之匹配的 (,分析可知,先出现的括号,要和最后出现的与之匹配的括号对应, 这不正是栈的特点吗?*/ int Match(char str[], int n) { int flag; SqStack st; intStack(st); int flag = 1, i = 0; char ch; while (i < n && flag == 1) { switch (str[i]) { //判断进入的是哪一种括号 case '(': case '{': case '[': Push(st, str[i]); break; case ')': if (!Pop(st, ch) || ch != '(') flag = 0; break; case ']': if (!Pop(st, ch) || ch != ']') flag = 0; break; case '}': if (!Pop(st, ch) || ch != '{') flag = 0; break; } i++; if (StackEmpty(st) && flag == 1) return 1; else return 0; }
|