概念:

栈(Stack)是一种先进后出(FILO,First in Last Out)的线性表,只允许在线性表的一端进行操作。

典型应用:

函数调用时,函数的上下文环境(返回地址,全局变量等),形参,是以栈这样的数据结构存储的。

基本操作:

1. 压栈

2. 出栈

3. 栈判空

4. 元素个数

5. 栈清空

6. 栈销毁

操作应用:

1. 进制转换

2. 括号匹配

3. 后缀表达式求值

4. 中缀转后缀

5. 迷宫问题求解


栈的实现方法:

方法1:静态顺序表

方法2:动态顺序表(高效)

方法3:只能头插头删的单链表


栈的定义(动态顺序表):


     
     
     
     
  1. typedef struct Stack {
  2. //以数组地址为栈底指针
  3. DataType* _array;
  4. //栈顶指针
  5. int _top;
  6. //栈的大小
  7. unsigned int _capacity;
  8. }*PStack;

初始化:


     
     
     
     
  1. //初始化栈
  2. void StackInit(PStack stack) {
  3. stack->_array = (DataType*) malloc( sizeof(DataType)*Init_StackSize);
  4. for ( int i = 0; i < sizeof( stack->_array) / sizeof( stack->_array[ 0]); i++) {
  5. stack->_array[i] = 0;
  6. }
  7. if (! stack->_array) {
  8. exit( 0);
  9. }
  10. stack->_top = 0;
  11. stack->_capacity = Init_StackSize;
  12. }

基本操作:

1. 压栈



     
     
     
     
[cpp] view plain copy
print ?
  1. class=“language-cpp”>//压栈  
  2. void StackPush(PStack stack, DataType data) {  
  3.     assert(stack);  
  4.     //判断栈是否已满  
  5.     if (stack->_top >= stack->_capacity) {  
  6.         //申请10个空间  
  7.         stack->_array = (DataType*)realloc(stack->_array,   
  8.             sizeof(DataType)*(stack->_capacity + 10));  
  9.         //判断是否申请成功  
  10.         if (!stack->_array) {  
  11.             exit(0);  
  12.         }  
  13.         stack->_top = stack->_capacity;  
  14.         stack->_capacity = stack->_capacity + 10;  
  15.     }  
  16.   
  17.     *(stack->_array + stack->_top) = data;  
  18.     stack->_top++;  
  19. }  

      
      
      
      
  1. //压栈
  2. void StackPush(PStack stack, DataType data) {
  3. assert( stack);
  4. //判断栈是否已满
  5. if ( stack->_top >= stack->_capacity) {
  6. //申请10个空间
  7. stack->_array = (DataType*) realloc( stack->_array,
  8. sizeof(DataType)*( stack->_capacity + 10));
  9. //判断是否申请成功
  10. if (! stack->_array) {
  11. exit( 0);
  12. }
  13. stack->_top = stack->_capacity;
  14. stack->_capacity = stack->_capacity + 10;
  15. }
  16. *( stack->_array + stack->_top) = data;
  17. stack->_top++;
  18. }




2. 出栈(pop的数据放在data里面)


     
     
     
     
  1. //出栈
  2. int StackPop(PStack stack, DataType* data) {
  3. assert( stack);
  4. //判断栈是否为空
  5. if ( stack->_top == 0) {
  6. return 0;
  7. }
  8. //先减一再取值
  9. -- stack->_top;
  10. *data = *( stack->_array + stack->_top);
  11. return 1;
  12. }


3. 栈判空


     
     
     
     
  1. //判断栈是否为空
  2. int StackEmpty(PStack stack) {
  3. assert( stack);
  4. //为空返回1
  5. return stack->_top == 0 ? 1 : 0;
  6. }


4. 有效元素个数


     
     
     
     
  1. //有效元素个数
  2. int StackSize(PStack stack) {
  3. assert( stack);
  4. return stack->_top;
  5. }

5. 栈清空


     
     
     
     
  1. //清空栈,不进行物理删除
  2. void ClearStack(PStack stack) {
  3. assert( stack);
  4. stack->_top = 0;
  5. }


6. 栈销毁


     
     
     
     
  1. //销毁栈
  2. void dropStack(PStack stack) {
  3. assert( stack);
  4. int len = stack->_capacity;
  5. for ( int i = 0; i < len; i++) {
  6. free( stack->_array);
  7. stack->_array++;
  8. }
  9. stack->_array = NULL;
  10. stack->_top = 0;
  11. stack->_capacity = 0;
  12. }


操作应用:

1. 进制转换



     
     
     
     
  1. //二进制转10进制
  2. int BinaryToTen(PStack stack, DataType* str) {
  3. assert( stack);
  4. unsigned int len = stack->_capacity;
  5. char* p_str = str;
  6. int sum = 0;
  7. for ( int i = 0; i < len; i++) {
  8. if (*p_str == '\0')
  9. break;
  10. StackPush( stack, *p_str);
  11. p_str++;
  12. }
  13. char binary = ' ';
  14. for ( int i = 0; i < len; i++) {
  15. if ( 0 == StackPop( stack, &binary))
  16. break;
  17. sum += (binary - 48)* pow( 2, i);
  18. }
  19. return sum;
  20. }

栈_第1张图片


2. 括号匹配



     
     
     
     
  1. //括号匹配
  2. void MatchBranckets(char* str) {
  3. if (str == NULL)
  4. return;
  5. //初始化栈
  6. PStack stack = (PStack) malloc( sizeof(struct Stack));
  7. StackInit( stack);
  8. char* p_str = str;
  9. //用来保存弹出的字符
  10. char c;
  11. while (*p_str) {
  12. if (*p_str == '{' || *p_str == '(' || *p_str == '[') {
  13. StackPush( stack, *p_str);
  14. }
  15. if (*p_str == '}' || *p_str == ')' || *p_str == ']') {
  16. StackPop( stack, &c);
  17. if (c == '{' && *p_str == '}');
  18. else if (c == '(' && *p_str == ')');
  19. else if (c == '[' && *p_str == ']');
  20. else {
  21. printf( "匹配失败\n");
  22. return;
  23. }
  24. }
  25. p_str++;
  26. }
  27. //遍历完之后,栈中还有括号,代表匹配失败
  28. if (StackPop( stack, &c))
  29. {
  30. printf( "匹配失败\n");
  31. return;
  32. }
  33. printf( "匹配成功\n");
  34. }

栈_第2张图片



3. 后缀表达式求值


     
     
     
     
  1. //根据操作符的不同进行不同的计算
  2. int caculate(int first, int second, char operator) {
  3. if ( operator == '+') {
  4. return first + second;
  5. }
  6. else if ( operator == '-') {
  7. return first - second;
  8. }
  9. else if ( operator == '*') {
  10. return first * second;
  11. }
  12. else if ( operator == '/') {
  13. return first / second;
  14. }
  15. }
  16. //后缀表达式求值
  17. int caculateNifixExpression(char* str) {
  18. //用来放整形操作数
  19. PStack operator = (PStack) malloc( sizeof(struct Stack));
  20. StackInit( operator);
  21. if (str == NULL)
  22. return;
  23. char* p_str = str;
  24. char* p_preStr = str;
  25. int StackPopData = 0;
  26. //弹出的第一个操作数,右操作数
  27. int first = 0;
  28. //弹出的第二个操作数, 左操作数
  29. int second = 0;
  30. while (*p_str) {
  31. if (*p_str == ' ') {
  32. //空格前是数字,压栈
  33. if (*p_preStr >= '0' && *p_preStr <= '9')
  34. StackPush( operator, atoi(p_preStr));
  35. p_preStr = p_str + 1;
  36. }
  37. if (*p_str == '+' || *p_str == '-' || *p_str == '*' || *p_str == '/') {
  38. StackPop( operator, &StackPopData);
  39. second = StackPopData;
  40. StackPop( operator, &StackPopData);
  41. first = StackPopData;
  42. //计算结果
  43. StackPopData = caculate(first, second, *p_str);
  44. //结果入栈
  45. StackPush( operator, StackPopData);
  46. }
  47. p_str++;
  48. }
  49. StackPop( operator, &StackPopData);
  50. printf( "计算结果为%d\n", StackPopData);
  51. return StackPopData;
  52. }


栈_第3张图片


4.中缀表达式转后缀表达式

思路:

    (1).初始化两个栈(一个用来运算operand,一个用来存放结果operand)

    (2).扫描字符串

  • 遇到操作数入栈
  • 遇到’(‘直接入栈
  • 遇到’)’,一直出栈,直到遇到(,将左括号出栈
  • 遇到其他操作符,先将这个操作符和用来运算的栈(operator)的栈顶元素比较,如果栈顶运算符的优先级较高,将栈顶运算符入存放结果的栈(operand),并将当前运算符入(operator)栈。




     
     
     
     
  1. //中缀转后缀
  2. char* SuffixToNifix(char* str) {
  3. //操作数栈
  4. PStack operand = (PStack) malloc( sizeof(struct Stack));
  5. StackInit(operand);
  6. //操作符栈
  7. PStack operator = (PStack) malloc( sizeof(struct Stack));
  8. StackInit( operator);
  9. char buffer;
  10. while (*str) {
  11. //判断是操作数还是操作符
  12. if (*str >= '0' && *str <= '9') {
  13. //操作数入栈
  14. StackPush(operand, *str);
  15. if(*(str + 1) < '0' || *(str + 1) > '9')
  16. if (StackTop(operand) != 0)
  17. StackPush(operand, 0);
  18. }
  19. else {
  20. /*if (StackTop(operand) != 0)
  21. StackPush(operand, 0);*/
  22. //扫描到操作符
  23. //判断操作符栈是否为空,为空直接入栈
  24. if ( 1 == StackEmpty( operator)) {
  25. StackPush( operator, *str);
  26. }
  27. else if ( '(' == *str) {
  28. //遇到左括号,直接入栈,左括号的优先级最高
  29. StackPush( operator, *str);
  30. }
  31. else if ( ')' == *str) {
  32. //遇到右括号,一直出栈,并压栈到操作数栈,直到把括号弹出
  33. while ( 1) {
  34. StackPop( operator, &buffer);
  35. if (buffer == '(')
  36. break;
  37. StackPush(operand, buffer);
  38. /*if (StackTop(operand) != 0)
  39. StackPush(operand, 0);*/
  40. }
  41. }
  42. else {
  43. //非空,则比较当前栈顶运算符和遇到的运算符的优先级
  44. char operatorTop = StackTop( operator);
  45. if (cmpPriority(operatorTop, *str) > 0 && operatorTop != '(') {
  46. //栈顶运算符优先级较高,弹出栈顶运算符,并压到操作数栈
  47. StackPop( operator, &buffer);
  48. StackPush(operand, buffer);
  49. StackPush( operator, *str);
  50. }
  51. else {
  52. //栈顶运算符优先级较低,当前运算符直接入栈
  53. StackPush( operator, *str);
  54. }
  55. }
  56. }
  57. str++;
  58. }
  59. char buf;
  60. while (StackPop( operator, &buf)) {
  61. StackPush(operand, buf);
  62. }
  63. while (StackPop(operand, &buf)) {
  64. StackPush( operator, buf);
  65. }
  66. while (StackPop( operator, &buf)) {
  67. printf( "%c", buf);
  68. }
  69. printf( "\n");
  70. return NULL;
  71. }


栈_第4张图片


5. 迷宫问题

思路:

非递归:

(1)入口点压栈。

(2)以左上右下的顺序判断周围有哪个坐标可以到达(数组的值设置为1)。

(3)遇到可以到达的坐标就把当前坐标设置为这个坐标,将当前坐标设置为不可达(数组的值设置为2),并把这个坐标压栈

(4)重复(2)(3)步。

(5)遇到了死胡同(周围都不可达),栈顶坐标出栈,并将弹出的坐标设置为当前坐标。

(6)判断是否到达了起点(无出口),判断是否到达了边界位置(非起点),到达边界跳出。未到达边界。

(7)重复(2)(3)步


     
     
     
     
  1. #include
  2. #include
  3. #include
  4. #define INIT_STACKSIZE 100
  5. #define WIDTH 10
  6. //设置当前坐标的状态,将当前坐标入栈
  7. #define SET_WENTSTATE_AND_PUSHSTACK \
  8. map[y][x] = 2;\
  9. loc._x = x;\
  10. loc._y = y;\
  11. StackPush(s, loc);\
  12. continue
  13. typedef struct Location {
  14. //坐标
  15. int _x;
  16. int _y;
  17. }Location;
  18. typedef Location DataType;
  19. typedef struct Stack {
  20. DataType* _array;
  21. int _top;
  22. //最大容量
  23. int _capacity;
  24. }*PStack, Stack;
  25. void StackInit(PStack s) {
  26. s->_array = (PStack) malloc( sizeof(Stack)*INIT_STACKSIZE);
  27. if (s->_array == NULL)
  28. exit( 0);
  29. s->_capacity = INIT_STACKSIZE;
  30. s->_top = 0;
  31. }
  32. void StackPush(PStack s, DataType loc) {
  33. assert(s);
  34. if (s->_top >= s->_capacity) {
  35. s->_array = (PStack) realloc(s->_array, ((s->_capacity)+ 10)* sizeof(Stack));
  36. if (s->_array == NULL)
  37. exit( 0);
  38. s->_capacity = s->_capacity + 10;
  39. }
  40. *(s->_array + s->_top) = loc;
  41. s->_top++;
  42. }
  43. int StackPop(PStack s, DataType* loc) {
  44. assert(s);
  45. if (!s->_top) {
  46. return 0;
  47. }
  48. --s->_top;
  49. *loc = *(s->_array + s->_top);
  50. return 1;
  51. }
  52. DataType StackTop(PStack s) {
  53. return *(s->_array + s->_top);
  54. }
  55. //判断是否到达边界
  56. int isBorder(int x, int y) {
  57. if (x == WIDTH - 1 || x == 0 || y == 0 || y == WIDTH - 1)
  58. return 1;
  59. return 0;
  60. }
  61. //判断是否回到了起点
  62. int isStart(int start_x, int start_y, int x, int y) {
  63. if (start_x == x && start_y == y)
  64. return 1;
  65. return 0;
  66. }
  67. //打印地图
  68. void showMap(int map[WIDTH][WIDTH]) {
  69. for ( int i = 0; i < WIDTH; i++) {
  70. for ( int j = 0; j < WIDTH; j++) {
  71. if ( map[i][j] == 0) {
  72. printf( "█");
  73. }
  74. else if( map[i][j] == 1){
  75. printf( " ");
  76. }
  77. else {
  78. printf( " *");
  79. }
  80. //printf("%d ", map[i][j]);
  81. }
  82. printf( "\n");
  83. }
  84. }
  85. void maze(int map[WIDTH][WIDTH], int start_x, int start_y) {
  86. PStack s = (PStack) malloc( sizeof(Stack));
  87. StackInit(s);
  88. //入口
  89. int x = start_x;
  90. int y = start_y;
  91. //将入口位置设置为已走过的状态
  92. map[y][x] = 2;
  93. //将当前坐标压栈,
  94. showMap( map);
  95. Location loc = { x, y };
  96. StackPush(s, loc);
  97. while ( 1) {
  98. int oldx = x;
  99. int oldy = y;
  100. //左
  101. if ( map[y][x - 1] == 1) {
  102. --x;
  103. SET_WENTSTATE_AND_PUSHSTACK; //宏:入栈和赋值当前坐标操作。
  104. }
  105. //上
  106. if ( map[y - 1][x] == 1) {
  107. --y;
  108. SET_WENTSTATE_AND_PUSHSTACK;
  109. }
  110. //右
  111. if ( map[y][x + 1] == 1) {
  112. ++x;
  113. SET_WENTSTATE_AND_PUSHSTACK;
  114. }
  115. //下
  116. if ( map[y + 1][x] == 1) {
  117. ++y;
  118. SET_WENTSTATE_AND_PUSHSTACK;
  119. }
  120. Location loc1;
  121. if (!StackPop(s, &loc1)) {
  122. if (isStart(start_x, start_y, oldx, oldy)) {
  123. printf( "迷宫无出口\n");
  124. break;
  125. }
  126. break;
  127. }
  128. //判断是否到达边界
  129. if (isBorder(x, y)) {
  130. //判断是否遇到起始位置
  131. showMap( map);
  132. break;
  133. }
  134. //遇到分叉点的处理,因为第二次到达分叉点的时候分叉点已经弹出。所以要求出分叉点的坐标
  135. if (oldx + 2 == loc1._x || oldy + 2 == loc1._y ||
  136. oldx - 2 == loc1._x || oldy - 2 == loc1._y
  137. ) {
  138. x = (oldx + loc1._x) / 2;
  139. y = (oldy + loc1._y) / 2;
  140. StackPush(s, loc1);
  141. }
  142. else {
  143. x = loc1._x;
  144. y = loc1._y;
  145. }
  146. }
  147. }
  148. //迷宫问题递归解法
  149. int ENDX = 0;
  150. int ENDY = 8;
  151. int mazeRecursion(int map[][WIDTH], int x, int y) {
  152. map[y][x] = 2;
  153. int isEnd = 0; //判断是不是终点
  154. if (ENDX == x && ENDY == y) {
  155. isEnd = 1;
  156. }
  157. //左
  158. if (isEnd != 1 && x >= 0 && map[y][x - 1] == 1) {
  159. if(mazeRecursion( map, x - 1, y) == 1)
  160. return 1;
  161. }
  162. //上
  163. if (isEnd != 1 && y >= 0 && map[y - 1][x] == 1) {
  164. if (mazeRecursion( map, x, y - 1) == 1)
  165. return 1;
  166. }
  167. //右
  168. if (isEnd != 1 && x < WIDTH && map[y][x + 1] == 1) {
  169. if (mazeRecursion( map, x + 1, y) == 1)
  170. return 1;
  171. }
  172. //下
  173. if (isEnd != 1 && y < WIDTH && map[y + 1][x] == 1) {
  174. if (mazeRecursion( map, x, y + 1) == 1)
  175. return 1;
  176. }
  177. //未到终点,但是没有路可以走了。
  178. if (isEnd == 0) {
  179. map[y][x] = 1;
  180. }
  181. //未到终点返回0。
  182. return isEnd;
  183. }



     
     
     
     
  1. int main() {
  2. int map[WIDTH][WIDTH] = {
  3. { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
  4. { 0, 0, 1, 1, 1, 0, 1, 0, 1, 0 },
  5. { 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
  6. { 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
  7. { 0, 0, 1, 0, 0, 0, 1, 0, 1, 0 },
  8. { 0, 0, 1, 1, 1, 0, 1, 0, 1, 0 },
  9. { 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 },
  10. { 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 },
  11. { 1, 1, 1, 0, 1, 1, 1, 1, 1, 0 },
  12. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  13. };
  14. printf( "非递归:\n");
  15. maze( map, 6, 0);
  16. /*printf("递归:\n");
  17. mazeRecursion(map, 6, 0);
  18. showMap(map);*/
  19. return 0;
  20. }


运行结果:


栈_第5张图片


栈_第6张图片






你可能感兴趣的:(C++)