当前位置:   article > 正文

数据结构——栈_栈是一种非常重要的特殊线性数据结构,有着广泛的应用。假设栈adt的数据元素为整数

栈是一种非常重要的特殊线性数据结构,有着广泛的应用。假设栈adt的数据元素为整数

栈是一种重要的数据结构,它广泛应用于各种软件系统中,这种数据结构与线性表有密切的联系。从逻辑上看,栈属于线性结构,是一种特殊的线性表。其特殊性在于栈的基本操作是线性表操作的子集,它是限定公在表尾进行插入或删除操作的线性表,是操作受限的线性表。

学习要点:

1.了解栈的概念。

2.掌握栈的数据结构定义方法和基本运算的实现方法。

3.能够使用栈这种数据结构来解决具体的问题

栈的定义

栈(Stack)是一种特殊的线性表,是限定公在表尾进行插入或删除操作的线性表。栈的表尾称为栈顶(top),处于栈顶位置的数据元素称为栈顶元素。栈的表头称为栈底(bottom),处于栈底位置的数据元素称为栈底元素。不含任何元素的表称为空栈。

下面来看栈的使用代码实现

1. 栈的顺序存储的实现

【问题描述】

实现栈的顺序存储结构的基本运算。

【算法描述】

要求通过具体的算法来实现栈的顺序存储。首先建立栈的顺序结构,对栈的各个运算的算法做详细的描述,然后在主函数中通过函数调用实现顺序栈的置空、数据元素进栈、出栈等。

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. #include<conio.h>
  4. #define ERROR 0
  5. #define TRUE 1
  6. #define FALSE 0
  7. #define OK 1
  8. #define EQUAL 1
  9. #define OVERFLOW -1
  10. #define STACK_INIT_SIZE 100
  11. #define STACKINCREMENT 10
  12. typedef int ElementType ;
  13. struct STU
  14. {
  15. char name[20];
  16. char stuno[10];
  17. int age;
  18. int score;
  19. };
  20. typedef struct STU SElemType;
  21. struct STACK
  22. {
  23. SElemType *base;
  24. SElemType *top;
  25. int stacksize;
  26. };
  27. typedef struct STACK SqStack;
  28. typedef struct STACK *pSqstack;
  29. ElementType InitStack(SqStack **S);
  30. void DestroyStack(SqStack *S);
  31. void ClearStack(SqStack *S);
  32. ElementType StackEmpty(SqStack S);
  33. int StackLength(SqStack S);
  34. ElementType GetTop(SqStack S,SElemType *e);
  35. ElementType Push(SqStack *S,SElemType e);
  36. ElementType Pop(SqStack *S,SElemType *e);
  37. ElementType StackTraverse(SqStack S,ElementType (*visit)());
  38. ElementType InitStack(SqStack **S) /* 栈的初始化 */
  39. {
  40. (*S)=(SqStack *) malloc(sizeof(SqStack));
  41. (*S)->base=(SElemType *)malloc(STACK_INIT_SIZE *sizeof(SElemType));
  42. if(!(*S)->base)
  43. exit(OVERFLOW);
  44. (*S)->top=(*S)->base;
  45. (*S)->stacksize=STACK_INIT_SIZE;
  46. return OK;
  47. }
  48. void DestroyStack(SqStack *S) /* 栈的释放 */
  49. {
  50. free(S->base);
  51. free(S);
  52. }
  53. void ClearStack(SqStack *S) /* 栈的置空 */
  54. {
  55. S->top=S->base;
  56. }
  57. ElementType StackEmpty(SqStack S)
  58. {
  59. if(S.top==S.base)
  60. return TRUE;
  61. else
  62. return FALSE;
  63. }
  64. int StackLength(SqStack S)
  65. {
  66. int i;
  67. SElemType *p;
  68. i=0;
  69. p=S.top;
  70. while(p!=S.base)
  71. {
  72. p++;
  73. i++;
  74. }
  75. return i;
  76. }
  77. ElementType GetTop(SqStack S,SElemType *e)
  78. {
  79. if(S.top==S.base) return ERROR;
  80. *e=*(S.top-1);
  81. return OK;
  82. }
  83. ElementType Push(SqStack *S,SElemType e)
  84. {
  85. *(S->top++)=e;
  86. return OK;
  87. }
  88. ElementType Pop(SqStack *S,SElemType *e)
  89. {
  90. if(S->top==S->base) return ERROR;
  91. *e=*--S->top;
  92. return OK;
  93. }
  94. ElementType StackPrintElem(SElemType * e)
  95. {
  96. printf("%s %s %d %d\n",e->name,e->stuno,e->age,e->score);
  97. }
  98. ElementType StackTraverse(SqStack S, ElementType (*visit)())
  99. {
  100. while(S.top!=S.base)
  101. visit(--S.top);
  102. }
  103. int main(void) /* 顺序栈的主函数 */
  104. {
  105. SElemType e;
  106. SqStack *Sa;
  107. printf("\n\n------------SqStack Demo is running...-----------\n\n");
  108. printf("First is Push function.\n");
  109. InitStack(&Sa);
  110. strcpy(e.name,"stu1");
  111. strcpy(e.stuno,"100001");
  112. e.age=80;
  113. e.score=1000;
  114. printf("Now Stack is Empty.\n");
  115. StackTraverse(*Sa,StackPrintElem);
  116. Push(Sa,e);
  117. printf("Now Stack has one element.\n");
  118. StackTraverse(*Sa,StackPrintElem);
  119. strcpy(e.name,"stu3");
  120. strcpy(e.stuno,"100002");
  121. e.age=80;
  122. e.score=1000;
  123. Push(Sa,e);
  124. printf("Now Stack has another element.\n");
  125. StackTraverse(*Sa,StackPrintElem);
  126. printf("Now Pop Stack,the top elem put into variable e.\n");
  127. Pop(Sa,&e);
  128. printf("%s\n%s\n%d\n%d\n",e.name,e.stuno,e.age,e.score);
  129. printf("Let's see the left of Stack's elem:\n");
  130. StackTraverse(*Sa,StackPrintElem);
  131. printf("\n\n\nWelcom to visit http://zmofun.topcool.net\n\n");
  132. return 0;
  133. }

运行结果

 

2. 栈的链式存储的实现

【问题描述】

链栈是栈的另一种存储方式,要求通过具体的算法实现链栈的倒置、出栈等运算。

【算法描述】

在设计链栈的基本运算之前,首先定义链栈的存储类型、结点类型,然后分别设计各种运算的具体函数。最后在主函数中实现链栈的各种运算时,分别调用相应的函数即可。

  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include <stdlib.h>
  4. #define NULL 0
  5. typedef char ElementType;
  6. typedef struct stacknode
  7. {
  8. ElementType data;
  9. struct stacknode *next;
  10. }StackNode;
  11. typedef struct
  12. {
  13. StackNode *top;
  14. }LinkStack;
  15. void InitStack(LinkStack *s)
  16. {
  17. s->top=NULL;
  18. }
  19. int StackEmpty(LinkStack *s)
  20. {
  21. return s->top==NULL;
  22. }
  23. /* 链栈的节点是动态分配的,无须判断 Full(上溢) */
  24. void Push(LinkStack *s, ElementType x)
  25. {
  26. StackNode *p;
  27. p=malloc(sizeof(StackNode));
  28. p->next=s->top; /* 由于是在栈顶 PUSH,所以要指向栈顶 */
  29. p->data=x;
  30. s->top=p; /* 插入 */
  31. }
  32. ElementType Pop(LinkStack *s)
  33. {
  34. ElementType x;
  35. StackNode *p=s->top; /* 指向栈顶 */
  36. if (StackEmpty(s))
  37. {
  38. printf("栈为空,不能出栈...\n");
  39. exit(-1);
  40. }
  41. x=p->data;
  42. s->top=p->next; /* 当前的栈顶指向原栈的 next */
  43. free(p);
  44. return x;
  45. }
  46. ElementType StackTop(LinkStack *s)
  47. {
  48. if (StackEmpty(s))
  49. {
  50. printf("栈为空,不能出栈...\n");
  51. exit(-1);
  52. }
  53. return s->top->data;
  54. }
  55. void Disp(LinkStack *s)
  56. {
  57. StackNode *p=s->top;
  58. printf("=======================================\n");
  59. while (p!=NULL)
  60. {
  61. printf("\n%c",p->data);
  62. p=p->next;
  63. }
  64. printf("=======================================\n");
  65. }
  66. void RevStack(LinkStack *s)
  67. {
  68. int i, n=0;
  69. char dat[50];
  70. while(!StackEmpty(s))
  71. {
  72. dat[n]=Pop(s); /* 保存退栈后的数据到数组 */
  73. n++;
  74. }
  75. for (i=0;i<n;i++)
  76. Push(s,dat[i]);
  77. }
  78. int main(void)
  79. {
  80. LinkStack * s=(LinkStack *)malloc(sizeof(LinkStack));
  81. char ch,ch2,ch3;
  82. printf("================= 链栈操作 DEMO =================\nn");
  83. InitStack(s);
  84. printf("依次压栈 a,b,c,d,e 后,栈中的数据为:\n");
  85. Push(s,'a');
  86. Push(s,'b');
  87. Push(s,'c');
  88. Push(s,'d');
  89. Push(s,'e');
  90. Disp(s);
  91. printf("\n 将此栈倒置,栈中的数据序列为:\n");
  92. RevStack(s);
  93. Disp(s);
  94. ch=Pop(s);
  95. printf("\n 出栈操作开始,第一次出栈得到的数据:%c",ch);
  96. ch2=Pop(s);
  97. printf("\n 第二次出栈得到的数据:%c",ch2);
  98. ch3=StackTop(s);
  99. printf("\n 此时的栈顶元素为:%c",ch3);
  100. return 0;
  101. }

运行结果:

 

3. 计算表达式的值

【问题描述】

计算用运算符后缀法表示的表达式的值。后缀表达式也称逆波兰表达式,比中缀表达式计算起来更方便简单些,中缀表达式计算存在着括号的匹配问题,所以在计算表达式值时一般都是先转换成后缀表达式,再用后缀法计算表达式的值。如表达式(a+b*c)/d-e 用后缀法表示应为 abc*+d/e-1。只考虑四则算术运算,且假设输入的操作数均为 1 位十进制数(0~9),并且输入的后缀形式表达式不含语法错误。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define add 43
  4. /* 运算符加号'+'的 ASCII 码 */
  5. #define subs 45
  6. /* 运算符减号'-'的 ASCII 码 */
  7. #define mult 42
  8. /* 运算符乘号'*'的 ASCII 码 */
  9. #define div 47
  10. /* 运算符除号'/'的 ASCII 码 */
  11. #define MAXSIZE 100
  12. typedef struct
  13. {
  14. int stkdata[MAXSIZE];
  15. /* 用数组来表示栈空间,定义长度为 MAXSIZE 的堆栈 */
  16. int top ;
  17. /* 栈顶 */
  18. }STKzone;
  19. typedef STKzone *STK;
  20. typedef enum{ok,error} status;
  21. STKzone expSTKzone;
  22. STK expSTK;
  23. STK initSTK(STKzone *stack_zone)
  24. {
  25. /* 执行栈初始化,建栈指针 */
  26. STK p;
  27. p=stack_zone;
  28. p->top=0;
  29. return p;
  30. }
  31. status push(int *term,STK pstk)
  32. {
  33. /* 将一结构型数据送入栈中 */
  34. if(pstk->top==MAXSIZE)
  35. return error; /* 栈满,进栈失败 */
  36. pstk->stkdata[pstk->top] =*term;
  37. (pstk->top)++;/* 栈顶指针移动 */
  38. return ok;
  39. }/* push */
  40. bool emptySTK(STK pstk)
  41. {
  42. return(pstk->top==0);
  43. }
  44. status pop(int *pdata, STK pstk)
  45. {
  46. /* 从栈中取出一结构型数据 */
  47. if(emptySTK(pstk))
  48. return error;
  49. (pstk->top)--; /* 退栈 */
  50. *pdata =pstk->stkdata[pstk->top];
  51. return ok;
  52. }
  53. void synerror()
  54. {
  55. printf("\n 表达式语法错!");
  56. exit(-1);
  57. }
  58. int eval(char tag,int a1,int a2)
  59. {
  60. switch(tag)
  61. {
  62. case add:return(a1+a2);
  63. case subs:return(a1-a2);
  64. case mult:return(a1*a2);
  65. case div:return(a1/a2);
  66. }
  67. }
  68. int main()
  69. {
  70. char c;
  71. int opd1,opd2,temp,c1;
  72. expSTK=initSTK(&expSTKzone);
  73. printf("\n 后置表达式: ");
  74. while((c=getchar())!='\n')
  75. {
  76. if(c== ' ')
  77. continue;
  78. if((c>47)&&(c<58))
  79. /* 判断是否是 0~9 的字符 */
  80. {
  81. putchar(c);
  82. c1=c-48;
  83. /* 把输入的字符型数字转换成数字 */
  84. if(push(&c1,expSTK)==error) /* 运算分量进栈 */
  85. {
  86. printf("\n 表达式太长\n");
  87. exit(-1);
  88. }
  89. }
  90. else if((c==add)||(c==subs)||(c==mult)||(c==div))
  91. {
  92. putchar(c);
  93. if(pop(&opd1,expSTK)==error) /* 将运算量 1 出栈 */
  94. synerror();
  95. if(pop(&opd2,expSTK)==error) /* 将运算量 2 出栈 */
  96. synerror();
  97. temp=eval(c,opd2,opd1); /* 计算得到结果 */
  98. push(&temp,expSTK); /* 将运算结果进栈 */
  99. }
  100. else synerror(); /* 出现非法字符 */
  101. } /* while */
  102. if(pop(&opd1,expSTK)==error) synerror();
  103. if(!(emptySTK(expSTK))) synerror();
  104. printf("=%-3d\n",opd1);
  105. return 0;
  106. }

运行结果:

 

4. 递归程序设计实训例题:求 Fibonacci 数列函数的实现前 n 项的值,n 由键盘输入,每行输出 4 项。

 

【问题描述】

由题意可知,Fibonacci 数列的第一项、第二项的值都为 1,从第三项起,每一项的值均是其前面两项值之和。

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. long fib(int i)
  4. {
  5. if(i==1||i==2)
  6. return(1);
  7. else
  8. return(fib(i-1)+fib(i-2));
  9. }
  10. int main()
  11. {
  12. int i,n;
  13. long fib();
  14. printf("Please input fibnacci number:");
  15. scanf("%d",&n);
  16. for(i=1;i<=n;i++)
  17. {
  18. printf("fib(%d)=%2ld ",i,fib(i));
  19. if(i%4==0)
  20. printf("\n");
  21. }
  22. return 0;
  23. }

运行结果:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/641323
推荐阅读
相关标签
  

闽ICP备14008679号