2018.02.27~28
数据结构入门
1.字符串排序(结构体,指针)
题目描述:有N个字符串,利用指针把它们按照字典序从大到小排序。
思路:定义一个二维数组$read[1001][1001]$用来储存字符串,定义一个指针数组$book[1001]$指向$read$的第一维,用$sort$排序时调用的是指针,换的也是指针,不必将整个字符串交换。
核心代码:
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 int n; 8 char read[1001][1001]; 9 char* book[1001]; 10 bool tmp(char* str1,char* str2){return strcmp(str1,str2)<0;} 11 int main(){ 12 scanf("%d",&n); 13 int i,j; 14 for(i=1;i<=n;i++){ 15 scanf("%s",read[i]); 16 book[i]=read[i]; 17 getchar(); 18 } 19 sort(book+1,book+1+n,tmp); 20 for(i=n;i>=1;i--)printf("%s ",book[i]); 21 return 0; 22 }
状态:AC
2.约瑟夫问题(指针,链表)
思路:用$now$表示当前的这个人,$next[now]$表示这个人的下一人是谁,在$while$里面每次循环,遇到该退出的时候就用以下代码将这个人退出。最后输出$next$数组中不是$-1$的。
int tmp=next[now]; next[now]=next[next[now]]; next[tmp]=-1;
核心代码:
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 int next[10001]; 5 int main(){ 6 int n,m,k; 7 scanf("%d%d",&n,&m); 8 k=n; 9 int i,j; 10 for(i=1;i<=n;i++){ 11 if(i==n)next[i]=1; 12 else next[i]=i+1; 13 } 14 int now=1,bs=0; 15 while(k>1){ 16 bs++; 17 if(bs==m-1){ 18 k--; 19 bs=0; 20 int tmp=next[now]; 21 next[now]=next[next[now]]; 22 next[tmp]=-1; 23 } 24 now=next[now]; 25 } 26 for(i=1;i<=n;i++) 27 if(next[i]!=-1) 28 printf("%d",i); 29 return 0; 30 }
状态:AC
3.括号序列(栈,指针)
思路:利用栈,遇到左括号就入栈,遇到右括号就看栈里面当前栈顶元素是否和当前右括号匹配。在最后,还要看栈是否清空。
核心代码(80分垃圾):
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 char word[2000001]; 5 char zhan[2000001]; 6 int top=0; 7 int bz=0; 8 int main(){ 9 int n; 10 scanf("%d",&n); 11 int i,j; 12 for(i=1;i<=n;i++){ 13 getchar(); 14 scanf("%s",word); 15 top=0; 16 bz=0; 17 zhan[0]='H'; 18 for(j=0;j<=strlen(word)-1;j++){ 19 if(word[j]=='['||word[j]=='<'||word[j]=='{'||word[j]=='('){ 20 top++; 21 zhan[top]=word[j]; 22 } 23 else if(word[j]==']'&&zhan[top]=='[')top--; 24 else if(word[j]=='}'&&zhan[top]=='{')top--; 25 else if(word[j]=='>'&&zhan[top]=='<')top--; 26 else if(word[j]==')'&&zhan[top]=='(')top--; 27 else bz=1; 28 if(top<0)bz=1; 29 if(bz==1)break; 30 } 31 if(top!=0)bz=1; 32 if(bz==0)printf("TRUE "); 33 else printf("FALSE "); 34 } 35 return 0; 36 }
1 #include<bits/stdc++.h> 2 #define For(i,l,r) for(int i=(l);i<=(r);i++) 3 using namespace std; 4 char s[4000008]; 5 6 int main(){ 7 int n,len; 8 bool ok; 9 scanf("%d ",&n); 10 For(i,1,n){ 11 scanf("%s",s); 12 stack<char> ST; 13 len=strlen(s); 14 ok=true; 15 For(j,0,len-1){ 16 if (s[j]=='{' || s[j]=='('|| s[j]=='['|| s[j]=='<') 17 ST.push(s[j]); 18 else 19 if (ST.empty() || abs(s[j]-ST.top())>2){ 20 ok=false; 21 break; 22 } 23 else ST.pop(); 24 } 25 if (ST.empty() && ok) 26 cout<<"TRUE"<<endl; 27 else 28 cout<<"FALSE"<<endl; 29 } 30 return 0; 31 }
1 #include<bits/stdc++.h> 2 #define For(i,l,r) for(int i=(l);i<=(r);i++) 3 using namespace std; 4 char s[4000008]; 5 char ST[5000000]; 6 int t; 7 int main(){ 8 int n,len; 9 bool ok; 10 scanf("%d ",&n); 11 For(i,1,n){ 12 scanf("%s",s); 13 t=0; 14 len=strlen(s); 15 ok=true; 16 For(j,0,len-1){ 17 if (s[j]=='{' || s[j]=='('|| s[j]=='['|| s[j]=='<') 18 ST[++t]=s[j]; 19 else 20 if (t==0 || abs(s[j]-ST[t])>2){ 21 ok=false; 22 break; 23 } 24 else t--; 25 } 26 if (t==0 && ok) 27 cout<<"TRUE"<<endl; 28 else 29 cout<<"FALSE"<<endl; 30 } 31 return 0; 32 }
状态:AC
4.表达式转换
思路:......................................
AC代码:
1 #include<bits/stdc++.h> 2 #define For(i,l,r) for(int i=(l);i<=(r);i++) 3 using namespace std; //+ - * / ( ) ^ 4 const int prior[7][7]={{ 1, 1,-1,-1,-1,1,-1}, 5 /*栈顶运算vs当前运算*/ { 1, 1,-1,-1,-1,1,-1}, 6 /*栈顶运算优先算,置1*/{ 1, 1, 1, 1,-1,1,-1}, 7 /*当前运算先算,置-1*/ { 1, 1, 1, 1,-1,1,-1}, 8 /*对括号特殊处理,置0*/{-1,-1,-1,-1,-1,0,-1}, //左边为左括号,则右边什么运算都要先算,除了右括号 9 { 0, 0, 0, 0, 0,0, 0}, //这一行其实没有意义可以随便赋初值,因为左括号不会出现在栈顶 10 { 1, 1, 1, 1,-1,1, 1}}; 11 char strh[2000]={0},strz[2000]={0}; //后缀表达式字符串,中缀表达式字符串 12 char opst[10000],top=0; //运算符栈 13 int numst[10000],t=0; //操作数栈 14 int f(char op){ //将运算符对应到0-6的标号 15 switch(op){ 16 case '+': return 0; 17 case '-': return 1; 18 case '*': return 2; 19 case '/': return 3; 20 case '(': return 4; 21 case ')': return 5; 22 case '^': return 6; 23 } 24 } 25 26 void convert(char strz[],char strh[]){ 27 int len=strlen(strz); 28 int j=0; 29 opst[++top]='('; //在最外层添加左括号 30 31 //以下部分,opst[top]是栈顶的上一个运算符,strz[i]是当前扫描到的运算符 32 33 For(i,0,len-1){ 34 if (isdigit(strz[i])) strh[j++]=strz[i]; //如果是操作数,直接输出到strh中 35 else { 36 while (prior[f(opst[top])][f(strz[i])]>0) //将所有优先于strz[i]的opst[top]都弹出 37 strh[j++]=opst[top--]; 38 if (prior[f(opst[top])][f(strz[i])]==0) //如果str[i]是右括号,将栈顶的左括号弹出 39 top--; 40 else 41 opst[++top]=strz[i]; //如果str[i]不是右括号,将strz[i]压入栈 42 } 43 } 44 } 45 46 void print(char s[]){//给后缀表达式的剩余部分加上空格输出 47 int len=strlen(s); 48 For(i,0,len-1){ 49 printf("%c ",s[i]); 50 } 51 printf(" "); 52 } 53 54 void cal(char strh[]){ //后缀表达式的计算 55 int len=strlen(strh); 56 print(strh); //输出后缀表达式本身 57 For(i,0,len-1) //扫描后缀表达式 58 if (isdigit(strh[i])) numst[++t]=strh[i]-'0'; //数字字符就入操作数栈 59 else { 60 t--; //否则根据strh[i]运算符对栈顶的两个元素进行计算 61 switch(strh[i]){ 62 case '+':numst[t]=numst[t]+numst[t+1];break; 63 case '-':numst[t]=numst[t]-numst[t+1];break; 64 case '*':numst[t]=numst[t]*numst[t+1];break; 65 case '/':numst[t]=numst[t]/numst[t+1];break; 66 case '^':numst[t]=pow(numst[t],numst[t+1]);break; 67 } 68 For(j,1,t) printf("%d ",numst[j]); //输出计算完这一步的后缀表达式中间过程 69 print(strh+i+1); //分两段输出,前面一段对应操作数栈,后面一段对应未扫描的strh 70 } 71 } 72 73 int main(){ 74 gets(strz); 75 int len=strlen(strz); 76 strz[len]=')'; 77 strz[len+1]='