数据结构上机实验
关于文件的输入输出,只要在主函数中添加:
freopen("E:\\read9.txt","r",stdin);
freopen("E:\\write9.txt","w",stdout);
即可。
其余地方的输入输出不变,但是必须用scanf和printf进行输入输出。
实验一 迷宫问题(bfs)
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"queue" 5 #include"string.h" 6 #include"cmath" 7 #include"stack" 8 #include"fstream" 9 #define mx 105 10 #define inf 1000 11 using namespace std; 12 int n,m; 13 int sx,sy,ex,ey; 14 int maze[mx][mx],vis[mx][mx]; 15 int dir[8][2]= {{0,1},{0,-1},{1,0},{-1,0},{-1,-1},{-1,1},{1,-1},{1,1}}; 16 bool judge(int x,int y) 17 { 18 if(maze[x][y]==0&&x>=0&&x<n&&y>=0&&y<m) 19 { 20 return true; 21 } 22 return false; 23 } 24 void output(int step) 25 { 26 int i; 27 stack<int>path; 28 path.push(ex*m+ey); 29 printf("%s%d\n","最少步骤是:",step); 30 int x=ex,y=ey,dx,dy; 31 while(vis[x][y]!=0) 32 { 33 for(i=0;i<8;i++) 34 { 35 dx=x+dir[i][0]; 36 dy=y+dir[i][1]; 37 if(dx>=0&&dx<n&&dy>=0&&dy<m) 38 if(vis[dx][dy]==vis[x][y]-1) 39 { 40 path.push(dx*m+dy); 41 break; 42 } 43 } 44 x=dx;y=dy; 45 } 46 printf("%s","最短路径为:"); 47 while(!path.empty()) 48 { 49 int u=path.top(); 50 path.pop(); 51 x=u/m;y=u%m; 52 if(x!=ex||y!=ey) 53 printf("%s%d%s%d%s%s","(",x,",",y,")","->"); 54 else printf("%s%d%s%d%s\n\n","(",x,",",y,")"); 55 } 56 57 } 58 void bfs(int step) 59 { 60 queue<int>q; 61 int i,x,y,dx,dy,u; 62 x=sx;y=sy; 63 u=x*m+y; 64 q.push(u); 65 while(!q.empty()) 66 { 67 u=q.front(); 68 q.pop(); 69 x=u/m;y=u%m; 70 if(x==ex&&y==ey) 71 { 72 output(step); 73 return; 74 } 75 int flag=1; 76 step=vis[x][y]; 77 for(i=0;i<8;i++) 78 { 79 dx=x+dir[i][0]; 80 dy=y+dir[i][1]; 81 if(judge(dx,dy)) 82 { 83 if(flag){step++;flag=0;} 84 maze[dx][dy]=1; 85 if(step<vis[dx][dy]) 86 vis[dx][dy]=step; 87 u=dx*m+dy; 88 q.push(u); 89 90 } 91 } 92 } 93 printf("%s","没有满足条件的通路!\n"); 94 } 95 int main() 96 { 97 int i,j; 98 freopen("C://read.txt","r",stdin); 99 freopen("C://write.txt","w",stdout); 100 while(scanf("%d%d",&n,&m),n||m) 101 { 102 for(i=0;i<n;i++) 103 { 104 for(j=0;j<m;j++) 105 {scanf("%d",&maze[i][j]);vis[i][j]=inf;} 106 } 107 scanf("%d%d%d%d",&sx,&sy,&ex,&ey); 108 maze[sx][sy]=1; 109 vis[sx][sy]=0; 110 bfs(0); 111 } 112 return 0; 113 }
实验二 锦标赛问题(简单的分治思想)
1 #include"iostream" 2 #include"stdio.h" 3 #include"cmath" 4 #include"string.h" 5 #include"algorithm" 6 #include"queue" 7 using namespace std; 8 const int mx=1005; 9 int calendar[mx][mx];//日程表 10 FILE* rfile=fopen("E:\\read2.txt","r"); 11 FILE* wfile=fopen("E:\\write2.txt","w");//文件读写 12 void championship(int k) 13 { 14 int i,j,t; 15 calendar[1][1]=1;//只有两个人比赛的情况 16 calendar[1][2]=2; 17 calendar[2][1]=2; 18 calendar[2][2]=1; 19 int temp=1; 20 for(t=1;t<k;t++) 21 { 22 temp*=2; 23 for(i=1;i<=temp;i++) 24 { 25 for(j=1;j<=temp;j++) 26 { 27 calendar[i+temp][j+temp]=calendar[i][j]; 28 } 29 } 30 for(i=1;i<=temp;i++)//用分治的方式打表 31 { 32 for(j=1;j<=temp;j++) 33 { 34 calendar[i+temp][j]=calendar[i][j]+temp; 35 } 36 } 37 38 for(i=temp+1;i<=temp*2;i++) 39 { 40 for(j=1;j<=temp;j++) 41 { 42 calendar[i-temp][j+temp]=calendar[i][j]; 43 } 44 } 45 } 46 47 int n=pow(2,k); 48 for(i=1;i<=n;i++)//日程表的输出 49 { 50 for(j=1;j<=n;j++) 51 fprintf(wfile,"%d ",calendar[i][j]); 52 fprintf(wfile,"%s\n",""); 53 } 54 fprintf(wfile,"%s\n","");//文件输出 55 } 56 int main() 57 { 58 int k,icase=0; 59 while((fscanf(rfile,"%d",&k),k!=-1)) 60 { 61 fprintf(wfile,"%s%d%s\n","Case ",++icase," :"); 62 fprintf(wfile,"%s%d\n","input k :",k); 63 championship(k); 64 } 65 fclose(wfile); 66 fclose(rfile); 67 return 0; 68 }
实验三 kruskal算法(最小生成树)
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"cmath" 5 #include"string.h" 6 #include"string" 7 using namespace std; 8 9 const int mx=105; 10 const int inf=32767; 11 FILE* rfile=fopen("E:\\read3.txt","r"); 12 FILE* wfile=fopen("E:\\write3.txt","w");//文件读写 13 struct Edge//记录边的两个端点和权值 14 { 15 int u; 16 int v; 17 int w; 18 }; 19 20 struct Mgraph 21 { 22 int edges[mx][mx];//存储边 23 int n;//顶点数 24 }; 25 26 struct UFStree//并查集的数据结构 27 { 28 int data;//节点对应的编号 29 int parent;//节点对应双亲下标 30 int rank;//节点对应秩 31 }; 32 33 bool cmp(const Edge a,const Edge b) 34 { 35 return a.w<b.w; 36 } 37 void Make_set(UFStree t[],int n)//初始化 38 { 39 for(int i=0;i<n;i++) 40 { 41 t[i].rank=0; 42 t[i].parent=i; 43 } 44 } 45 46 int Find_set(UFStree t[],int x)//查找集合的代表元素 47 { 48 while(x!=t[x].parent) 49 x=t[x].parent; 50 return x; 51 } 52 53 void Union(UFStree t[],int x,int y)//将两个集合并为一个 54 { 55 x=Find_set(t,x); 56 y=Find_set(t,y); 57 if(t[x].rank>t[y].rank)//将秩小的作为秩大的子集 58 t[y].parent=x; 59 else 60 { 61 t[x].parent=y; 62 if(t[x].rank==t[y].rank) t[y].rank++; 63 } 64 } 65 66 void Kruskal(Mgraph g)//求最小生成树的算法 67 { 68 69 int i,j,k,u1,v1,sn1,sn2; 70 UFStree t[mx]; 71 Edge E[mx]; 72 k=1; //E数组的下标从1开始 73 for(i=0;i<g.n;i++) //由g产生的边集E 74 for(j=0;j<g.n;j++) 75 { 76 if(g.edges[i][j]!=0&&g.edges[i][j]!=inf)//取出图的邻接矩阵中所有的边 77 { 78 E[k].u=i;E[k].v=j;E[k++].w=g.edges[i][j]; 79 } 80 } 81 sort(E,E+k,cmp);//按边的权值从小到大排序 82 Make_set(t,g.n); 83 k=1;//k表示当前构造生成树的第几条边,初值为1 84 j=1;//E中边的下标,初值为1 85 while(k<g.n) 86 { 87 u1=E[j].u; 88 v1=E[j].v; 89 sn1=Find_set(t,u1); 90 sn2=Find_set(t,v1); 91 if(sn1!=sn2)//两定顶点属于不同的集合,该边是最小生成树的一条边 92 { 93 fprintf(wfile,"%s%d%s%d%s%d\n","(",u1,",",v1,"):",E[j].w); 94 k++;//生成边数增1 95 Union(t,u1,v1);//将 u1和v1两个顶点合并 96 } 97 j++; 98 } 99 } 100 101 int main() 102 { 103 Mgraph g; 104 int i,j,n; 105 fprintf(wfile,"%s\n\n","输入顶点数为0时结束!"); 106 while(fscanf(rfile,"%d",&n),n) 107 { 108 fprintf(wfile,"%s%d\n","输入图的顶点数目:",n); 109 g.n=n; 110 fprintf(wfile,"%s\n","输入每个顶点与n个顶点边的权值:"); 111 for(i=0;i<n;i++) 112 { 113 for(j=0;j<n;j++) 114 {fscanf(rfile,"%d",&g.edges[i][j]);//取地址符很关键 115 fprintf(wfile,"%d ",g.edges[i][j]); 116 } 117 fprintf(wfile,"%s\n",""); 118 } 119 fprintf(wfile,"%s\n","输出构成最小生成树的边和顶点集:"); 120 Kruskal(g); 121 fprintf(wfile,"%s\n",""); 122 } 123 fclose(wfile);//关闭文件 124 fclose(rfile); 125 return 0; 126 }
实验四 哈夫曼编码
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"string" 5 #include"string.h" 6 #include"cmath" 7 #include"fstream" 8 using namespace std; 9 const int mx=105; 10 const int inf=32767;//表示无穷 11 FILE* rfile=fopen("E:\\read4.txt","r"); 12 FILE* wfile=fopen("E:\\write4.txt","w"); 13 struct htnode 14 { 15 char data;//节点值 16 double weight;//权重 17 int parent;//双亲节点 18 int lchild;//左孩子节点 19 int rchild;//右孩子节点 20 }; 21 22 struct hcode 23 { 24 char cd[mx];//存放当前结点的哈夫曼码 25 int start;//cd[start]~cd[n]存放哈夫曼码 26 }; 27 void CreatHuffman(htnode ht[],int n) 28 { 29 int i,j,k,lnode,rnode; 30 double min1,min2; 31 for(i=0;i<2*n-1;i++)//所有节点的相关域置初值-1 32 { 33 ht[i].parent=ht[i].lchild=ht[i].rchild=-1; 34 } 35 for(i=n;i<2*n-1;i++)//构造哈弗曼树 36 { 37 min1=min2=inf; 38 lnode=rnode=-1;//lnode和rnode为最小权重的两个结点位置 39 for(k=0;k<=i-1;k++)//在ht[]中找权值最小的两个结点 40 { 41 if(ht[k].parent==-1)//只在尚未构造二叉树的结点中查找 42 { 43 if(ht[k].weight<min1) 44 { 45 min2=min1;rnode=lnode; 46 min1=ht[k].weight;lnode=k; 47 } 48 else if(ht[k].weight<min2) 49 { 50 min2=ht[k].weight;rnode=k; 51 } 52 } 53 } 54 ht[i].weight=ht[lnode].weight+ht[rnode].weight; 55 ht[i].lchild=lnode;ht[i].rchild=rnode;//ht[i]作为双亲结点 56 ht[lnode].parent=i;ht[rnode].parent=i; 57 } 58 } 59 60 void CreatHuffmanCode(htnode ht[],hcode hcd[],int n) 61 { 62 int i,f,c; 63 hcode hc; 64 for(i=0;i<n;i++)//根据哈夫曼树求哈夫曼编码 65 { 66 hc.start=n;c=i; 67 f=ht[i].parent; 68 while(f!=-1) 69 { 70 if(ht[f].lchild==c) 71 hc.cd[hc.start--]='0'; 72 else 73 hc.cd[hc.start--]='1'; 74 c=f;f=ht[f].parent; 75 } 76 hc.start++;hcd[i]=hc; 77 } 78 } 79 void display(htnode ht[],hcode hcd[],int n) 80 { 81 for(int i=0;i<n;i++) 82 { 83 fprintf(wfile,"%c%s",ht[i].data,": "); 84 for(int j=hcd[i].start;j<=n;j++) 85 fprintf(wfile,"%c",hcd[i].cd[j]); 86 fprintf(wfile,"%s\n",""); 87 } 88 fprintf(wfile,"%s\n",""); 89 } 90 int main() 91 { 92 htnode ht[mx]; 93 hcode hcd[mx]; 94 char enter;//用于清除换行 95 int n,i,j; 96 while(fscanf(rfile,"%d",&n),n) 97 { 98 for(i=0;i<n;i++) 99 { 100 fscanf(rfile,"%c%c%lf",&enter,&ht[i].data,&ht[i].weight); 101 } 102 CreatHuffman(ht,n); 103 CreatHuffmanCode(ht,hcd,n); 104 display(ht,hcd,n); 105 } 106 fclose(wfile); 107 fclose(rfile); 108 return 0; 109 }
实验五 树和二叉树
任务(1)和(2):
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"string" 5 #include"string.h" 6 #include"Stack" 7 #include"queue" 8 #include"vector" 9 //顺序表ADT的定义 10 //datatype的定义 11 #ifndef datatype 12 #define datatype NODE 13 #define _ERROR NULL 14 #endif 15 FILE* rfile=fopen("E:\\read5.txt","r"); 16 FILE* wfile=fopen("E:\\write5.txt","w"); 17 //树结点的定义 18 struct Tnode{ 19 struct Tnode * lchild; 20 struct Tnode * rchild; 21 char* data;//data用于保存节点信息,类型为字符串 22 }; 23 typedef struct Tnode * Bitree; 24 typedef struct Tnode * NODE; 25 struct Table{ //为了定义栈 26 datatype* Table_head; 27 int Length; 28 int Max_Length; 29 }; 30 typedef struct Table* mystable; 31 32 //栈ADT的定义 33 typedef struct Table* mystack; 34 //为顺序表分配空间,将所有数据初始化为init 35 mystable Assign(const int maxlen,datatype init) 36 { 37 mystable temp; 38 if((temp=(mystable)malloc(sizeof(struct Table)))!=NULL){//分配空间成功 39 temp->Max_Length = maxlen; 40 temp->Length=0; 41 if((temp->Table_head=(datatype *)malloc(sizeof(datatype)*maxlen))!=NULL) 42 for(int i=0;i<maxlen;i++) 43 *(temp->Table_head+i)=init; 44 else 45 return NULL; 46 return temp; 47 } 48 return NULL; 49 } 50 51 //判断表是否为空 52 int isEmpty(const mystable table) 53 { 54 if (table==NULL) 55 return -1; 56 if(table->Length == 0) 57 return 1; 58 return 0; 59 } 60 61 //判断表是否为满 62 int isFull(const mystable table) 63 { 64 if (table==NULL) 65 return -1; 66 if(table->Length == table->Max_Length) 67 return 1; 68 return 0; 69 } 70 71 //获取position位置的数据 72 datatype get(const mystable table,int position) 73 { 74 if (position>table->Length-1 || position<0) 75 return _ERROR; 76 return *(table->Table_head + position); 77 } 78 79 //获取表长 80 int getLength(const mystable table) 81 { 82 if (table==NULL) 83 return -1; 84 return table->Length; 85 } 86 87 //从表中删除一个数据 88 int Remove(const mystable table,int position) 89 { 90 int i=0; 91 if(table==NULL) 92 return -1; 93 if(position>table->Length-1 || position<0) 94 return 0; 95 for(i=position;i<table->Length-1;i++) 96 *(table->Table_head+i)=*(table->Table_head+(i+1)); 97 table->Length--; 98 return 1; 99 } 100 101 //插入一个数据到position位置 102 int Insert(mystable table,int position,datatype data) 103 { 104 int i=0; 105 if(table==NULL) 106 return -1; 107 if(position>table->Length || position<0) 108 return 0; 109 if(isFull(table)==0){ 110 for(i=table->Length;i>position;i--) 111 *(table->Table_head+i)=*(table->Table_head+(i-1)); 112 *(table->Table_head+i)=data; 113 table->Length++; 114 }else{ 115 mystable temp; 116 if((temp=(mystable)malloc(sizeof(struct Table)))==NULL) 117 return -1; 118 if((temp->Table_head=(datatype*) malloc(sizeof(datatype)*(table->Max_Length+1)))==NULL) 119 return -1; 120 temp->Length=table->Max_Length+1; 121 temp->Max_Length=table->Max_Length+1; 122 for(i=0;i<position;i++) 123 *(temp->Table_head+i)=*(table->Table_head+i); 124 *(temp->Table_head+i)=data; 125 for(i++;i<temp->Length;i++) 126 *(temp->Table_head+i)=*(table->Table_head+(i-1)); 127 free(table->Table_head); 128 free(table); 129 table=temp; 130 } 131 return 1; 132 } 133 134 //释放表占用的空间 135 int del(const mystable table) 136 { 137 free(table->Table_head); 138 free(table); 139 return 1; 140 } 141 //在表的最后插入一个数据 142 int add(const mystable table,datatype x) 143 { 144 return Insert(table,table->Length,x); 145 } 146 //初始化栈,分配空间 147 mystack initial() 148 { 149 return Assign(100,0); 150 } 151 152 //从栈中弹出一个数据 153 datatype pop(mystack Stack) 154 { 155 if(Stack==NULL) 156 return _ERROR; 157 if(isEmpty(Stack)) 158 return _ERROR; 159 datatype data; 160 data=get(Stack,Stack->Length-1); 161 Remove(Stack,Stack->Length-1); 162 return data; 163 } 164 165 //返回栈顶的数据但不弹出 166 datatype peek(mystack Stack) 167 { 168 if(Stack==NULL) 169 return _ERROR; 170 if(isEmpty(Stack)) 171 return _ERROR; 172 datatype data; 173 data=get(Stack,Stack->Length-1); 174 return data; 175 } 176 177 //向栈中压入数据 178 int push(mystack Stack,datatype x) 179 { 180 return Insert(Stack,Stack->Length,x); 181 } 182 183 184 //分配一个新的树节点 185 NODE newNode(char* data) 186 { 187 NODE temp=(NODE)malloc(sizeof(struct Tnode)); 188 if(temp==NULL) 189 return NULL; 190 temp->lchild=NULL; 191 temp->rchild=NULL; 192 temp->data=data; 193 return temp; 194 } 195 196 //字符串转化为中缀顺序表,这是本实验的核心代码 197 mystable char_to_infix(char ex[]) 198 { 199 int length=strlen(ex); 200 mystable infix=Assign(length,NULL); 201 char* temp; 202 for (int i = 0; i < length; i++) { 203 if ((ex[i] >= '0' && ex[i] <= '9') || ex[i] == '.' ) { 204 //若是数字字符则查询直到遇到一个不是数字的字符 205 int Count=0; 206 for(int j=i;(ex[j] >= '0' && ex[j] <= '9') || ex[j] == '.';j++,Count++); 207 temp=(char *)malloc(sizeof(char)*(Count+1)); 208 for(int j=0;j<Count;j++) 209 temp[j]=ex[i+j]; 210 temp[Count]='\0'; 211 add(infix,newNode(temp)); 212 i=i+Count-1; 213 }else{ 214 temp=(char *)malloc(sizeof(char)*2); 215 temp[0]=ex[i];temp[1]='\0'; 216 add(infix,newNode(temp)); 217 } 218 } 219 return infix; 220 } 221 222 //中缀表达式转化为后缀表达式 223 mystable infix_to_postfix(mystable infix) 224 { 225 mystack Stack=initial(); 226 mystable postfix=Assign(getLength(infix),NULL); 227 for (int i = 0; i < getLength(infix); i++) { 228 char opF,opS; 229 opF=get(infix,i)->data[0]; 230 if ((opF>='0' && opF<='9') || opF=='.' || (opF>='a' && opF<='z')) 231 //数字则直接压入后缀表达式 232 add(postfix,get(infix,i)); 233 else{ 234 if (getLength(Stack) == 0) { 235 push(Stack,get(infix,i)); 236 } else if (opF == '(') { 237 push(Stack,get(infix,i)); 238 } else if (opF == ')') { 239 //遇到右括号,将栈中的数据依次弹出,直到遇到左括号 240 do { 241 opS = peek(Stack)->data[0]; 242 if (opS != '(') 243 add(postfix,pop(Stack)); 244 else 245 pop(Stack); 246 } while (opS != '('); 247 } else { 248 //比较优先级,若优先级高于栈顶元素则压入栈,否则弹出 249 do { 250 opS = peek(Stack)->data[0]; 251 int spriority,fpriority; 252 switch(opS){ 253 //设置优先级 254 case '+':spriority=4;break; 255 case '-':spriority=4;break; 256 case '*':spriority=3;break; 257 case '/':spriority=3;break; 258 case '^':spriority=2;break; 259 case '(':spriority=7;break; 260 } 261 switch(opF){ 262 case '+':fpriority=4;break; 263 case '-':fpriority=4;break; 264 case '*':fpriority=3;break; 265 case '/':fpriority=3;break; 266 case '^':fpriority=2;break; 267 case '(':spriority=7;break; 268 } 269 if (fpriority >= spriority) 270 add(postfix,pop(Stack)); 271 else 272 break; 273 } while (getLength(Stack) != 0); 274 push(Stack,get(infix,i)); 275 } 276 } 277 } 278 while (getLength(Stack) != 0) 279 add(postfix,pop(Stack)); 280 //释放括号占用的内存 281 for(int i=0;i<getLength(infix);i++){ 282 NODE temp=get(infix,i); 283 if(temp->data[0]=='(' || temp->data[0]==')'){ 284 free(temp->data); 285 free(temp); 286 } 287 } 288 //释放栈占用的内存 289 del(Stack); 290 //释放掉前缀表达式占用的内存 291 del(infix); 292 return postfix; 293 } 294 295 //生成表达式树 296 Bitree postfix_to_binarytree(mystable postfix) 297 { 298 mystack Stack=initial(); 299 for (int i = 0; i < getLength(postfix); i++) { 300 char name; 301 name=get(postfix,i)->data[0]; 302 if ((name>='0' && name<='9') || name=='.' || (name>='a' && name<='z')){ 303 push(Stack,get(postfix,i)); 304 }else{ 305 NODE parent=get(postfix,i); 306 NODE lchild,rchild; 307 //从栈中弹出操作数,将运算符节点的两个儿子指针指向操作数结点 308 if(getLength(Stack)!=0){ 309 rchild=pop(Stack); 310 parent->rchild=rchild; 311 } 312 if(getLength(Stack)!=0){ 313 lchild=pop(Stack); 314 parent->lchild=lchild; 315 } 316 push(Stack,parent); 317 } 318 } 319 if(getLength(Stack)!=1){ 320 return NULL; 321 }else{ 322 NODE result=pop(Stack); 323 //释放内存 324 free(Stack); 325 free(postfix); 326 return result; 327 } 328 } 329 330 //打印前缀表达式 331 void print_prefix(Bitree node) 332 { 333 if(node==NULL) 334 return; 335 fprintf(wfile,"%s",node->data); 336 if(node->lchild!=NULL) 337 print_prefix(node->lchild); 338 if(node->rchild!=NULL) 339 print_prefix(node->rchild); 340 } 341 342 //打印后缀表达式 343 void print_postfix(Bitree node) 344 { 345 if(node==NULL) 346 return; 347 if(node->lchild!=NULL) 348 print_postfix(node->lchild); 349 if(node->rchild!=NULL) 350 print_postfix(node->rchild); 351 fprintf(wfile,"%s",node->data); 352 } 353 354 355 356 //递归打印叶节点递归函数入口 357 void _print_path_with_recursion(Bitree tree,NODE path[],int depth) 358 { 359 if(tree==NULL) 360 return; 361 //若为叶节点则打印路径 362 if(tree->lchild==NULL && tree->rchild==NULL){ 363 fprintf(wfile,"%s : %s",tree->data,tree->data); 364 for(int i=depth-1;i>=0;i--) 365 fprintf(wfile," %s",path[i]->data); 366 fprintf(wfile,"%s\n",""); 367 } 368 if(tree->lchild!=NULL){ 369 path[depth]=tree; 370 _print_path_with_recursion(tree->lchild,path,depth+1); 371 } 372 if(tree->rchild!=NULL){ 373 path[depth]=tree; 374 _print_path_with_recursion(tree->rchild,path,depth+1); 375 } 376 } 377 378 //非递归打印叶节点 379 void print_path_without_recursion(Bitree tree) 380 { 381 NODE curr=tree; 382 NODE path[100]; 383 //存放深度的数组 384 int depth[100]; 385 int top=0,curdepth=0; 386 387 mystack track=initial(); 388 do{ 389 if(curr!=NULL){ 390 if(curr->lchild==NULL && curr->rchild==NULL){ 391 fprintf(wfile,"%s : %s",curr->data,curr->data); 392 for(int i=curdepth-1;i>=0;i--) 393 fprintf(wfile," %s",path[i]->data); 394 fprintf(wfile,"%s\n",""); 395 //从栈中弹出下一个要访问的结点,并将当前深度更新为该结点深度 396 curr=pop(track); 397 curdepth=depth[--top]; 398 }else{ 399 path[curdepth]=curr; 400 push(track,curr->rchild); 401 depth[top++]=++curdepth; 402 curr=curr->lchild; 403 } 404 }else{ 405 curr=pop(track); 406 curdepth=depth[--top]; 407 } 408 }while(curr!=NULL || getLength(track)!=0); 409 } 410 //递归打印叶节点主程序入口 411 void print_path_with_recursion(Bitree tree) 412 { 413 NODE path[100]; 414 _print_path_with_recursion(tree,path,0); 415 } 416 int main(){ 417 char ch[100]; 418 int icase=1; 419 while(fscanf(rfile,"%s",ch),strcmp(ch,"no")!=0)//输入表达式 420 { 421 fprintf(wfile,"%s%d%s\n\n","案例 #",icase++,": "); 422 mystable infix=char_to_infix(ch); 423 mystable postfix=infix_to_postfix(infix); 424 Bitree root=postfix_to_binarytree(postfix); 425 if(root==NULL) 426 fprintf(wfile,"%s","输入有误!\n\n"); 427 else{ 428 fprintf(wfile,"%s","输出前缀表达式: "); 429 print_prefix(root);//输出前缀式 430 fprintf(wfile,"%s\n\n",""); 431 fprintf(wfile,"%s","输出后缀表达式: "); 432 print_postfix(root);//输出后缀式2 433 fprintf(wfile,"%s\n\n",""); 434 fprintf(wfile,"%s\n","用递归打印从根节点到叶子节点的路径:"); 435 print_path_with_recursion(root); 436 fprintf(wfile,"%s\n",""); 437 fprintf(wfile,"%s\n","用非递归打印从根节点到叶子节点的路径:"); 438 print_path_without_recursion(root); 439 } 440 } 441 return 0; 442 }
任务(3):
对于拓扑排序,我用了两种方法,一种是利用邻接矩阵:
1 #include"iostream" 2 #include"stdio.h" 3 #include"cmath" 4 #include"string.h" 5 #include"queue" 6 #include"stack" 7 #include"vector" 8 #include"algorithm" 9 #include"fstream" 10 using namespace std; 11 const int mx=105; 12 const int inf=32767;//表示无穷大 13 FILE* rfile=fopen("E:\\read6.txt","r"); 14 FILE* wfile=fopen("E:\\write6.txt","w"); 15 int n,m;;//n表示节点的数目,m表示边的数目 16 int topoArray[mx];//拓扑排序的数组 17 bool visited[mx];//用来标记该顶点是否已被访问过 18 bool cnt[mx];//用于拓扑排序中判断某个点是否已进栈 19 struct Mgraph//图的邻接矩阵 20 { 21 int NumVertices,NumEdges; 22 int Edges[mx][mx]; 23 }; 24 struct EdgeNode//邻接表的边节点类型 25 { 26 int dest;//边的另一顶点位置 27 int weight;//边的权重 28 EdgeNode *link;//下一条链指针 29 }; 30 struct VertexNode//顶点节点类型(表头节点) 31 { 32 int data; 33 EdgeNode *first; 34 }; 35 struct ALGraph//邻接表类型 36 { 37 VertexNode verticeslish[mx]; 38 int NumVetices,NumEdeges; 39 }; 40 //创建图的邻接矩阵表示 41 void Creat_Mgraph(Mgraph &M) 42 { 43 int i; 44 M.NumVertices=n; 45 M.NumEdges=m; 46 //初始化所有边之间的权值为-1,表示两个结点之间无直接通路 47 memset(M.Edges,-1,sizeof(M.Edges)); 48 for(i=0;i<m;i++) 49 { 50 int p,q,w; 51 fscanf(rfile,"%d%d%d",&p,&q,&w); 52 M.Edges[p][q]=w; 53 } 54 } 55 //将邻接矩阵转换为邻接表表示 56 void Mgraph_to_ALGraph(Mgraph &M,ALGraph &ALG) 57 { 58 ALG.NumVetices=M.NumVertices; 59 ALG.NumEdeges=M.NumEdges; 60 int i,j; 61 for(i=0;i<n;i++) 62 { 63 ALG.verticeslish[i].data=i; 64 ALG.verticeslish[i].first=NULL; 65 for(j=0;j<n;j++) 66 { 67 if(M.Edges[i][j]!=-1) 68 { 69 EdgeNode *temp=new EdgeNode; 70 temp->link=ALG.verticeslish[i].first; 71 temp->weight=M.Edges[i][j]; 72 temp->dest=j; 73 ALG.verticeslish[i].first=temp; 74 } 75 } 76 } 77 } 78 //输出图的邻接矩阵表示 79 void Output_Mgraph(Mgraph &M) 80 { 81 int i,j; 82 for(i=0;i<M.NumVertices;i++) 83 { 84 fprintf(wfile,"%d%s",i,": "); 85 for(j=0;j<M.NumVertices;j++) 86 { 87 fprintf(wfile,"%d%s",M.Edges[i][j]," "); 88 } 89 fprintf(wfile,"%s\n",""); 90 } 91 fprintf(wfile,"%s\n",""); 92 } 93 //输出图的邻接表表示 94 void Output_ALGraph(ALGraph &ALG) 95 { 96 int i; 97 for(i=0;i<ALG.NumVetices;i++) 98 { 99 int flag=false; 100 fprintf(wfile,"%d%s",i,": "); 101 EdgeNode *temp; 102 temp=ALG.verticeslish[i].first; 103 while(temp!=NULL) 104 { 105 flag=true; 106 fprintf(wfile,"%d%s%d%s",temp->dest,"(",temp->weight,") "); 107 temp=temp->link; 108 } 109 if(!flag) fprintf(wfile,"%s\n","空"); 110 fprintf(wfile,"%s\n",""); 111 } 112 } 113 //用dfs递归遍历从0开始的深度优先遍历序列 114 void Dfs_From_0(int k,ALGraph &ALG) 115 { 116 if(!visited[k]) 117 { 118 fprintf(wfile,"%d%s",k," "); 119 visited[k]=true; 120 EdgeNode *temp=ALG.verticeslish[k].first; 121 while(temp!=NULL) 122 { 123 Dfs_From_0(temp->dest,ALG); 124 temp=temp->link; 125 } 126 } 127 } 128 //从0开始的广度优先遍历非递归算法 129 void Bfs_From_0(int k,ALGraph &ALG) 130 { 131 memset(visited,false,sizeof(visited)); 132 fprintf(wfile,"%d%s",k," "); 133 visited[k]=true; 134 EdgeNode *temp=ALG.verticeslish[k].first; 135 queue<EdgeNode *>q; 136 while(temp!=NULL) 137 { 138 if(!visited[temp->dest]) 139 {q.push(temp);visited[temp->dest]=true;} 140 temp=temp->link; 141 } 142 EdgeNode *cur; 143 while(!q.empty()) 144 { 145 cur=q.front(); 146 q.pop(); 147 k=cur->dest; 148 fprintf(wfile,"%d%s",k," "); 149 cur=ALG.verticeslish[k].first; 150 while(cur!=NULL) 151 { 152 if(!visited[cur->dest]) 153 {q.push(cur);visited[cur->dest]=true;} 154 cur=cur->link; 155 } 156 } 157 } 158 //判断某个节点是否入度为零 159 bool Judge_Column(Mgraph &M,int k) 160 { 161 int i; 162 for(i=0;i<M.NumVertices;i++) 163 { 164 if(M.Edges[i][k]!=-1) 165 { 166 return false; 167 } 168 } 169 return true; 170 } 171 //输出拓扑排序的结果 172 void Output_Topoarray(Mgraph &M,int k) 173 { 174 if(k<M.NumVertices) 175 fprintf(wfile,"%s\n","图中有有向环!"); 176 else 177 { 178 fprintf(wfile,"%s","输出该图的拓扑序列: "); 179 for(int i=0;i<k;i++) 180 fprintf(wfile,"%d%s",topoArray[i]," "); 181 } 182 fprintf(wfile,"%s\n",""); 183 } 184 //进行拓扑排序 185 void TopologicalSort(Mgraph &M) 186 { 187 memset(cnt,false,sizeof(cnt)); 188 stack<int>S; 189 int k=0,i,j; 190 for(i=0;i<M.NumVertices;i++) 191 { 192 if(Judge_Column(M,i)&&!cnt[i]) 193 { 194 cnt[i]=true; 195 topoArray[k++]=i; 196 S.push(i); 197 } 198 } 199 while(!S.empty()) 200 { 201 int cur=S.top(); 202 S.pop(); 203 for(j=0;j<M.NumVertices;j++) 204 M.Edges[cur][j]=-1; 205 for(i=0;i<M.NumVertices;i++) 206 { 207 if(Judge_Column(M,i)&&!cnt[i]) 208 { 209 cnt[i]=true; 210 topoArray[k++]=i; 211 S.push(i); 212 } 213 } 214 } 215 Output_Topoarray(M,k); 216 } 217 218 int main() 219 { 220 int iCase=1;//案例个数 221 Mgraph M; 222 ALGraph ALG; 223 while(fscanf(rfile,"%d%d",&n,&m),n&&m) 224 { 225 fprintf(wfile,"%s%d%s\n","案例 #",iCase++,": "); 226 Creat_Mgraph(M); 227 Mgraph_to_ALGraph(M,ALG); 228 fprintf(wfile,"%s\n","输出图的邻接矩阵表示:"); 229 Output_Mgraph(M); 230 fprintf(wfile,"%s\n","输出图的邻接表表示:"); 231 Output_ALGraph(ALG); 232 memset(visited,false,sizeof(visited)); 233 fprintf(wfile,"%s","输出从0开始的递归dfs遍历:"); 234 Dfs_From_0(0,ALG); 235 fprintf(wfile,"%s\n",""); 236 fprintf(wfile,"%s","输出从0开始的非递归bfs遍历: "); 237 Bfs_From_0(0,ALG); 238 fprintf(wfile,"%s\n",""); 239 TopologicalSort(M); 240 fprintf(wfile,"%s\n",""); 241 } 242 return 0; 243 }
一种是利用邻接表:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <Queue> 4 #include <string.h> 5 #include <Stack> 6 using namespace std; 7 bool visit[1000]; 8 int inCount[1000]; 9 10 typedef struct EdgeNode{ 11 int dest; 12 int cost; 13 struct EdgeNode *Link; 14 }; 15 typedef struct VertexNode 16 { 17 int data; 18 struct EdgeNode *first; 19 }; 20 typedef struct ALGraph 21 { 22 VertexNode *VerticesList; 23 int numVertices,numEdges; 24 }; 25 void InitGraph(ALGraph& G) 26 { 27 G.numVertices=0; 28 G.numEdges=0; 29 G.VerticesList=new VertexNode[1000]; 30 for (int i=0;i<1000;i++) 31 { 32 G.VerticesList[i].first=NULL; 33 } 34 }; 35 int GetVertexPos(ALGraph& G,int vertex)/*找出该顶点的顶点号*/ 36 { 37 for (int i=0;i<G.numVertices;i++) 38 if (G.VerticesList[i].data==vertex) 39 return i; 40 return -1; 41 } 42 int GetValue(ALGraph& G,int i)/*返回顶点i,不合理则返回0*/ 43 { 44 if (i==-1) 45 return 0; 46 else 47 return G.VerticesList[i].data; 48 }; 49 int FirstNeighbor(ALGraph& G,int v)/*返回顶点v的第一个邻接顶点的顶点号,若无则返回-1*/ 50 { 51 if (v!=-1) 52 { 53 EdgeNode *p=G.VerticesList[v].first; 54 if (p!=NULL) 55 return p->dest; 56 } 57 else return -1; 58 } 59 60 int NextNeighbor(ALGraph &g, int v, int w)/*返回在顶点v的邻接顶点w后的下一个顶点号,没有则返回-1*/ 61 { 62 EdgeNode *p; 63 p=g.VerticesList[v].first; 64 while(p) 65 { 66 if(p->dest==w&&p->Link!=NULL) 67 return p->Link->dest; 68 p=p->Link; 69 } 70 return -1; 71 } 72 73 void creat(ALGraph& G) 74 { 75 int i,j,k; 76 EdgeNode *s; 77 int n,m; 78 int weight; 79 printf("请输入顶点数和边数:\n"); 80 scanf("%d %d",&G.numVertices,&G.numEdges); 81 printf("输入顶点信息:\n"); 82 for (i=0;i<G.numVertices;i++) 83 { 84 scanf("%d",&G.VerticesList[i].data); 85 G.VerticesList[i].first=NULL; 86 } 87 printf("输入边的信息:\n"); 88 for (k=0;k<G.numEdges;k++) 89 { 90 scanf("%d %d %d",&i,&j,&weight); 91 s=new EdgeNode; 92 s->dest=j; 93 inCount[j]++; 94 s->cost=weight; 95 s->Link=G.VerticesList[i].first; 96 97 G.VerticesList[i].first=s; 98 } 99 100 } 101 102 int Numberofvertices(ALGraph& G)/*返回图中的顶点个数*/ 103 { 104 return G.numVertices; 105 } 106 void PrintfGraph(ALGraph& G)/*输出有向图邻接表*/ 107 { 108 int i,j; 109 EdgeNode *p; 110 printf("图G的顶点数是:%d\n",G.numVertices); 111 printf("顶点向量的值是:"); 112 for (i=0;i<G.numVertices;i++) 113 printf("%d ",G.VerticesList[i].data); 114 printf("\n"); 115 printf("图G的边数是:%d\n",G.numEdges); 116 for (i=0;i<G.numVertices;i++){ 117 for (p=G.VerticesList[i].first;p!=NULL;p=p->Link) 118 printf("(%d,%d,%d)\n",i,p->dest,p->cost); 119 } 120 }; 121 void DFS(ALGraph& G,int v,bool visited[])/*DFS*/ 122 { 123 printf("%d ",GetValue(G,v)); 124 visited[v]=true; 125 int w=FirstNeighbor(G,v); 126 while (w!=-1) 127 { 128 if (visited[w]==false) 129 DFS(G,w,visited); 130 w=NextNeighbor(G,v,w); 131 } 132 }; 133 134 135 void BFS(ALGraph&G, int v)/*BFS*/ 136 { 137 int i,k,w,n=Numberofvertices(G); 138 for (i=0;i<n;i++) 139 visit[i]=false; 140 queue <int > q;/*创建队列*/ 141 if (!visit[v]) 142 { 143 printf("%d ",G.VerticesList[v].data); 144 visit[v]=true; 145 } 146 q.push(v); 147 while (!q.empty()) 148 { 149 int vv=q.front(); 150 q.pop(); 151 for (int w = FirstNeighbor(G, vv); w >= 0; w = NextNeighbor(G, vv, w)) 152 { 153 if (!visit[w]) 154 { 155 printf("%d ",G.VerticesList[w].data); 156 visit[w] = true; 157 q.push(w); 158 } 159 } 160 } 161 delete[]visit; 162 }; 163 void TopologicalSort(ALGraph& g)//拓扑排序算法 164 { 165 166 stack<int> s; 167 for(int i=1;i<=g.numVertices;i++) 168 if(!inCount[i]) 169 s.push(g.VerticesList[i].data);//入度为0者进栈 170 int count=0; 171 while(!s.empty()) 172 { 173 int v = s.top(); 174 s.pop(); 175 printf("%d ",v); 176 count++; 177 for(EdgeNode *p = g.VerticesList[v].first ; p!=NULL ; p=p->Link) 178 { 179 //对i号顶点的每个邻接点的入度减1,新产生的入度为0的顶点进栈 180 int k = p->dest; 181 if(!(--inCount[g.VerticesList[k].data])) 182 s.push(g.VerticesList[k].data); 183 } 184 } 185 printf("\n") 186 if(count<g.numVertices) 187 printf("存在回路\n"); 188 else 189 printf("存在拓扑排序\n"); 190 } 191 192 193 int main() 194 { 195 int start; 196 int i,j; 197 ALGraph G; 198 InitGraph(G); 199 creat(G); 200 PrintfGraph(G); 201 TopologicalSort(G); 202 printf("输入从哪个点开始DFS遍历:\n"); 203 scanf("%d",&start); 204 DFS(G,start,visit); 205 printf("\n"); 206 printf("输入从哪个点开始BFS遍历:\n"); 207 scanf("%d",&start); 208 BFS(G,start); 209 printf("\n"); 210 211 return 0; 212 }
实验六:
1、顺序查找和二分查找
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"string.h" 5 #include"string" 6 #include"fstream" 7 #include"cmath" 8 #include"queue" 9 #include"stack" 10 #include"vector" 11 using namespace std; 12 const int mx=1005; 13 FILE* rfile=fopen("E:\\read7.txt","r"); 14 FILE* wfile=fopen("E:\\write7.txt","w"); 15 16 struct SeqList //顺序表的数据结构 17 { 18 int DataNum; 19 int data[mx]; 20 }; 21 //顺序查找 22 int SeqFind(SeqList &L,int x) 23 { 24 int step=1; 25 L.data[L.DataNum]=x;//监视哨 26 for(int i=0;i<=L.DataNum;i++) 27 { 28 fprintf(wfile,"%s%d%s%d %d\n","第 ",step++," 步查找到的值和下标分别为:",L.data[i],i); 29 if(x==L.data[i]) return i; 30 } 31 } 32 //二分查找 33 int BinFind(SeqList &L,int x) 34 { 35 int step=1; 36 int mid,left,high; 37 left=0;high=L.DataNum-1; 38 while(left<=high) 39 { 40 mid=(left+high)/2; 41 fprintf(wfile,"%s%d%s%d %d\n","第 ",step++," 步查找到的值和下标分别为:",L.data[mid],mid); 42 if(L.data[mid]==x) 43 return mid; 44 else if(x<L.data[mid]) 45 high=mid-1; 46 else 47 left=mid+1; 48 } 49 return L.DataNum; 50 } 51 int main() 52 { 53 int iCase=1;//案例个数 54 int num;//元素个数; 55 int i,j,FindNum;//FindNum为查找返回的下标 56 while(fscanf(rfile,"%d",&num),num!=0) 57 { 58 fprintf(wfile,"%s%d%s\n","案例 #",iCase++,": "); 59 SeqList L; 60 L.DataNum=num; 61 fprintf(wfile,"%s","输出原始序列: "); 62 for(i=0;i<num;i++) 63 {fscanf(rfile,"%d",&L.data[i]);fprintf(wfile,"%d ",L.data[i]);} 64 fprintf(wfile,"%s\n",""); 65 fscanf(rfile,"%d",&FindNum); 66 fprintf(wfile,"%s%d\n\n","需要查找的数(顺序查找): ",FindNum); 67 fprintf(wfile,"%s\n","输出查找过程: "); 68 int FindResult=SeqFind(L,FindNum); 69 fprintf(wfile,"%s\n","输出查找结果: "); 70 if(FindResult==L.DataNum) 71 fprintf(wfile,"%s%d%s\n\n","原序列中不存在 ",FindNum,"!"); 72 else 73 fprintf(wfile,"%d%s%d\n\n",FindNum," 在原序列中的下标为: ",FindResult); 74 sort(L.data,L.data+L.DataNum); 75 fprintf(wfile,"%s","将上面的序列排好序输出: "); 76 for(i=0;i<num;i++) 77 fprintf(wfile,"%d%s",L.data[i]," "); 78 fprintf(wfile,"%s\n\n",""); 79 fprintf(wfile,"%s%d\n\n","需要查找的数(折半查找): ",FindNum); 80 FindResult=BinFind(L,FindNum); 81 fprintf(wfile,"%s\n","输出查找结果: "); 82 if(FindResult==L.DataNum) 83 fprintf(wfile,"%s%d%s\n\n","新序列中不存在 ",FindNum,"!"); 84 else 85 fprintf(wfile,"%d%s%d\n\n",FindNum," 在新序列中的下标为: ",FindResult); 86 } 87 return 0; 88 }
2、直接插入排序
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"string.h" 5 #include"string" 6 #include"cmath" 7 #include"queue" 8 #include"stack" 9 #include"vector" 10 #include"fstream" 11 using namespace std; 12 const int mx=1005; 13 //输出序列 14 void Output_Array(int Array[],int Num) 15 { 16 int i; 17 for(i=0;i<Num;i++) 18 printf("%d ",Array[i]); 19 printf("\n"); 20 } 21 //直接插入排序 22 void Straight_Insertion_Sort(int Array[],int Num) 23 { 24 int i,j; 25 for(i=1;i<Num;i++) 26 { 27 if(Array[i]<Array[i-1]) 28 { 29 int temp=Array[i]; 30 for(j=i-1;j>=0&&Array[j]>temp;j--) 31 { 32 Array[j+1]=Array[j]; 33 } 34 Array[j+1]=temp; 35 } 36 printf("第%d次进行插入排序得到的序列: ",i); 37 Output_Array(Array,Num); 38 } 39 } 40 41 int main() 42 { 43 int iCase=1; 44 freopen("E:\\read8.txt","r",stdin); 45 freopen("E:\\write8.txt","w",stdout); 46 int Array[mx]; 47 int i,j,Num; 48 while(scanf("%d",&Num),Num!=0) 49 { 50 printf("案例 #%d :\n",iCase++); 51 for(i=0;i<Num;i++) 52 scanf("%d",&Array[i]); 53 printf("原始序列:"); 54 for(i=0;i<Num;i++) 55 printf("%d ",Array[i]); 56 printf("\n"); 57 Straight_Insertion_Sort(Array,Num); 58 } 59 }
3、快速排序
1 #include"iostream" 2 #include"stdio.h" 3 #include"algorithm" 4 #include"string.h" 5 #include"string" 6 #include"cmath" 7 #include"queue" 8 #include"stack" 9 #include"vector" 10 #include"map" 11 using namespace std; 12 const int mx=1005; 13 int step;//记录快速排序进行的步数 14 int num;//记录序列中元素的个数 15 void Quick_Sort(int Array[],int low,int high) 16 { 17 if(low>=high) return; 18 int first=low; 19 int last=high; 20 int key=Array[first]; 21 while(first<last)//将比key小的放到key前面,比key大的放到key后面 22 { 23 while(first<last&&Array[last]>=key) last--; 24 Array[first]=Array[last]; 25 while(first<last&&Array[first]<=key) first++; 26 Array[last]=Array[first]; 27 } 28 Array[first]=key; 29 printf("第 %d 次排序后的序列: ",step++);//输出序列 30 for(int i=0;i<num;i++) 31 printf("%d ",Array[i]); 32 printf("\n"); 33 Quick_Sort(Array,low,first-1);//分治的思想 34 Quick_Sort(Array,first+1,high); 35 } 36 int main() 37 { 38 int i,iCase=1; 39 int Array[mx]; 40 freopen("E:\\read9.txt","r",stdin); 41 freopen("E:\\write9.txt","w",stdout); 42 while(scanf("%d",&num),num!=0) 43 { 44 step=1; 45 printf("案例 #%d : \n",iCase++); 46 for(i=0;i<num;i++) 47 scanf("%d",&Array[i]); 48 printf("进行快速排序:\n"); 49 Quick_Sort(Array,0,num-1); 50 } 51 return 0; 52 }