数据结构与算法实战 3.2.栈(青岛大学 周强)
1 #include<iostream> 2 3 using namespace std; 4 5 //栈的操作:初始化 push(插入) pop(弹栈,注意有的语言里的栈pop的时候会顺便返回top元素) top(看栈顶元素) 6 //用数组做栈,如果以起始位置作为栈顶的话,操作时候会引起大量数据的移动,不划算 7 //所以在用数组做栈的时候,会以末尾作为栈顶,起始位置作为栈底 8 //用链表做栈的时候,显然是与表头操作比较方便,所以链栈会用头作为栈顶 9 //C++ 中用stack利用栈 JAVA中用 Stack这个类 10 /* 11 C++: 12 #include<stack> 13 stack<int> st; 14 st.push(11); 15 st.push(22); 16 int x; 17 st.top();//返回是返回的一个引用 避免拷贝用内存过多 18 st.pop();//只弹栈 19 st.empty(); 20 */ 21 22 //顺序栈 23 struct Stack{ 24 int *data;//动态分配内存 不固定大小 int data[100](固定) 25 int capacity; 26 int top; 27 }; 28 29 void init(struct Stack *ps, int capacity){ 30 //指向一个栈的指针 容量 31 32 ps->capacity = capacity; 33 //总大小 = int * capacity 没毛病 34 ps->data = malloc(sizeof(int) * capacity); 35 ps->top = 0; 36 //-1 和 0都可以 指向最高元素或者最高元素再往上的空位置 37 //但是-1和0会导致后面的操作会有所不同 注意 38 39 } 40 41 //因为多个函数要用到判断栈满 所以写为一个函数 42 bool isFull(const struct Stack *ps){ 43 return ps->top == ps->capacity;//因为top = 0 44 } 45 46 bool push(struct Stack * ps, int data){ 47 //异常判断 栈满 48 if(isFull(ps)) return false; 49 else{ 50 //因为top = 0 51 ps->data[ps->top] = data; 52 //注意 这里能看出 栈顶在top - 1的位置 53 top ++; 54 return true; 55 } 56 } 57 58 //栈空时候不成功 59 //为什么非得写一个函数? 60 //我们写一个程序,里面的东西是作为接口提供给别人调用的 61 //别人只需要调用这个函数就行 内部细节不用给别人展现 62 bool isEmpty(const struct Stack *ps){ 63 return ps->top == 0; 64 } 65 66 bool pop(struct Stack *ps, int *px){ 67 //栈空 68 if(isEmpty(ps)) return false; 69 else{ 70 //top = 0; 栈顶元素在top-1的位置 71 ps->top --; 72 *px = ps->data[ps->top]; 73 return true; 74 } 75 } 76 //查看栈顶元素 77 int top(const struct Stack *ps, int *px){ 78 //栈空 79 if(isEmpty(ps)) return 0; 80 else{ 81 //top = 0; 栈顶元素在top-1的位置 82 83 *px = ps->data[ps->top - 1]; 84 //*px是x的内容,已经把栈顶元素数据赋值给main中的x了,return只是表明是否获取成功 85 return 1; 86 } 87 } 88 89 void destroy(struct Stack *ps){ 90 //只有data是malloc的 91 free(ps->data); 92 } 93 94 /***写函数 先写调用 再根据调用写具体内容***/ 95 int main(){ 96 struct Stack st; 97 //初始化 98 init(&st, 5);//要改变内容 所以要传地址; 多大 99 //压栈 100 push(&st, 11);//栈;元素数据 101 //弹栈 有两种,一种只负责弹出栈顶元素;另一种除了弹出还要返回弹出的值 102 //top()这个去查看栈顶元素 103 int x;//获取弹出值 104 pop(&st, &x); 105 top(&st, &x); 106 destroy(&st); 107 /***记得free!!!防止内存泄露 但是main中写也有问题 这样就是把细节展现在外面了***/ 108 return 0; 109 } 110 111 **实例**后缀式求值 112 科普运算:运算符在运算数的位置中 后 前 113 中缀式:3+5*2 114 后缀式(逆波兰式) 352*+ 115 前缀式(波兰式) +3*52 116 117 后缀式求值的思路:看见一个运算数,没有办法,先放一下,最终看见了运算符,可以做运算了 118 运算的运算数哪里来,就是前面的两个数. 119 例如:3 5 2 1 - * +,读 3 5 2 1 都没有处理方法,先晾着,然后读到了-,我们就可以做运算了, 120 那么要做运算的话,我们就需要运算数,运算数从哪里来啊,又因为是一个二元运算符,就前面拿来两个运算数, 121 这个操作就有点像栈,栈先存下了数字,到了运算符,就弹出. 122 123 题目:根据后缀式求值 124 输入样例:3 5.4 2.2 * + 125 输出样例:14.9 126 127 py实现代码 128 129 //函数计算 130 def cal(x, y, op): 131 if op == '+': 132 return x + y 133 else if op == '-' 134 return x - y 135 else if op == '*' 136 return x * y 137 else if op == '/' 138 return x / y 139 140 exp = input().split() //输入表达式并把每个字符分割 如3 5.5 + 2 / 会分割为一个列表['3' '5.5' '+' '2' '/'] 141 st = list() //创建栈 142 for i in exp: 143 if i in '+-*/'://碰到运算符就退出 144 b = st.pop() 145 a = st.pop() 146 st.append(cal(a, b, i)) 147 else://不是运算符就压栈 148 st.append(float(i)) 149 150 print('%.lf' % st.pop())