数据结构与算法分析表栈和队列

Posted MenAngel

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法分析表栈和队列相关的知识,希望对你有一定的参考价值。

    介绍栈的相关知识:

 

    (2)栈ADT:

    2.1栈模型:

      栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈的顶(top)。对栈的基本操作有Push(进栈)和Pop(出栈),前者相当于插入,后者则是删除最后插入的元素。

      栈有时又叫做LIFO(后进先出表)。一般的栈模型是,存在某个元素位于栈顶,而该元素是唯一可见元素。

      

 

    2.2栈的实现:

      由于栈是一个表,所以任何实现表的方法都可以实现栈,我们将给出两种方法,一个使用指针,一个使用数组。

      1)栈的链表实现:

      栈的链表实现的例程:

struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode Stack;

int IsEmpty(Stack s);
Stack CreateStack(void);
void DisposeStack(Stack s);
void MakeEmpty(Stack s);
void Push(ElementType x,Stack s);
ElementType Top(Stack s);
void Pop(Stack s);

struct Node{
  ElementType Element;
  PtrToNode Next;
};

      栈的链表实现的简单实例:

      编写程序,从键盘输入10个数据放入栈中,然后从栈中依次弹出这些数据,并输出。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<math.h>
 4  
 5 struct Node{
 6   int Element;
 7   struct Node* Next;      
 8 };
 9 //定义一个指向结点类型变量的指针类型 
10 typedef struct Node *Stack;
11 Stack creatStack(){
12     Stack s;
13     s=malloc(sizeof(struct Node));
14     if(s==NULL)
15       printf("Out of space!");
16     s->Next=NULL;
17     return s;
18 }
19 void Push(int n,Stack s){
20     struct Node *temp;
21     temp=malloc(sizeof(struct Node));
22     if(temp==NULL)
23       printf("Out of Space!");
24     else{
25         temp->Element=n;
26         temp->Next=s->Next;
27         s->Next=temp; 
28     }
29 }
30 int IsEmpty (Stack s){
31     return s->Next==NULL;
32 }
33 int Top(Stack s){
34     struct Node *temp;
35     if(IsEmpty(s)){
36       printf("Empty stack");
37       return 0;        
38     }
39     else
40     return s->Next->Element;
41 }
42 void Pop(Stack s){
43   struct Node *temp;
44   if(IsEmpty(s))
45     printf("Empty stack");
46   else
47     temp=s->Next;
48     s->Next=s->Next->Next;
49     free(temp);    
50 }
51 void MakeEmpty(Stack s){
52     if(s==NULL){
53         printf("此栈为空,必须先创建一个栈!\\n");
54     }else{
55         while(!IsEmpty(s)){
56             Pop(s);
57         }
58     }
59 } 
60 int main(){
61     printf("请输入10个整数,压入栈中:\\n");
62     Stack s;
63     s=creatStack();
64     int temp;
65     int k;
66     for(k=0;k<10;k++){
67         //printf("请输入第%d个数\\n",k+1);
68         temp=rand()%100;
69         printf("Num[%d]=%2d  ",k+1,temp);  
70         Push(temp,s);   
71     }    
72     printf("\\n下面按照顺序弹出栈中所有元素并输出:\\n");
73     for(k=0;k<10;k++){
74       printf("第%2d个出栈的是%4d",k+1,s->Next->Element);
75       if((k+1)%5==0){
76           printf("\\n");
77       } 
78       Pop(s);        
79     }
80     return 0;
81 }

      2)栈的数组实现:

      栈的数组实现避免了指针并且可能是更加流行的解决方案。这种策略的唯一潜在危害是我们需要提前声明一个数组的大小。

      栈的数组实现中一个很大的问题是对空栈的Pop和对满栈的Push都将超出数组的界限并引起程序的崩溃,因此有时可能需要防止用于构造栈的数组的下标越界。

      栈的数组实现的例程:

#include<stdlib.h>
#include<stdio.h>

struct StackRecord;
typedef struct StackRecord *Stack;
typedef int ElementType;

int IsEmpty(Stack s);
int IsFull(Stack s);
Stack CreateStack(int MaxElements);
void  DisposeStack(Stack s);
void MakeEmpty(Stack s);
void Push(ElementType x,Stack s);
ElementType Top(Stack s);
void Pop(Stack s);
ElementType TopAndPop(Stack s);

#define EmptyTOS (-1)
#define MinStackSize (5)
struct StackRecord{
  int Capacity;
  int TopOfStack;
  ElementType *Array; 
};
void MakeEmpty(Stack s){
    s->TopOfStack=EmptyTOS;
}
int IsFull(Stack s){
    return s->TopOfStack==s->Capacity;
}
Stack CreateStack(int MaxElements){
    Stack s;
    if(MaxElements<MinStackSize){
        printf("所建的栈空间太小");
        MaxElements=5;
    }
    s=malloc(sizeof(struct StackRecord));
    s->Array=malloc(sizeof(ElementType)*MaxElements);
    s->Capacity=MaxElements;
    MakeEmpty(s);    
    return s;
}
void DisposeStack(Stack s){
    if(s!=NULL){
        free(s->Array);
        free(s);
    }
}
int IsEmpty(Stack s){
    return s->TopOfStack==EmptyTOS;
}
void Push(ElementType x,Stack s){
    if(!IsFull(s)){
      printf("栈空间已经用完了");
    }
    else
      s->Array[++s->TopOfStack]=x;
}
ElementType Top(Stack s){
    if(!IsEmpty(s))
      return s->Array[s->TopOfStack];
    printf("空栈");
    return 0;
}
void Pop(Stack s){
    if(IsEmpty(s))
        printf("空栈");
    else
        s->TopOfStack--;    
}
ElementType    TopAndPop(Stack s){
    if(!IsEmpty(s))
      return s->Array[s->TopOfStack--];
    printf("空栈");
    return 0;
}

      栈的数组实现的实例在此就不做介绍了,下面的后缀表达式的实例涉及到了。

 

    2.4栈的应用: 

      1)平衡符号:

        编译器检查你的程序的语法错误,但是常常由于缺少一个符号(如遗漏一个花括号或者注释起始符)引起编译器列出上百行的诊断,而真正的错误却没有找出。

        在这种情况下一个有用的工具就是检验是否每件事情都能成对出现的一个程序:

        做一个空栈。读入字符指到文件尾,如果字符是一个开放的符号,则将推入栈中。如果是一个封闭符号,则当栈为空时报错,否则将栈元素推出。在文件尾,如果栈非空则报错。

      2)后缀表达式:

       主要包括后缀表达式的计算中缀到后缀的转换:  

   编写程序,从键盘输入一个中缀表达式,利用栈先转换为后缀表达式,然后计算该后缀表达式的结果,要求

  (1)用栈的数组实现完成

  (2)为简单起见,表达式中的操作数为非负整数

  (3)操作符仅包括加(+)、乘(*、左括号(、右括号)

  (4)若后缀表达式正确,输出计算结果;若表达式有误,输出错误提示信息

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4  
  5 #define EmptyTOS (-1)
  6 #define MinStackSize 5
  7  
  8 struct StackRecord{
  9   int Capacity;//能存元素最大量
 10   int TopOfStack;//记录新插入的元素所在数组中的位置
 11   char Array[20][5];//字符串数组,每个字符串的大小最多为5 
 12 };
 13 typedef struct StackRecord *Stack;
 14 
 15 void MakeEmpty(Stack s){
 16     s->TopOfStack=EmptyTOS;
 17 }
 18 
 19 Stack CreateStack(int MaxElement){
 20     Stack s;  
 21     if(MaxElement<MinStackSize){
 22         printf("要创建的栈太小,应大于5。\\n");
 23         exit(0); 
 24     }else{        
 25       s=malloc(sizeof(struct StackRecord));
 26       s->Capacity=MaxElement;
 27       MakeEmpty(s);    
 28     }
 29     return s; 
 30 }
 31 
 32 //判断栈是否为空栈 
 33 int isEmpty(Stack S){
 34     return S->TopOfStack==EmptyTOS; 
 35 }
 36 //判断是否满了,当为1是满了,为0是表示未满 
 37 int IsFull(Stack S){
 38     if(S->TopOfStack+1>=S->Capacity){
 39         return 1;
 40     }else
 41     return 0;
 42 }
 43 //压栈 
 44 void Push(char *x,Stack S){
 45  if(IsFull(S)){
 46      printf("栈已经满了!\\n");
 47  }else{
 48      strcpy(S->Array[++S->TopOfStack],x);
 49  }     
 50 }
 51 //只获得头元素 
 52 char *Top(Stack S){
 53     if(isEmpty(S)){
 54         printf("此栈为空,无法取栈头元素!\\n");
 55         exit(0);
 56     }else{
 57         return S->Array[S->TopOfStack]; 
 58     }
 59 }
 60 //只删除头元素 
 61 void Pop(Stack S){
 62     if(isEmpty(S)){
 63         printf("此栈为空,无法去除栈头元素!\\n");
 64     }else{
 65         S->TopOfStack--; 
 66     }
 67 }
 68 //获取头元素并删除 
 69 char *PopAndTop(Stack S){
 70     if(isEmpty(S)){
 71         printf("此栈为空,无法执行获取栈头元素和去除栈头元素!\\n");
 72         exit(0);
 73     }else{
 74         return S->Array[S->TopOfStack--];
 75     }
 76 }
 77 //释放栈空间 
 78 void DisposeStack(Stack s){
 79     if(s!=NULL){
 80         free(s); 
 81     }
 82 } 
 83 void printStack(Stack s){
 84     int i;
 85     for(i=0;i<=s->TopOfStack;i++){
 86         printf("%s ",s->Array[i]);
 87     }    
 88 }
 89 
 90 int isNumber(char p){
 91     if(p>=\'0\'&&p<=\'9\'){
 92       return 1;    
 93     }else
 94     return 0;
 95 }
 96 int isOperator(char *p){     
 97     //当长度为1,且不为从0到9的数时,才是操作符 
 98     if(isNumber(p[0])){
 99         return 0;
100     }else
101     return 1; 
102 } 
103 int exist(char *p,Stack temp){
104     int i;
105     for(i=0;i<=temp->TopOfStack;i++){
106         if(strcmp(temp->Array[i],p)==0){
107             return 1;
108         }
109     }
110     return 0;
111 }
112 //位置是从栈头开始计算,所以谁小谁离栈比较远 
113 int LastPosition(char *p,Stack temp){
114     int i;
115     if(exist(p,temp)){
116       for(i=temp->TopOfStack;i>=0;i--){
117         if(strcmp(temp->Array[i],p)){
118             return i;
119         }
120       }    
121     }
122     else{
123       //这个应该执行不到 
124       //printf("临时栈没有%s这个操作符\\n",p); 
125     }
126 }
127 void turnInto(Stack A,Stack B){
128     Stack temp=CreateStack(10);
129     int i;
130     for(i=0;i<=A->TopOfStack;i++){
131         //如果不是操作符,直接输出到后缀表达式 
132         if(!isOperator(A->Array[i])){
133             strcpy(B->Array[++B->TopOfStack],A->Array[i]);
134             //printf("输出中存的有:%s\\n",A->Array[i]);
135         }else{
136             char c=A->Array[i][0];
137         //当是操作符时,有可能是右括号 
138             if(c==\')\'){
139                 //printStack(temp);
140                 //当两个字符串不相等时 
141                 while(!strcmp( "(",Top(temp) )==0){
142                   strcpy(B->Array[++B->TopOfStack],PopAndTop(temp));
143                   //printf("输出中存的有:%s\\n",B->Array[B->TopOfStack]);    
144                 }
145                 Pop(temp);
146             }else if(c==\'(\'){
147                 //Push("(",temp);
148                 //printf("%s",A->Array[i]);
149                 Push(A->Array[i],temp);
150             }else if(c==\'+\'){
151                 //如果临时栈中有乘号
152                 if(exist("*",temp)){
153                     //printStack(temp); 
154                     //当没有左括号或者有,但左括号在乘号的左边 
155                     if( !exist("(",temp) || ( exist("(",temp)&& LastPosition("(",temp)>LastPosition("*",temp) ) ){
156                         //printf("%d<%d",LastPosition("(",temp),LastPosition("*",temp));
157                         //将乘号及以后的操作符输出到后缀表达式 
158                         while(Top(temp)[0]!=\'*\'){
159                           //printf("%s",Top(temp));
160                           strcpy( B->Array[++B->TopOfStack],PopAndTop(temp) );
161                           //printf("输出中存的有:%s\\n",A->Array[i]);
162                         }
163                         strcpy(B->Array[++B->TopOfStack],PopAndTop(temp));
164                         //printf("输出中存的有:%s\\n",B->Array[B->TopOfStack]);
165                         Push(A->Array[i],temp);
166                         //printStack(temp); 
167                     }else
168                     Push(A->Array[i],temp);
169                 }
170                 else{
171                   //如果不存在乘号 
172                   Push(A->Array[i],temp);    
173                 }                
174            }else if(c==\'*\'){
175             strcpy(temp->Array[++temp->TopOfStack],A->Array[i]);    
176            }            
177         }
178     }
179     while(!isEmpty(temp)){
180         strcpy(B->Array[++B->TopOfStack],PopAndTop(temp)); 
181     }    
182 }
183 
184 void calculate(Stack A){
185     //定义一个辅助计算后缀表达式的栈 
186     Stack as=CreateStack(10);
187     int result,i;
188     int a,b,temp;
189     char str[5];
190     for(i=0;i<=A->TopOfStack;i++){
191         //printf("%s\\n",A->Array[i]);
192         if(isNumber(A->Array[i][0])){
193             Push(A->Array[i],as);
194         }else{
195             int a=atoi(PopAndTop(as));
196             int b=atoi(PopAndTop(as));
197             char c=A->Array[i][0];
198             //putchar(c);
199             switch(c){
200                 case \'+\':temp=a+b;break;
201                 case \'*\':temp=a*b;break;
202                 default:printf("不知名错误!\\n");
203             }
204             itoa(temp,str,10);
205             Push(str,as);
206          }    
207     }
208 
209     if(as->TopOfStack<=0){
210         strcpy(str,Top(as));
211         result=atoi(str);
212         printf("计算的结果为:%3d\\n",result); 
213     }
214 }
215 
216 int main(){
217     printf("请输入一个中缀表达式(最多30个字符的字符串),只包含非负整数,+号,-号和()两个括号!\\n数据结构与算法分析表栈和队列

表栈和队列

数据结构和算法分析 表栈和队列

数据结构和算法分析(10)表栈和队列的实际应用

数据结构与算法第三章:表栈和队列

数据结构和算法 数据结构基础线性表栈和队列数组和字符串