一些C和数据结构的小题

1.写一个递归函数,完成会问的判断,回文是只有如下形式的字符串:"a","abcdcba","abccba"

View Code
int turn(char *str){
    char *p;
    p=str+strlen(str)-1;
        if(*str != *p)
            return 0;
        else{
            if(p-str <= 2)
                return 1;
            else {
                *p='\0';
                return (turn(str+1));
            }
            
        }
}

2. 对于仅含+、-、*、/的算术表达式

  1)写一函数,建立表达式树,函数的输入为算术表达式字符串。

  2)写一函数,按逆波兰式输出该表达式,该函数的输入表达式树。

 算法实现:  将一个普通的中序表达式转换为逆波兰表达式的一般算法是:

首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,    注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:

  (1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈;若取出的是运算符,并且当前S1栈顶为(,则当前运算符直接入S1栈。

  (2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈, 否者,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符送入S1栈。

  (3)若取出的字符是“(”,则直接送入S1栈栈顶。

  (4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。

  (5)重复上面的1~4步,直至处理完所有的输入字符

  (6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。

  完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!

View Code
  1 #include <stdio.h> 
  2 #include <string.h>
  3 #include <time.h>    /*记录运行时间*/ 
  4  
  5 #include "栈的链式存储.c"
  6 
  7 struct sNode *symbol;
  8 struct sNode *result;
  9  
 10 /* 1.符号优先级获取函数*/
 11 int getPriority(char op)
 12 {
 13     switch(op)
 14     {
 15         case '+':
 16         case '-':
 17             return 1;
 18         case '*':
 19         case '/':
 20             return 2;
 21         case '(':       /*不会有判断')'的情况*/ 
 22             return 0;        
 23         default:
 24             return -1; 
 25     }    
 26 } 
 27 /* 2.初始化栈*/
 28 int init2stack()
 29 {
 30     initStack(&symbol);
 31     initStack(&result);    
 32 } 
 33 /* 3.解析原始表达式,使之变成逆波兰式表达式(将表达式保存到result栈中,栈底为表达式左端).*/ 
 34 void transform(char *str)
 35 {
 36     elemType x,y;
 37     int i = 0; 
 38     int priority = -1;  
 39     
 40     /*遍历字符串*/ 
 41     while(i < strlen(str))   /*以换行符表示表达式结束,若表达式是通过外部输出,可更换*/
 42     {
 43             /*如果是操作数,直接压入result栈*/
 44             if(str[i] >= '0' && str[i]<='9')
 45             { 
 46                 x = 0;
 47                 while(str[i] >= '0' && str[i]<='9')
 48                 {
 49                     x = x*10 + str[i] - 48;
 50                     i++;    
 51                 }
 52                 if(str[i] == '.')
 53                 {
 54                     i++; 
 55                     y =0;
 56                     double j = 10.00; 
 57                     while(str[i] >= '0' && str[i]<='9')
 58                     {
 59                         y = y + str[i]/j; 
 60                         i++;    
 61                     }
 62                     x += y; 
 63                 }
 64                 push(&result,x); 
 65             }
 66             if(i >= strlen(str)) 
 67             {
 68                 break;    
 69             } 
 70             /*如果是运算符 : 
 71 .'('直接放入symbol栈
 72 . ')'将symbol栈中最靠近栈顶的'(' 与栈顶见得运算符,从顶到底依次写入result栈.并pop出'('
 73 . '-'或'+' 判断symbol栈顶运算符(小括号'('除外)的优先级,比'+-'小,就将'+-'压入栈symbol.比'+-'大于等于的,pop出来,压入result栈.
 74                     并将'+-'压入symbol栈
 75 .'*'或'/'同第3条规则.
 76 .若symbol栈为空,直接压栈 
 77             */ 
 78     
 79             switch(str[i])
 80             {
 81                 case '(':
 82                     push(&symbol,'(');       
 83                     break;
 84                 case ')':
 85                     while( (char)peek(&symbol) != '(')  /*double型的元素要强转一下*/ 
 86                     {
 87                         push(&result,pop(&symbol)); /*将( ) 之间的运算符导入result*/
 88                     }
 89                     pop(&symbol); 
 90                     break;
 91                 case '+':
 92                 case '-':
 93                 case '*':
 94                 case '/':
 95                     if(emptyStack(&symbol)) /*如果栈空,直接压栈*/ 
 96                     {
 97                         push(&symbol,str[i]);        
 98                     }else{  
 99                         priority = getPriority(str[i]);
100                         if(priority <= getPriority((char)peek(&symbol))) /*若symbol栈顶元素优先级大,基本是栈顶为*'/',此时str[i]为+-的情况*/ 
101                         {
102                             push(&result,pop(&symbol));
103                             push(&symbol,str[i]);    
104                         }else{    /*栈顶为+-,str[i]为*'/'的情况*/                             
105                             push(&symbol,str[i]);   
106                         }                         
107                     } 
108                     break;
109                 default:
110                    break;                            
111             } 
112             i++;
113     } /*结束遍历原始表达式*/ 
114     while(!emptyStack(&symbol)) /*将symbol中的所有剩余运算符送入result栈*/ 
115     {
116         push(&result,pop(&symbol)); 
117     } 
118 } 
119 /* 4.使存储逆波兰式的栈中数据倒置,用于挨个取出进行分析计算(将result中表达式倒置入symbol栈中.表达式右端在栈顶).*/
120 void dataInversion()
121 {
122     while(!emptyStack(&result))  /*将result中的逆波兰式倒置进symbol,以便进行最终结果计算时使用*/ 
123     {
124         push(&symbol,pop(&result)); 
125     } 
126 } 
127 /* 5.分析计算函数*/ 
128 double compute()
129 {
130     elemType x,y;         /*用于保存数字,x为整数部分,y为小数部分.(如果是小数的话)*/ 
131     elemType temp; 
132     int i;              /*用于遍历字符串*/
133     
134     while(emptyStack(&symbol) != 1)
135     {
136         temp = pop(&symbol);
137         if((char)temp == ' ')  /*如果是空格,不做操作*/ 
138         {
139             i++;
140             continue;    
141         }
142         
143         switch((char)temp)
144         {
145             case '+':
146                 x = pop(&result);
147                 x = x + pop(&result); 
148                 i++; 
149                 break;
150             case '-':
151                 x = pop(&result);
152                 x = pop(&result) - x;
153                 i++; 
154                 break;
155             case '*':
156                 x = pop(&result);
157                 x = x * pop(&result);
158                 i++; 
159                 break;
160             case '/':
161                 x = pop(&result);
162                 if(x>0.000001 && x<-0.000001)  /*不可以将浮点变量用“==”或者“!=”与任何数字比较。*/ 
163                 {
164                     printf("除数是0,终止程序.\n");
165                     system("pause");    
166                 }else{
167                     x = pop(&result) / x;    
168                 } 
169                 break;
170             default: 
171                 x = temp; 
172                 break;                                 
173         } /*switch 判断当前字符结束*/ 
174         push(&result,x);
175     } /*str字符串遍历结束*/
176 
177    x = pop(&result); 
178    return x; 
179 } 
180 
181 /* 6.遍历整个栈,从底到顶*/
182 void travelStack(struct sNode *hs)
183 {
184     struct sNode *temp = hs;
185     char arr[100]; 
186     int i,n =0; 
187     
188     while(temp != NULL)
189     {
190         arr[n++] = temp->data;       
191         temp = temp->next; 
192     }
193     for(i = n-1; i>=0; i--)
194     {
195         switch((char)arr[i])
196         {
197             case '+':
198             case '-':
199             case '*': 
200             case '/':
201             case '(':
202             case ')': 
203                 printf("%c ",(char)arr[i]);
204                 break;
205             default: 
206                 printf("%d ",(int)arr[i]); 
207                 break;                     
208         }          
209     }    
210 }
211 
212 /* 7.检查表达式格式,通过返回1,否则返回0*/ 
213 int checkExpression(char *str)
214 {
215     int i = 0;
216     int len = strlen(str);
217     int head = 0;
218     int parenthesis =0; 
219     while(i < len)
220     {
221         /*如果是操作数,直接压入result栈*/
222             if(str[i] >= '0' && str[i]<='9')
223             { 
224                 while(str[i] >= '0' && str[i]<='9')
225                 {
226                     i++;    
227                 }
228                 if(str[i] == '.')
229                 {
230                     i++;  
231                     while(str[i] >= '0' && str[i]<='9')
232                     {
233         
234                         i++;    
235                     } 
236                 }
237                 if(head == 0) head = 1;
238                 /*数字后面必须是+ - * '/' 或者,数字为表达式结尾时除外)*/ 
239                 if(str[i] != 42 && str[i] != 43 && str[i] != 45 && str[i] != 47 && i != len)
240                 {
241                     if( str[i] != 41)
242                     { 
243                         printf("表达式错误... %c a附近\n",str[i]);
244                         return 0;  
245                     } 
246                 }  
247             }
248             if(i >= strlen(str)) 
249             {
250                 return 1;    
251             }
252         switch(str[i])
253         {
254              
255             case '+':
256             case '-': 
257             case '*': 
258             case '/':
259                 /* '+''-''*''/'后面只可以是'('或者操作数,且不能在表达式开头,或结尾*/
260                 if(head == 0 || i== len -1)
261                 {
262                     printf("表达式错误... %c 附近\n",str[i]);
263                     return 0;  
264                 } 
265                 if((str[i+1] < '0'|| str[i+1] > '9' ))
266                 {
267                     if(str[i+1] != '(')
268                     { 
269                         printf("表达式错误... %c 附近\n",str[i]);
270                         return 0; 
271                     } 
272                 } 
273                 break;                
274             case '(':
275                 if(head == 0) head =1; 
276                 /* '+''-''*''/'后面只可以是'('或者操作数,且不能在表达式开头,或结尾*/
277                 if(i== len -1)
278                 {
279                     printf("表达式错误... %c 附近\n",str[i]);
280                     return 0;  
281                 }
282                 if(str[i+1] < '0' || str[i+1] > '9' )
283                 {
284                     printf("表达式错误... %c 附近\n",str[i]);
285                     return 0; 
286                 } 
287                 
288                 parenthesis++; 
289                 break;      
290             case ')': 
291                 /* ')'后面只可以是运算符*/
292                 if(i == len -1) break; 
293                 if((str[i+1] != 42 && str[i+1] != 43 && str[i+1] != 45 && str[i+1] != 47) || head == 0) 
294                 {
295                     printf("表达式错误... %c 附近\n",str[i]);
296                     return 0; 
297                 } 
298                 
299                 parenthesis--;
300                 if(parenthesis < 0)
301                 {
302                     printf("表达式错误... 缺少与 ) 匹配的 (\n");
303                     return 0;         
304                 } 
305                 break;
306             default:
307                 printf("不明运算符: %c\n",str[i]);
308                 return 0;  
309         }
310         i++;    
311     }
312     if(parenthesis < 0)
313     {
314             printf("表达式错误... 缺少与 ) 匹配的 (\n");
315             return 0;         
316     }else if(parenthesis > 0)  
317     {
318             printf("表达式错误... 缺少与 ( 匹配的 )\n");
319             return 0;
320     } 
321     
322     return 1; 
323 }
324  
325 int main(void)
326 {
327     double cost_time; 
328     clock_t start,end; /*时间毫秒级*/ 
329     char *str = "(1+2)*3-(5+6)/4";
330     elemType res; 
331     
332     start=clock();
333     printf("表达式为:\n\t%s\n",str);
334     printf("正在检查表达式格式...\n"); 
335     if(checkExpression(str) == 0)
336     {        
337        system("pause");         
338     } 
339     printf("将表达式转换成逆波兰式(后缀式)...\n\t"); 
340     transform(str); 
341     travelStack(result); 
342     
343     printf("\n进行倒置\n\t"); 
344     dataInversion(); 
345     travelStack(symbol); 
346     
347     res = compute(); 
348     printf("\n结果为 : %f\n",res); 
349     end=clock();
350     cost_time=(double)(end-start)/CLOCKS_PER_SEC; 
351     printf("所用时间: %f\n",cost_time);
352     system("pause"); 
353     return 0;   
354 }

3. 试编写一个函数int like(char *str,char *pattern),该函数是吸纳字符串匹配功能,str为匹配的字符串,pattern是匹配模式,匹配模式有一下几种:

  1)_和?:匹配以为任意字符

     2)*和%:匹配0个,1个活多个任意字符

    3)转移字符\:、\?、\_等表示精确匹配,而不是通配

    4)其他字符为精确匹配

    5)通配符可以多次出现

例如:str=“a nice string”,pattern = "%nice%stri_g"是返回为真;

View Code
#include "Stdio.h"
#include "Conio.h"
int like(char *str,char *pattern)
{
    int j,k=0;

        for(j=0;str[j]&&pattern[k]&&(str[j]==pattern[k]||pattern[k]=='?'||pattern[k]=='*'||pattern[k]=='%'||pattern[k]=='_');)
        {
            if(str[j]==pattern[k])
            {
                j++;k++;
            }  else if(k>0&&pattern[k-1]=='\\'){
                return -1;
            } else if(pattern[k]=='?'||pattern[k]=='_')  {
                j++;k++;
            } else {
                while(pattern[++k]=='*' || pattern[k]=='%');
                while(pattern[k]!=str[j]&&str[j]!='\0')
                    j++;
            }

        }

        if(!pattern[k])
            return 1;
        return -1;

}

int main(void)
{
 /* 此处添加你自己的代码 */
 char pattern[]="%%nic_%str*g",str[]="a nice strig";
 printf("%d",like(str,pattern));
  getch();
  return 0;
}

 4.编写一个函数,求字符串a和b的最长公共子串。

解题思路:最长公共子串问题( longest common substring problem)也就是找到两个或以上的字符串的最长公共子串,该字串在位置上相邻。

例如ABAB,BABA,ABBA,最长公共子串为AB。

我们可以把该问题定义如下:

给出两个字符串S和T,S的长度为m,T的长度为n,找出S与T的最长公共子串。

假设S = “ABAB”,T=“BABA”,我们可以构造一个如下的矩阵:

  V A B A B
L 0 0 0 0 0
B 0 0 1 0 1
A 0 1 0 2 0
B 0 0 2 0 3
A 0 1 0 3 0

 

 

 

 

对于数组array[m][n],扩展为array[m+1][n+1],这样是为了方便初始化,减少循环中对边界的判断。

  • if( S[i] == T[j] ) array[i+1][j+1] = array[i][j] + 1
  • if( S[i] != T[j] ) array[i+1][j+1] = 0
View Code
#define M 5
char *LSC(char *left, char *right)
{
    int lenLeft = strlen(left),lenRight = strlen(right),k;
    int c[M][M] = {0};
    char *p;

    int start,end,len,i,j; /*start表明最长公共子串的起始点,end表明最长公共子串的终止点 */
    end=len=0; /*len表示最长公共子串的长度*/
    for(i=0; i<lenLeft; i++) /*串1从前向后比较*/
    { 
        /*串2从后向前比较,为什么要从后向前呢?是把一维数组c[ ]当二维数组来用,
        如果要从前向后,可以将c申明为一个二维数组c[M][M].但程序要做相应调整. */

        for(j=0; j<lenRight; ++j)
        {
            if(left[i] == right[j])/*元素相等时*/
            { 
                if(i==0||j==0) 
                    c[i][j]=1;
                else
                { 
                    c[i][j]=c[i-1][j-1]+1;
                } 
            } 
            else
                c[i][j] = 0;
            if(c[i][j] > len)
            { 
                len=c[i][j];
                end=j; 
            } 
        } 
    } 
    start=end-len+1;

    /*数组p纪录最长公共子串*/
    p =(char*)malloc(len+1); 
    for(i=start; i<=end; i++) 
    { 
        p[i-start] = right[i]; 
    } 
    p[len]='\0'; 
    return p; 

}

用一维数组代替二维数组:

View Code
#define M 100 

//LCS问题就是求两个字符串最长公共子串的问题 
char* LCS(char left[],char right[]) 
{    
    //获取左子串的长度,获取右子串的长度 
    int lenLeft=strlen(left),lenRight=strlen(right),k; 
    //注意这里要写成char型,而不是int型,否则输入整型数据时会产生错误。 
    //矩阵c纪录两串的匹配情况 
    char*c=(char*)malloc(lenRight*sizeof(char)),*p;       
    //int c[M][M]={0};//当将c申明为一个二维数组时 
    int start,end,len,i,j;//start表明最长公共子串的起始点,end表明最长公共子串的终止点 
    end=len=0;//len表示最长公共子串的长度 

    for(i=0; i<lenLeft; i++) //串1从前向后比较 
    { 
        //串2从后向前比较,为什么要从后向前呢?是把一维数组c[ ]当二维数组来用, 
        //如果要从前向后,可以将c申明为一个二维数组c[M][M].但程序要做相应调整. 
        // for(j=0;j<lenRight;j++)//当c申明为一个二维数组时 
        for(j=lenRight-1; j>=0; j--)  
        { 
            if(left[i] == right[j])//元素相等时 
            { 
                if(i==0||j==0) 
                    c[j]=1;//c[i][j]=1; 
                else
                { 
                    c[j]=c[j-1]+1;//c[i][j]=c[i-1][j-1]+1; 
                } 
            } 
            else
                c[j] = 0;    //c[i][j]=0; 
            if(c[j] > len)   //if (c[i][j]>len) 
            { 
                len=c[j];   //len=c[i][j]; 
                end=j; 
            } 
        } 
    } 
    start=end-len+1; 

    //数组p纪录最长公共子串 
    p =(char*)malloc(len+1); 
    for(i=start; i<=end; i++) 
    { 
        p[i-start] = right[i]; 
    } 
    p[len]='\0'; 
    return p; 
} 

 

 

 

 

 

 

 

posted on 2012-12-22 20:58  黑夜一支烟  阅读(177)  评论(0)    收藏  举报

导航