一些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; }

浙公网安备 33010602011771号