完整测试代码

零零散散学算法系列相关算法的完整测试代码

零零散散学算法系列:http://blog.csdn.net/column/details/superfc-algorithm.html

第一部分 最短路径算法

第一节 戴克斯特拉算法(Dijkstra algorithm)

第二节 弗洛伊德算法(Floyd algorithm)

第三节 A*搜索算法


第二部分 最小生成树

第一节 克鲁斯卡尔算法(Kruskal algorithm)

第二节 普利姆算法(Prim algorithm)


第三部分 结束语

第一部分 最短路径算法

第一节 戴克斯特拉算法(Dijkstra algorithm)

#include <stdio.h> #include <string.h> #include <Windows.h> typedef char VertexType; /***顶点***/ typedef int EdgeType; /***边***/ #define maxvex 100 #define INFINITY 65535 int vexnum = 0; #define FALSE 0 #define TRUE 1 typedef struct { VertexType vexs[maxvex]; /***顶点个数***/ EdgeType arc[maxvex][maxvex]; /***两顶点构成边的权值***/ }Mgraph; int create(Mgraph *gph) { //memset(gph->arc,INFINITY,(maxvex*maxvex)); //memset(gph->vexs,0,maxvex); int n; int i, j; int temp1,temp2; for(i = 0;i < maxvex;i++) for(j = 0;j < maxvex;j++) gph->arc[i][j] = INFINITY; memset(gph->vexs,0,maxvex); printf("-----------这是一个有向图----------\n"); printf("请输入有向图的顶点个数:"); scanf("%d",&n); vexnum = n; printf("请输入有向图的各个顶点:"); for(i = 0; i < n;i++) scanf(" %c",&(gph->vexs[i])); while(1) { printf("请输入可形成边的两个节点:"); scanf("%d %d",&temp1,&temp2); if(temp1 >= n || temp2 >= n) break; printf("请输入边的权值:"); scanf("%d",&gph->arc[temp1][temp2]); } /***这个图的矩阵表示如下***/ for(i = 0; i < n;i++) for(j = 0;j < n;j++) { printf("%d\t",gph->arc[i][j]); if(((j+1) % n) == 0) printf("\n"); } return 0; } int ShortPath(Mgraph *G,int v0,int (*P)[maxvex],int *D) { //用戴克斯特拉算法求有向图G中v0顶点到其余顶点v的最短路径P[v]及带权长度D[v]。 //若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。 //final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。 int v, w, min,i; int final[maxvex] = {0}; for(v = 0;v < vexnum;v++) { final[v] = FALSE; D[v] = G->arc[v0][v]; for(w = 0;w < vexnum;w++) P[v][w] = FALSE; //设空路径 if(D[v] < INFINITY) { P[v][v0] = TRUE; P[v][v] = TRUE; } } D[v0] = 0;final[v0] = TRUE; //初始化,v0顶点属于S集合 //开始主循环,每次求得v0到某个顶点v的最短路径,并将v加到S集合中 for(i = 1; i < vexnum; i++) //其余G.vexnum - 1个顶点 { min = INFINITY; //当前所知离v0点的最近距离 for(w = 0;w < vexnum; w++) { if(!final[w]) //w顶点在V-S中 { if(D[w] < min) //w顶点离v0更近 { v = w; min = D[w]; } } } final[v] = TRUE; //离v0顶点最近的v加入到S中 for(w = 0;w < vexnum;w++) //更新当前最算路径及距离 { if(!final[w] && (min + G->arc[v][w] < D[w])) { D[w] = min + G->arc[v][w]; //p[w] = P[v] + P[w]; //P[w] = P[v]; P[w][w] = TRUE; } } } return 0; } int main() { Mgraph *graph = NULL; int D[maxvex] = {0}; int P[maxvex][maxvex] = {0}; graph = (Mgraph *)malloc(sizeof(Mgraph)); create(graph); ShortPath(graph,0,P,D); system("pause"); return 0; }


第二节 弗洛伊德算法(Floyd algorithm)

#include <stdio.h> #include <string.h> #include <Windows.h> typedef char VertexType; /***顶点***/ typedef int EdgeType; /***边***/ #define maxvex 100 #define INFINITY 65535 int vexnum = 0; typedef struct { VertexType vexs[maxvex]; /***顶点个数***/ EdgeType arc[maxvex][maxvex]; /***两顶点构成边的权值***/ }Mgraph; int create(Mgraph *gph) { //memset(gph->arc,INFINITY,(maxvex*maxvex)); //memset(gph->vexs,0,maxvex); int n; int i, j; int temp1,temp2; for(i = 0;i < maxvex;i++) for(j = 0;j < maxvex;j++) gph->arc[i][j] = 0; memset(gph->vexs,0,maxvex); printf("-----------这是一个有向图----------\n"); printf("请输入有向图的顶点个数:"); scanf("%d",&n); vexnum = n; printf("请输入有向图的各个顶点:"); for(i = 0; i < n;i++) scanf(" %c",&(gph->vexs[i])); while(1) { printf("请输入可形成边的两个节点:"); scanf("%d %d",&temp1,&temp2); if(temp1 >= n || temp2 >= n) break; printf("请输入边的权值:"); scanf("%d",&gph->arc[temp1][temp2]); } /***这个图的矩阵表示如下***/ for(i = 0; i < n;i++) for(j = 0;j < n;j++) { printf("%d\t",gph->arc[i][j]); if(((j+1) % n) == 0) printf("\n"); } return 0; } int ShortPath(Mgraph *G,int (*D)[maxvex]) { //用Floyd算法求有向图中各对顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]。 //若p[v][w][u]为TRUE,则u是从v到w当前求得的最短路径上的顶点 int v, w, u; for(v = 0;v < vexnum;v++) { for(w = 0;w < vexnum;w++) { D[v][w] = G->arc[v][w]; printf("%d\t",D[v][w]); /* if(D[v][w] < INFINITY) //从v到w有直接路径 { P[v][w][u] = TRUE; P[v][w][w] = TRUE; } */ } printf("\n"); } for(u = 0;u < vexnum;u++) for(v = 0;v < vexnum;v++) { for(w = 0;w < vexnum;w++) { if(D[v][u] + D[u][w] < D[v][w]) //从v经u到w的一条更短路径 { D[v][w] = D[v][u] + D[u][w]; printf("从v-%d经u-%d到w-%d的最短路径的值是:%d\n",v,u,w,D[v][w]); /* for(i = 0;i < G.vexnum;i++) P[v][w][i] = P[v][u][i] || P[u][w][i]; */ } } } return 0; } int main() { Mgraph *graph = NULL; int D[maxvex][maxvex] = {0}; graph = (Mgraph *)malloc(sizeof(Mgraph)); create(graph); ShortPath(graph,D); system("pause"); return 0; }

第三节 A*搜索算法

//节点结构体 typedef struct Node { int data[9]; double f,g; struct Node * parent; }Node,*Lnode; //OPEN CLOSED 表结构体 typedef struct Stack { Node * npoint; struct Stack * next; }Stack,* Lstack; //选取OPEN表上f值最小的节点,返回该节点地址 Node * Minf(Lstack * Open) { Lstack temp = (*Open)->next,min = (*Open)->next,minp = (*Open); Node * minx; while(temp->next != NULL) { if((temp->next ->npoint->f) < (min->npoint->f)) { min = temp->next; minp = temp; } temp = temp->next; } minx = min->npoint; temp = minp->next; minp->next = minp->next->next; free(temp); return minx; } //判断是否可解 int Canslove(Node * suc, Node * goal) { int a = 0,b = 0,i,j; for(i = 1; i< 9;i++) for(j = 0;j < i;j++) { if((suc->data[i] > suc->data[j]) && suc->data[j] != 0) a++; if((goal->data[i] > goal->data[j]) && goal->data[j] != 0) b++; } if(a%2 == b%2) return 1; else return 0; } //判断节点是否相等 ,1相等,0不相等 int Equal(Node * suc,Node * goal) { for(int i = 0; i < 9; i ++ ) if(suc->data[i] != goal->data[i])return 0; return 1; } //判断节点是否属于OPEN表 或 CLOSED表,是则返回节点地址,否则返回空地址 Node * Belong(Node * suc,Lstack * list) { Lstack temp = (*list) -> next ; if(temp == NULL)return NULL; while(temp != NULL) { if(Equal(suc,temp->npoint))return temp -> npoint; temp = temp->next; } return NULL; } //把节点放入OPEN 或CLOSED 表中 void Putinto(Node * suc,Lstack * list) { Stack * temp; temp =(Stack *) malloc(sizeof(Stack)); temp->npoint = suc; temp->next = (*list)->next; (*list)->next = temp; } ///计算f值部分-开始// double Fvalue(Node suc, Node goal, float speed) {//计算f值 double Distance(Node,Node,int); double h = 0; for(int i = 1; i <= 8; i++) h = h + Distance(suc, goal, i); return h*speed + suc.g; //f = h + g(speed值增加时搜索过程以找到目标为优先因此可能不会返 回最优解) } double Distance(Node suc, Node goal, int i) {//计算方格的错位距离 int k,h1,h2; for(k = 0; k < 9; k++) { if(suc.data[k] == i)h1 = k; if(goal.data[k] == i)h2 = k; } return double(fabs(h1/3 - h2/3) + fabs(h1%3 - h2%3)); } ///计算f值部分-结束// ///扩展后继节点部分的函数-开始/ int BelongProgram(Lnode * suc ,Lstack * Open ,Lstack * Closed ,Node goal ,float speed) {//判断子节点是否属于OPEN或CLOSED表 并作出相应的处理 Node * temp = NULL; int flag = 0; if((Belong(*suc,Open) != NULL) || (Belong(*suc,Closed) != NULL)) { if(Belong(*suc,Open) != NULL) temp = Belong(*suc,Open); else temp = Belong(*suc,Closed); if(((*suc)->g) < (temp->g)) { temp->parent = (*suc)->parent; temp->g = (*suc)->g; temp->f = (*suc)->f; flag = 1; } } else { Putinto(* suc, Open); (*suc)->f = Fvalue(**suc, goal, speed); } return flag; } void Spread(Lnode * suc, Lstack * Open, Lstack * Closed, Node goal, float speed) {//扩展后继节点总函数 int i; Node * child; for(i = 0; i < 4; i++) { if(Canspread(**suc, i+1)) //判断某个方向上的子节点可否扩展 { child = (Node *) malloc(sizeof(Node)); //扩展子节点 child->g = (*suc)->g +1; //算子节点的g值 child->parent = (*suc); //子节点父指针指向父节点 Spreadchild(child, i); //向该方向移动空格生成子节点 if(BelongProgram(&child, Open, Closed, goal, speed)) // 判断子节点是否属 于OPEN或CLOSED表 并作出相应的处理 free(child); } } } ///扩展后继节点部分的函数-结束// Node * Process(Lnode * org, Lnode * goal, Lstack * Open, Lstack * Closed, float speed) {//总执行函数 while(1) { if((*Open)->next == NULL)return NULL; //判断OPEN表是否为空,为空则失败退出 Node * minf = Minf(Open); //从OPEN表中取出f值最小的节点 Putinto(minf, Closed); //将节点放入CLOSED表中 if(Equal(minf, *goal))return minf; //如果当前节点是目标节点,则成功退出 Spread(&minf, Open, Closed, **goal, speed); //当前节点不是目标节点时扩展当前节点的后继 节点 } } int Shownum(Node * result) {//递归显示从初始状态到达目标状态的移动方法 if(result == NULL)return 0; else { int n = Shownum(result->parent); for(int i = 0; i < 3; i++) { printf("/n"); for(int j = 0; j < 3; j++) { if(result->data[i*3+j] != 0) printf(" %d ",result->data[i*3+j]); else printf(" "); } } printf("/n"); return n+1; } }

附注:A*搜索算法的代码来自v_JULY_v的专栏http://blog.csdn.net/v_july_v/article/details/6238029

第二部分 最小生成树(稍后送上)

第一节 克鲁斯卡尔算法(Kruskal algorithm)

第二节 普利姆算法(Prim algorithm)

第三部分 结束语

未完,待续!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值