码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-07-09 23:38:56      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

    在接下来的几篇博文中,将介绍表、栈、队列在编程实践中的应用。

 

    (1)表达式求值:

    输入一个中缀表达式,操作符包括(+ - * / ^)。转化为后缀表达式之后并计算表达式的值:

    要求:

      1.输入的中缀表达式必须是一个完整的字符串;

      2.不限制数字的位数和正负,负数用()括起来;

    代码如下:

  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[30][5];//字符串数组,每个字符串的大小最多为5 
 12 };
 13 typedef struct StackRecord *Stack;
 14 
 15 void MakeEmpty(Stack s){
 16     s->TopOfStack=EmptyTOS;
 17 }
 18 Stack CreateStack(int MaxElement){
 19     Stack s;  
 20     if(MaxElement<MinStackSize){
 21         printf("要创建的栈太小,应大于5。\n");
 22         exit(0); 
 23     }else{        
 24       s=malloc(sizeof(struct StackRecord));
 25       s->Capacity=MaxElement;
 26       MakeEmpty(s);    
 27     }
 28     return s; 
 29 }
 30 //判断栈是否为空栈 
 31 int IsEmpty(Stack S){
 32     return S->TopOfStack==EmptyTOS; 
 33 }
 34 //判断是否满了,当为1是满了,为0是表示未满 
 35 int IsFull(Stack S){
 36     if(S->TopOfStack+1>=S->Capacity){
 37         return 1;
 38     }else
 39     return 0;
 40 }
 41 //压栈 
 42 void Push(char *x,Stack S){
 43  if(IsFull(S)){
 44      printf("栈已经满了!\n");
 45  }else{
 46      strcpy(S->Array[++S->TopOfStack],x);
 47  }     
 48 }
 49 //只获得头元素 
 50 char *Top(Stack S){
 51     if(IsEmpty(S)){
 52         printf("此栈为空,无法取栈头元素!\n");
 53         exit(0);
 54     }else{
 55         return S->Array[S->TopOfStack]; 
 56     }
 57 }
 58 //只删除头元素 
 59 void Pop(Stack S){
 60     if(IsEmpty(S)){
 61         printf("此栈为空,无法去除栈头元素!\n");
 62     }else{
 63         S->TopOfStack--; 
 64     }
 65 }
 66 //获取头元素并删除 
 67 char *PopAndTop(Stack S){
 68     if(IsEmpty(S)){
 69         printf("此栈为空,无法执行获取栈头元素和去除栈头元素!\n");
 70         exit(0);
 71     }else{
 72         return S->Array[S->TopOfStack--];
 73     }
 74 }
 75 //释放栈空间 
 76 void DisposeStack(Stack s){
 77     if(s!=NULL){
 78         free(s); 
 79     }
 80 } 
 81 void printStack(Stack s){
 82     int i;
 83     for(i=0;i<=s->TopOfStack;i++){
 84         printf("%s ",s->Array[i]);
 85     }    
 86 }
 87 //位置是从栈头开始计算,所以谁小谁离栈顶比较远 
 88 int LastPosition(char *p,Stack temp){
 89     int i;
 90     if(exist(p,temp)){
 91       for(i=temp->TopOfStack;i>=0;i--){
 92         if(strcmp(temp->Array[i],p)){
 93             return i;
 94         }
 95       }    
 96     }
 97     else{
 98       printf("临时栈没有%s这个操作符\n",p);
 99       return -1; 
100     }
101 }
102 int IsNumber(char p){
103     if(p>=0&&p<=9){
104       return 1;    
105     }else
106     return 0;
107 }
108 //由于这里允许负数的存在,所以与之前的函数不同 
109 int IsOperator(char *p){//这个函数是给turnInto函数使用的 
110     //当长度不为1.肯定是数字,不是操作符 
111     if(p[1]!=\0){
112         return 0;
113     }     
114     //当长度为1,且不为从0到9的数时,才是操作符 
115     if(IsNumber(p[0])){
116         return 0;
117     }else
118     return 1; 
119 }
120 int exist(char *p,Stack temp){
121     int i;
122     for(i=0;i<=temp->TopOfStack;i++){
123         if(strcmp(temp->Array[i],p)==0){
124             return 1;
125         }
126     }
127     return 0;
128 }
129 //用这个递归提取函数明显比以前用的顺序处理要好得多 
130 void handleString(char *s,Stack    s_center){
131     //printf("即将操作的字符串%s\n",s);
132     int i=0;
133     int flag=-1;//当递归调用这个函数,上一个函数的flag会影响下一个函数的flag值,所以最好每次用时都初始化,而且函数段中每次用flag都最好先赋初值 
134     char temp[5];
135     if(s[0]==\0){
136         return;
137     }
138     if(s[i]==(&&s[i+1]==-){//处理类似1.(-34*76+21)-12或者2.(-43)+76这种形式的表达式字符串
139       flag=0; 
140       temp[flag]=-;
141       i=i+2;//i指到-号后的第一个数字 
142       while(IsNumber(s[i])){
143           temp[++flag]=s[i];
144           temp[flag+1]=\0;
145           i++;
146       }//如果数字过后的符号不是右括号,类似1 
147       if(s[i]!=)){
148           Push("(",s_center);
149           Push(temp,s_center);
150         s=s+i;
151         handleString(s,s_center); 
152       }else{//等于右括号,类似2 
153         Push(temp,s_center);
154         i++;
155         s=s+i;
156         handleString(s,s_center); 
157         }
158    } 
159    //如果字符串的开头是是数字,就将这一串数字压栈,并将数字后的第一个操作符压栈 
160      else//else不能少,这里是为了在一次调用此函数时只能执行一次操作,他们是互斥关系 
161      if(IsNumber(s[i])){
162        flag=-1;
163        while(IsNumber(s[i])){
164           temp[++flag]=s[i];
165           temp[flag+1]=\0;
166           i++;
167        }
168        Push(temp,s_center);
169        s=s+i;
170        handleString(s,s_center); 
171     }
172     else
173     if(!IsNumber(s[0])) {
174          temp[0]=s[0];
175          temp[1]=\0;
176          Push(temp,s_center);
177          handleString(s+1,s_center);
178     }
179 }
180 int Max(int a,int b){
181     return a>b?a:b;
182 } 
183 void turnInto(Stack A,Stack B){
184     Stack s_temp=CreateStack(15);
185     int i;int max;int leftbracketPosition;
186     for(i=0;i<=A->TopOfStack;i++){
187       //printStack(s_temp);printf("\n");
188       //如果不是操作符,直接输出到后缀表达式 
189       if(!IsOperator(A->Array[i])){
190         strcpy(B->Array[++B->TopOfStack],A->Array[i]);
191         //printf("输出中存的有:%s\n",A->Array[i]);
192       }else{
193         char c=A->Array[i][0];
194         //printf("\n操作的字符是第%d个%c\n",i+1,A->Array[i][0]); 
195         switch(c){
196           case (:{
197                       Push(A->Array[i],s_temp);
198                       break;
199                    }
200           case ):{
201                       while(!strcmp( "(",Top(s_temp) )==0){
202                         strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));
203                       }
204                       Pop(s_temp);
205                       break;
206                    }
207           case +:
208           case -:{
209                       if(exist("(",s_temp)){//如果存在左括号,将左括号右侧全部运算符弹出 
210                         while(Top(s_temp)[0]!=(){
211                           strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));
212                         }
213                       Push(A->Array[i],s_temp);          
214                       }else{//如果不存在左括号,将栈中所有元素弹出 
215                         while(!IsEmpty(s_temp)){
216                           strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));    
217                         }
218                       Push(A->Array[i],s_temp);        
219                       }
220                       break;
221                    }
222           case *:
223           case /:{
224                       if(IsEmpty(s_temp)){
225                           Push(A->Array[i],s_temp);
226                       }
227                       else{
228                         if(exist("(",s_temp)){
229                           leftbracketPosition=LastPosition("(",s_temp);
230                           if(exist("/",s_temp)||exist("*",s_temp)){
231                             max=Max(LastPosition("/",s_temp),LastPosition("*",s_temp));
232                           if(max>leftbracketPosition){//表明符号在左括号右侧 
233                             while(Top(s_temp)[0]!=* || Top(s_temp)[0]!=/){
234                               strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );      
235                             }
236                             strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));
237                             Push(A->Array[i],s_temp);
238                           }else{//符号在左括号左侧 
239                             Push(A->Array[i],s_temp); 
240                           }    
241                         }else{//存在左括号,但既不存在乘号也不存在除号,判断此时有没有乘方号 
242                         //如果有乘方号,且乘方号在左括号右侧 
243                           if(exist("^",s_temp)&&(LastPosition("^",s_temp)>leftbracketPosition)){
244                             strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );
245                             Push(A->Array[i],s_temp);       
246                           }else{//不存在乘方号或者存在乘方号,但乘方号在左括号的左侧 
247                             Push(A->Array[i],s_temp);
248                           }        
249                         }    
250                         }else{//不存在左括号时,只要临时栈中有乘号或除号就不可能再有乘方号 
251                           if(exist("*",s_temp)||exist("/",s_temp)){
252                             while(Top(s_temp)[0]!=*&&Top(s_temp)[0]!=/){
253                             strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );
254                             }
255                             strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));
256                             Push(A->Array[i],s_temp);    
257                           }else{//表示既没有左括号也没有乘号或除号,此时考虑栈中有没有乘方号 
258                             if(exist("^",s_temp)){//如果有乘方号,肯定在栈顶 
259                               strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );
260                               Push(A->Array[i],s_temp);       
261                             }else{
262                               Push(A->Array[i],s_temp);    
263                             } 
264                           }//不存在*或/的结束 
265                         }//不存在左括号的结束 
266                       }    
267                       break;
268                     }
269           case ^:{
270                       if(IsEmpty(s_temp)){
271                            Push(A->Array[i],s_temp);
272                       }else{                          
273                       //最高优先级,但临时栈中有可能还有乘方号,要把临时栈中与当前操作符有相同优先级的并在左括号的右边的符号弹出 
274                       if(!exist("^",s_temp)){
275                         strcpy(s_temp->Array[++s_temp->TopOfStack],A->Array[i]);
276                         break;    
277                       }else{
278                         if(exist("(",s_temp)&& ( LastPosition("(",s_temp)<LastPosition("^",s_temp) ) ){
279                             while(Top(s_temp)[0]!=^){
280                               //printf("%s",Top(temp));
281                               strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );
282                               //printf("输出中存的有:%s\n",A->Array[i]);
283                             }
284                             strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp));
285                             //printf("输出中存的有:%s\n",B->Array[B->TopOfStack]);
286                             Push(A->Array[i],s_temp);
287                             //printStack(temp); 
288                         }else{//包括不存在左括号和存在左括号且左括号在^右边的情况 
289                            if(!exist("(",s_temp)){
290                              strcpy( B->Array[++B->TopOfStack],PopAndTop(s_temp) );
291                              Push(A->Array[i],s_temp);           
292                            }else 
293                              strcpy(s_temp->Array[++s_temp->TopOfStack],A->Array[i]);    
294                            }    
295                         }     
296                      } 
297                      break;             
298                   }
299           default:printf("未知错误\n");    
300         }//switch语句的结束        
301       }//如果是操作符的结束 
302     }//for循环结束 
303     while(!IsEmpty(s_temp)){
304         strcpy(B->Array[++B->TopOfStack],PopAndTop(s_temp)); 
305     }    
306 }
307 //利用斐波那契数快速求幂 
308 unsigned long FB_QiuMi(int x,int n){
309     if(n<=2){
310         //printf("不用求幂公式!\n");
311         switch(n){
312             case 1:return x;
313             case 2:return x*x;
314         }
315     }
316     //记录斐波那契数列的下标 
317     int N=0;    
318     int f=1;
319     int temp;
320     int flag=f+1; 
321     while(flag<=n){
322         temp=flag;
323         flag=flag+f;
324         f=temp;
325         N++; 
326     }
327     int less=n-temp;
328     int i;
329     unsigned long result=x;
330     flag=x;
331     for(i=0;i<N;i++){
332         temp=result;
333         result=result*flag;
334         flag=temp;
335     } 
336     while(less>0){
337         result=result*x;
338         less--;
339     }
340     return result;
341 } 
342 void Calculate(Stack A){
343     //定义一个辅助计算后缀表达式的栈 
344     Stack as=CreateStack(10);
345     long result;
346     int a,b,temp,i;
347     char str[5];
348     for(i=0;i<=A->TopOfStack;i++){
349         //printf("%s\n",A->Array[i]);
350         if(!IsOperator(A->Array[i])){
351             Push(A->Array[i],as);
352         }else{
353             int b=atof(PopAndTop(as));
354             int a=atoi(PopAndTop(as));
355             char c=A->Array[i][0];
356             //printf("a=%d,b=%d",a,b);
357             //putchar(c);printf("\n"); 
358             switch(c){
359                 case +:temp=a+b;break;
360                 case *:temp=a*b;break;
361                 case -:temp=a-b;break; 
362                 case /:temp=a/b;break;
363                 case ^:temp=FB_QiuMi(a,b);break;
364                 default:printf("不知名错误!\n");
365             }
366             ltoa(temp,str,10);
367             Push(str,as);
368             //printStack(as);
369          }    
370     }
371     if(as->TopOfStack<=0){
372         strcpy(str,Top(as));
373         result=atol(str);
374         printf("计算的结果为:%ld\n",result); 
375     }
376 }
377 int main(){
378     printf("请输入一个中缀表达式:");
379     printf("(最多40个字符的字符串,可以包含任意整数,+,-,*,/,^和()两个括号!)\n");
380     Stack s_center=CreateStack(35);
381     Stack s_later=CreateStack(35); 
382     char x[40];
383     gets(x);
384     char *p=x;
385     handleString(p,s_center);
386     printf("此中缀表达式为:\n"); 
387     printStack(s_center);
388     //将中缀表达式转化为后缀表达式 
389     turnInto(s_center,s_later);
390     printf("\n这个后缀表达式是:\n");
391     printStack(s_later);printf("\n");
392     Calculate(s_later);
393     return 0;
394 } 

技术分享

    与之前写的只有+和*两种运算的计算器作对比,这个程序改进了不少:

    1.虽然+和*运算没有先后之分,但-和/和^运算要严格按照顺序;

    2.递归地处理一个字符串,在字符串开头可以是符号"("也可以是整数的数字,也可以是负数的数字。(之前写的程序使用while循环来提取字符串,第一个字符不能为符号,只能为数字。)

    3.在将中缀转化为后缀表达式时,我用的是switch语句,而之前我用的if else语句。相对而言,switch语句使逻辑结构要更加清晰。

 

    (2)符号匹配:

    栈在计算机语言的编译过程中用来进行语法检查,试编写一个算法,用来检查一个C/C++语言程序源文件中的大括号、方括号和圆括号是否匹配。

    要求:

      1.若能够全部匹配则返回1,否则返回0。

      2.成对的符号有(),[],{},//,/* */。

      3.如果符号不匹配,输出错误信息。

      4.如果符号匹配,输出一遍正确的代码(注释的内容去掉,无效的空行去掉)。

  1 /*
  2   1.在处理源码文件时,把去掉注释并去掉空行的源码输出到新建的文件中 
  3   2.在用栈处理文件字符匹配的过程中,采用栈的链表实现,链表带有头结点。
  4   3.需要进行匹配的有(),<>,{},[],//这些符号,其中/符号不在注释里时必须成对出现。
  5   4.自定义readline()从文件中读一行。 
  6 */
  7 /*5.当前注释符号中不能再次包含此符号,否则编译器会提示语法错误。*/
  8 
  9 #include <stdio.h>
 10 #include <string.h>
 11 #include <stdlib.h> 
 12 
 13 //存无注释源码的文件名 
 14 char *newfile="F:/VS/NoAnnotationSoundCode.txt";
 15 
 16 struct SymbolNode{
 17   char handlesymbol; 
 18   struct SymbolNode *Next;
 19 };
 20 
 21 typedef struct SymbolNode *Symbol;
 22 typedef struct SymbolNode *PtrToNode;
 23 typedef PtrToNode Stack;
 24 
 25 Stack createStack(){
 26   Stack symbolstack=malloc(sizeof(struct SymbolNode));
 27   symbolstack->Next=NULL;
 28   return symbolstack;
 29 }
 30 Symbol TopAndPop(Stack test_stack){
 31   PtrToNode temp=test_stack->Next;
 32   test_stack->Next=test_stack->Next->Next;
 33   return temp;
 34 }
 35 Symbol Top(Stack test_stack){
 36   return test_stack->Next;
 37 }
 38 void Push(char p,Stack test_stack){
 39   //printf("%c进栈",p);
 40   PtrToNode temp=malloc(sizeof(struct SymbolNode));
 41   temp->handlesymbol=p; 
 42   temp->Next=test_stack->Next;
 43   test_stack->Next=temp;
 44 } 
 45 void Pop(Stack test_Stack){
 46   PtrToNode temp=test_Stack->Next;
 47   test_Stack->Next=test_Stack->Next->Next;
 48   //printf("%c出栈\n",temp->handlesymbol);
 49   free(temp);
 50 }
 51 int IsEmpty(Stack test_stack){
 52   return test_stack->Next==NULL;
 53 } 
 54 int IsQuotationAround(char *p,int i){
 55   if(p[i+1]==\‘&&p[i-1]==\‘ || p[i+1]==\"&&p[i-1]==\" ){
 56     return 1;
 57   }else
 58     return 0; 
 59 }
 60 char *Read_Line(FILE *fp){
 61   int lines=100;
 62   char *str=malloc(sizeof(char)*100);
 63   fgets(str,lines,fp);
 64   //printf("读取的字符串是%s\n",str);
 65   return str;
 66 }
 67 int totalSpaceOrTableOrAnotation(char *p){
 68   int i=0;
 69   //printf("当前操作的字符串是%sEOF\n",p);
 70   //printf("当前字符串的长度是%d\n",strlen(p));
 71   while(p[i]== ||p[i]==\t)
 72     i++;
 73     if(p[i]==\n){//在每行一开始就是\n肯定是无效行 
 74       return 1;
 75     }else{
 76       if(p[i]==/&&p[i+1]==/)
 77         return 1;
 78       else 
 79            return 0;
 80     }
 81 }
 82 void printStack(Stack s){
 83   PtrToNode ptr=s->Next;
 84   while(ptr!=NULL){
 85     putchar(ptr->handlesymbol);
 86     ptr=ptr->Next;
 87   }
 88 } 
 89 int symbolMatch(char *p){
 90   FILE *fp;
 91   int linenumber=0;//记录行数 
 92   //首先新建一个存无注释源码的文件
 93   FILE *outputFilePoint=fopen(newfile,"w");
 94   if(outputFilePoint==NULL){
 95     printf("无法新建存源码的文件");
 96     return 0;
 97   }    
 98     Stack temp_stack=createStack(15);//用于存需要进行匹配的符号。
 99     if((fp=fopen(p,"r"))!=NULL){
100         char *p;//指向读取的每一行的字符串 
101         int i;
102         while(!feof(fp)){
103           p=Read_Line(fp);
104             //printf("%d.输出栈中的元素:",linenumber);
105           linenumber++; 
106           //printStack(temp_stack); 
107           //printf("\n");
108             if(totalSpaceOrTableOrAnotation(p)){//如果是空行或者只有注释的行,丢掉。 
109                continue;
110             }else{
111             i=0;//每一行都要重新初始化,防止上一行的对此行产生影响
112               while(!( p[i]==\0 && !IsQuotationAround(p,i) ) ){//当字符不是每行的末尾时 
113               //putchar(p[i]);
114               //处理栈中为*号的情况。
115               if(Top(temp_stack)!=NULL&&Top(temp_stack)->handlesymbol==*){
116                    if(p[i]!=Top(temp_stack)->handlesymbol){
117                    i=i+1;
118                      continue;}
119                   else{
120                      if(p[i+1]!=/){
121                         i++;
122                       continue;}
123                     else{
124                     Pop(temp_stack);
125                     i=i+2;
126                   }
127                 }           
128             }
129             //当不属于/*注释范围时。
130             //putchar(p[i]); 
131             switch(p[i]){
132               case /://不需要压入栈中进行匹配 
133               {    
134                   if(p[i+1]==/){
135                   fputc(\n,outputFilePoint);
136                   if(!feof(fp)){//以后的为无效注释文本,忽略,开始下一行 
137                   p=Read_Line(fp);i=0;
138                   linenumber++;
139                   while(totalSpaceOrTableOrAnotation(p)){
140                     p=Read_Line(fp);
141                     linenumber++;
142                   }     
143                 }
144                 }else if(p[i+1]==*){
145                   Push(*,temp_stack);
146                   i++;
147                   }else{
148                     fputc(p[i],outputFilePoint);
149                 }
150               }break;
151               case {:
152               {        
153                    if(!IsQuotationAround(p,i))
154                   Push(p[i],temp_stack);
155                   fputc(p[i],outputFilePoint);        
156               }break;
157               case }:
158               {        
159                   if(!IsQuotationAround(p,i)){
160                    if(Top(temp_stack)->handlesymbol=={){
161                     Pop(temp_stack);
162                   }else
163                     printf("在源码的%d行出现错误\n",linenumber);                                    
164                   }
165                   fputc(p[i],outputFilePoint);
166               }break;
167               case (:
168               {    
169                    if(!IsQuotationAround(p,i))
170                   Push(p[i],temp_stack);
171                   fputc(p[i],outputFilePoint);            
172               }break;
173               case ):
174               {        
175                   if(!IsQuotationAround(p,i)){
176                   if(Top(temp_stack)->handlesymbol==(){
177                     Pop(temp_stack);
178                   }else{
179                      printf("在源码的%d行出现错误\n",linenumber);    
180                   }                                    
181                 }
182                 fputc(p[i],outputFilePoint);                        
183               }break;
184               case [:
185               {        
186                   if(!IsQuotationAround(p,i))
187                   Push(p[i],temp_stack);
188                   fputc(p[i],outputFilePoint);                        
189                 }break;
190               case ]:
191               {        
192                   if(!IsQuotationAround(p,i)){
193                   if(Top(temp_stack)->handlesymbol==[){
194                     Pop(temp_stack);
195                   }else{
196                     printf("在源码的%d行出现错误\n",linenumber);
197                   }                                    
198                 }
199                 fputc(p[i],outputFilePoint);
200               }break;
201               default:
202                 {
203                 if(!(i>0&&p[i-1]==/‘&&p[i-2]==‘*‘)){
204                     fputc(p[i],outputFilePoint);    
205                   }                          
206               }
207               }//对每个字符进行处理的结束    
208              i++;                 
209              }//当字符指针没有到行尾的while语句的结束    
210         }//此行为有效行的else语句的结束 
211       }//打开文件语句的结束                                         
212     }else{
213          printf("打开文件%s失败!\n",p);
214   }
215   fclose(fp);
216   fclose(outputFilePoint);//打开文件得指针一定要关闭,否则会影响后面的读写。 
217   if(IsEmpty(temp_stack)){
218     return 1;
219   }else{
220     return 0;
221   }        
222 }
223 void printFile(char *p){
224   printf("\n--------------------%s---------------------\n",p);
225   FILE *fp=NULL;
226   if((fp=fopen(p,"r"))==NULL){
227     printf("打开文件失败");
228       exit(0); 
229   }else{
230     printf("打开文件成功!\n"); 
231     //用来存读到的东西 
232     char ch;
233     while(!feof(fp)){    
234        ch=fgetc(fp);
235       putchar(ch);
236     }
237   }
238   fclose(fp);
239 } 
240 int main(){
241   char *file="SymbolMatch.c";
242   FILE *fp=NULL;
243   //如果此源码文件没有语法错误,就打印出去掉所有注释的源码文件 
244   if(symbolMatch(file)){
245     printFile(newfile); 
246   }else{
247     printf("符号匹配出现错误!\n");
248   }
249   return 0;
250 } 

技术分享

    上面这张图片是程序运行的结果的部分截屏。

    在本地目录的F:/VS/NoAnnotationSoundCode.txt下存有上面源码去掉注释和空行的版本:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h> 
  4 char *newfile="F:/VS/NoAnnotationSoundCode.txt";
  5 struct SymbolNode{
  6   char handlesymbol; 
  7   struct SymbolNode *Next;
  8 };
  9 typedef struct SymbolNode *Symbol;
 10 typedef struct SymbolNode *PtrToNode;
 11 typedef PtrToNode Stack;
 12 Stack createStack(){
 13   Stack symbolstack=malloc(sizeof(struct SymbolNode));
 14   symbolstack->Next=NULL;
 15   return symbolstack;
 16 }
 17 Symbol TopAndPop(Stack test_stack){
 18   PtrToNode temp=test_stack->Next;
 19   test_stack->Next=test_stack->Next->Next;
 20   return temp;
 21 }
 22 Symbol Top(Stack test_stack){
 23   return test_stack->Next;
 24 }
 25 void Push(char p,Stack test_stack){
 26   PtrToNode temp=malloc(sizeof(struct SymbolNode));
 27   temp->handlesymbol=p; 
 28   temp->Next=test_stack->Next;
 29   test_stack->Next=temp;
 30 } 
 31 void Pop(Stack test_Stack){
 32   PtrToNode temp=test_Stack->Next;
 33   test_Stack->Next=test_Stack->Next->Next;
 34   free(temp);
 35 }
 36 int IsEmpty(Stack test_stack){
 37   return test_stack->Next==NULL;
 38 } 
 39 int IsQuotationAround(char *p,int i){
 40   if(p[i+1]==\‘&&p[i-1]==\‘ || p[i+1]==\"&&p[i-1]==\" ){
 41     return 1;
 42   }else
 43     return 0; 
 44 }
 45 char *Read_Line(FILE *fp){
 46   int lines=100;
 47   char *str=malloc(sizeof(char)*100);
 48   fgets(str,lines,fp);
 49   return str;
 50 }
 51 int totalSpaceOrTableOrAnotation(char *p){
 52   int i=0;
 53   while(p[i]== ||p[i]==\t)
 54     i++;
 55     if(p[i]==\n){
 56   return 1;
 57     }else{
 58       if(p[i]==/&&p[i+1]==/)
 59         return 1;
 60       else 
 61            return 0;
 62     }
 63 }
 64 void printStack(Stack s){
 65   PtrToNode ptr=s->Next;
 66   while(ptr!=NULL){
 67     putchar(ptr->handlesymbol);
 68     ptr=ptr->Next;
 69   }
 70 } 
 71 int symbolMatch(char *p){
 72   FILE *fp;
 73   int linenumber=0;
 74  FILE *outputFilePoint=fopen(newfile,"w");
 75   if(outputFilePoint==NULL){
 76     printf("无法新建存源码的文件");
 77     return 0;
 78   }    
 79     Stack temp_stack=createStack(15);
 80    if((fp=fopen(p,"r"))!=NULL){
 81         char *p;
 82     int i;
 83         while(!feof(fp)){
 84           p=Read_Line(fp);
 85           linenumber++; 
 86             if(totalSpaceOrTableOrAnotation(p)){
 87               continue;
 88             }else{
 89             i=0;
 90              while(!( p[i]==\0 && !IsQuotationAround(p,i) ) ){
 91           if(Top(temp_stack)!=NULL&&Top(temp_stack)->handlesymbol==*){
 92                    if(p[i]!=Top(temp_stack)->handlesymbol){
 93                    i=i+1;
 94                      continue;}
 95                   else{
 96                      if(p[i+1]!=/){
 97                         i++;
 98                       continue;}
 99                     else{
100                     Pop(temp_stack);
101                     i=i+2;
102                   }
103                 }           
104             }
105             switch(p[i]){
106               case /:
107           {    
108                   if(p[i+1]==/){
109                   fputc(\n,outputFilePoint);
110                   if(!feof(fp)){
111                    p=Read_Line(fp);i=0;
112                    linenumber++;
113                   while(totalSpaceOrTableOrAnotation(p)){
114                     p=Read_Line(fp);
115                     linenumber++;
116                   }     
117                 }
118                 }else if(p[i+1]==*){
119                   Push(*,temp_stack);
120                   i++;
121                   }else{
122                     fputc(p[i],outputFilePoint);
123                 }
124               }break;
125               case {:
126               {        
127                    if(!IsQuotationAround(p,i))
128                     Push(p[i],temp_stack);
129                     fputc(p[i],outputFilePoint);        
130               }break;
131               case }:
132               {        
133                   if(!IsQuotationAround(p,i)){
134                    if(Top(temp_stack)->handlesymbol=={){
135                     Pop(temp_stack);
136                   }else
137                     printf("在源码的%d行出现错误\n",linenumber);                                    
138                   }
139                    fputc(p[i],outputFilePoint);
140               }break;
141               case (:
142               {    
143                    if(!IsQuotationAround(p,i))
144                       Push(p[i],temp_stack);
145                       fputc(p[i],outputFilePoint);            
146               }break;
147               case ):
148               {        
149                   if(!IsQuotationAround(p,i)){
150                   if(Top(temp_stack)->handlesymbol==(){
151                     Pop(temp_stack);
152                   }else{
153                      printf("在源码的%d行出现错误\n",linenumber);    
154                   }                                    
155                 }
156                 fputc(p[i],outputFilePoint);                        
157               }break;
158               case [:
159               {        
160                   if(!IsQuotationAround(p,i))
161                   Push(p[i],temp_stack);
162                   fputc(p[i],outputFilePoint);                        
163                 }break;
164               case ]:
165               {        
166                   if(!IsQuotationAround(p,i)){
167                   if(Top(temp_stack)->handlesymbol==[){
168                     Pop(temp_stack);
169                   }else{
170                     printf("在源码的%d行出现错误\n",linenumber);
171                   }                                    
172                 }
173                 fputc(p[i],outputFilePoint);
174               }break;
175               default:
176                 {
177                 if(!(i>0&&p[i-1]==/&&p[i-2]==*)){
178                     fputc(p[i],outputFilePoint);    
179                   }                          
180               }
181               }
182             i++;                 
183              }
184     }
185   }
186    }else{
187          printf("打开文件%s失败!\n",p);
188   }
189   fclose(fp);
190   fclose(outputFilePoint);
191  if(IsEmpty(temp_stack)){
192     return 1;
193   }else{
194     return 0;
195   }        
196 }
197 void printFile(char *p){
198   printf("\n--------------------%s---------------------\n",p);
199   FILE *fp=NULL;
200   if((fp=fopen(p,"r"))==NULL){
201     printf("打开文件失败");
202       exit(0); 
203   }else{
204     printf("打开文件成功!\n"); 
205     char ch;
206     while(!feof(fp)){    
207        ch=fgetc(fp);
208       putchar(ch);
209     }
210   }
211   fclose(fp);
212 } 
213 int main(){
214   char *file="SymbolMatch.c";
215   FILE *fp=NULL;
216   if(symbolMatch(file)){
217     printFile(newfile); 
218   }else{
219     printf("符号匹配出现错误!\n");
220   }
221   return 0;
222 } 

    你可以用这个程序来获得不带注释的源码,而且还能进行符号的匹配。

 

    (3)进制转换:

    把十进制整数转换为二至十六之间的任意进制输出。

    算法原理:N=(N div d)*d+N mod d(其中:div为整除操作,mod为求余操作)。

    例如:(1348)10=(2504)8

N N div 8 N mod 8
1348 168 4
168 21 0
21 2 5
2 0 2

 

   

 

 

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 struct numNode{
 4     char *Array;
 5     int Capicity;
 6     int TopOfStack; 
 7 };
 8 typedef struct numNode *PtrToNode;
 9 typedef PtrToNode Stack;
10 Stack create(int size){
11     Stack tempStack=malloc(sizeof(struct numNode));
12     if(size<20)
13       size=20;
14     tempStack->Array=malloc(sizeof(char)*size);
15     tempStack->Capicity=size;
16     tempStack->TopOfStack=-1;
17     return tempStack; 
18 }
19 char Top(Stack s){
20     return s->Array[s->TopOfStack];
21 }
22 char TopAndPop(Stack s){
23     if(s->TopOfStack<0){
24         printf("栈为空!\n");
25     }else{
26         return s->Array[s->TopOfStack--];
27     }
28 }
29 int isFull(Stack s){
30     if(s->TopOfStack+1<s->Capicity){
31         return 0;
32     }else{
33         return 1;
34     }
35 }
36 int isEmpty(Stack s){
37     return s->TopOfStack==-1; 
38 }
39 void Push(int element,Stack s){
40     if(element>16||element<0){
41         printf("出现错误"); 
42     }
43     char ch;
44     switch(element){
45         case 15:ch=f;break;
46         case 14:ch=e;break;
47         case 13:ch=d;break;
48         case 12:ch=c;break;
49         case 11:ch=b;break;
50         case 10:ch=a;break;
51         default:ch=(char)(48+element);
52     }
53     if(!isFull(s)){
54         s->Array[++s->TopOfStack]=ch; 
55     }else{
56         printf("栈空间已满!\n");
57     }
58 }
59 void Pop(Stack s){
60     s->TopOfStack--;
61 }
62 char *Conversion(long element,int n){
63     Stack tempStack=create(25);
64     //printf("%d",element); 
65     while(element){
66         Push(element%n,tempStack);
67         element=element/n;
68     }
69     char *temp;
70     int i=0;
71     temp=malloc(sizeof(char)*25);
72     while(!isEmpty(tempStack))
73         temp[i++]=TopAndPop(tempStack);
74     temp[i]=\0;
75     return temp;
76 }
77 int main(){
78     long element;
79     scanf("%d",&element);
80     printf("%d转化为2进制是:%s\n",element,Conversion(element,2));
81     printf("%d转化为8进制是:%s\n",element,Conversion(element,8));
82     printf("%d转化为10进制是:%s\n",element,Conversion(element,10));
83     printf("%d转化为16进制是:%s\n",element,Conversion(element,16));
84     return 0;
85 } 

技术分享

 

    (4)栈与递归的综合案例--n阶汉诺塔(Tower of Hanoi)问题: 

    有三个分别为A,B,C的塔座,在塔座A上插有n个直径大小不同的圆盘,依小到大进行编号(1~n)。现在要求将A上的n个圆盘移至塔座Z上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:

  (1)每次只能移动一个圆盘;

      (2)圆盘可以在A,B,C任意一格塔座上;

      (3)任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

    试编写一个程序实现输出搬运过程和最终搬运结果。

    算法:把n个圆盘的问题转化为两个n-1个圆盘的问题,当n=1时不需要再递归,只需要直接移动即可。

 1 //汉诺塔问题的递归解法
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 struct HnNodeLeader{
 6   char name;    
 7   struct HnNode *Next;    
 8 }; 
 9 struct HnNode{
10     int element;
11     struct HnNode *Next;    
12 };
13 typedef struct HnNode *PtrToNode;
14 typedef struct HnNodeLeader *Stack;
15 Stack createStack(char ch){
16     Stack tempStack=malloc(sizeof(struct HnNodeLeader));
17     tempStack->name=ch;
18     tempStack->Next=NULL;
19     return tempStack;
20 }
21 void Push(int x,Stack s){
22     PtrToNode temp=malloc(sizeof(struct HnNode));
23     temp->element=x;
24     temp->Next=s->Next;
25     s->Next=temp;
26 }
27 int IsEmpty(Stack s){
28     return s->Next==NULL;
29 } 
30 PtrToNode TopAndPop(Stack s){
31     if(IsEmpty(s)){
32         return NULL;
33     }
34     PtrToNode temp=s->Next;
35     s->Next=s->Next->Next;
36     return temp;
37 }
38 PtrToNode Top(Stack s){
39     return s->Next;
40 }
41 int TotalNumOfStack(Stack s){
42     PtrToNode temp=s->Next;
43     int i=0;
44     while(temp!=NULL){
45         i++;
46         temp=temp->Next;
47     }
48     return i;
49 } 
50 void Move(Stack local,Stack target){
51     Push(TopAndPop(local)->element,target);
52 }
53 void printAndFreeStack(Stack temp){
54     int i=0;
55     while(!IsEmpty(temp)){
56         printf("%4d",TopAndPop(temp)->element);
57         i++;
58         if(i%20==0){
59             printf("\n");
60         }
61     }
62 }
63 //把a栈中的n个元素通过b栈送到c栈上 
64 void TransferHanNoi(int n,Stack a,Stack b,Stack c){
65     if(n==1){
66         Move(a,c);
67         printf("圆盘%2d从栈%c移动到栈%c\n",Top(c)->element,a->name,c->name);
68         return;
69     }
70     TransferHanNoi(n-1,a,c,b);//把n-1个元素从a移动到b 
71     Move(a,c);//再把a中的一个元素移动到c中。 
72     printf("圆盘%2d从栈%c移动到栈%c\n",Top(c)->element,a->name,c->name);
73     TransferHanNoi(n-1,b,a,c);//再移动b中的所有元素到c中 
74 }
75 int main(){
76     srand(time(NULL));
77     //数值太大,非常耗时间。所以测试数要非常小。 
78     int testNum=rand()%13+1;
79     printf("测试汉诺塔圆盘数为%d时候的转移问题:\n",testNum);
80     Stack A=createStack(A);
81     Stack B=createStack(B);
82     Stack C=createStack(C);
83     int i;
84     for(i=1;i<=testNum;i++){
85         Push(i,A);
86     }
87     TransferHanNoi(TotalNumOfStack(A),A,B,C);
88     printAndFreeStack(C);    
89     return 0;
90 } 

技术分享

 

    (5)循环链表与贪婪算法的综合案例--Josephus问题:

    N个人从1到N编号,围坐成一个圆圈。从一号开始传递一个热土豆。经过M次传递后拿着热土豆的人将被清除离座,围坐的圆圈锁紧,由坐在被清除的人后面的人拿起热土豆继续进行游戏。最后剩下的人获得胜利。 

    试编写一程序得出胜利者的编号:

    算法:构造循环链表,模拟n个人围成的圈,然后依次删除需要删除的元素。每次删除一个元素后,圈更新,问题又重新开始:

  1 //用循环链表 
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <time.h>
  5 
  6 struct PersonNode{
  7     int Num;
  8     struct PersonNode *Next;
  9 };
 10 typedef struct PersonNode *List;
 11 typedef struct PersonNode *PtrToNode;
 12 
 13 List createList(){
 14     List tempList=malloc(sizeof(struct PersonNode));
 15     tempList->Next=NULL;
 16     return tempList;
 17 }
 18 int IsEmpty(List list){
 19     if(list->Next==NULL)
 20         return 1;
 21     else
 22         return 0;
 23 } 
 24 void InsertIntoList(int n,List list){
 25     //创建临时结点 
 26     PtrToNode temp=malloc(sizeof(struct PersonNode));
 27     temp->Num=n;
 28     //找到位置
 29     if(IsEmpty(list)){
 30         list->Next=temp;
 31         temp->Next=list->Next;
 32         return;
 33     } 
 34     PtrToNode p1=list->Next;
 35     while(p1->Next!=list->Next){
 36         p1=p1->Next;
 37     }
 38     temp->Next=list->Next;
 39     p1->Next=temp;
 40 }
 41 int ClearProcess(List list,int M){
 42     int flag=1;
 43     if(IsEmpty(list)){
 44         printf("表为空!\n");
 45         return -1; 
 46     }
 47     int i;
 48     PtrToNode ptr=list->Next;
 49     //当循环链表中元素不止一个时,继续删除 
 50     while(ptr!=ptr->Next){
 51         //当M=0时,找到当前结点前一个 
 52         if(M==0){    
 53           PtrToNode p=ptr->Next;
 54           while(p->Next!=ptr)
 55               p=p->Next;
 56           ptr=p;    
 57         }else{
 58           for(i=0;i<M-1;i++)
 59             ptr=ptr->Next;    
 60         }
 61         //处理过程 
 62           PtrToNode temp=ptr->Next;
 63         ptr->Next=ptr->Next->Next;
 64         printf("%2d.游戏者%2d出局!  ",flag,temp->Num);
 65         if(flag%5==0)
 66             printf("\n");
 67         flag++;
 68            free(temp);
 69         ptr=ptr->Next;  
 70     }
 71     return ptr->Num;
 72 }
 73 void printList(List list){
 74     int flag=0;
 75     if(IsEmpty(list)){
 76       printf("链表为空");
 77       return;
 78     }
 79     PtrToNode ptr=list->Next;
 80     while(ptr->Next!=list->Next){
 81         flag++;
 82         printf("%3d",ptr->Num);
 83         ptr=ptr->Next;
 84         if(flag%30==0)
 85           printf("\n");
 86     }
 87     printf("%3d",ptr->Num);
 88     printf("\n");
 89 }
 90 int main(){
 91     srand(time(NULL));
 92     int N,M;
 93     int i;
 94     N=rand()%100+1;//人数不超过100
 95     M=rand()%50;//传递次数
 96     List list=createList();
 97     for(i=0;i<N;i++){
 98         InsertIntoList(i+1,list);
 99     }
100     printf("N的大小为%d,M的大小为%d\n",N,M);
101     //printList(list);
102     int winerNum=ClearProcess(list,M); 
103     printf("\n获胜者是%d",winerNum);
104     return 0;
105 }

技术分享

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

标签:

原文地址:http://www.cnblogs.com/MenAngel/p/5630963.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!