C語言資料結構--相對路徑設計
阿新 • • 發佈:2018-12-30
#include<stdio.h> #include<stdlib.h> #include<iomanip.h> #include <process.h> typedef struct node//邊表結點 { int adjvex; //鄰接點編號 int dut; //弧的資訊 struct node *next; //下一條弧指標 }edgenode; typedef struct //頂點表結點 { int projectname;//頂點域 int id;//頂點的入度資訊 edgenode *link; //邊表頭指標 }vexnode; void CreateGraphic(vexnode* Graphicmap,int projectnumber,int activenumber)//建立圖 { int begin,end,duttem; //分別代表弧的前節點,尾節點,活動時間 edgenode *p;// 邊表頭指標 for(int i=0;i<projectnumber;i++) { Graphicmap[i].projectname=i;//頂點的命名按0,1,2,3...... Graphicmap[i].id =0;//頂點的資訊的度數均賦為零 Graphicmap[i].link =NULL; } printf("\n"); printf("請輸入某專案的資訊,並請用整形數字表示(格式:弧頭,弧尾,權值):\n"); printf("例如:輸入1,2,4 即代表結點1與4之間的活動需要4個時間單位。\n"); printf("\n"); for(int k=0;k<activenumber;k++) //activenumber為活動的數目,即弧的條數 { scanf("%d,%d,%d",&begin,&end,&duttem); //請輸入第%d條的起點、終點和權值 p=(edgenode*)malloc(sizeof(edgenode));//臨時分配儲存空間 p->adjvex =end-1;//因為是從零開始記的,姑要減一,就是讓終點插入到鄰接表內 p->dut =duttem; //該弧的活動時間為duttem Graphicmap[end-1].id ++; //入度加一 p->next =Graphicmap[begin-1].link ; Graphicmap[begin-1].link =p;//讓下一個節點作為下一插入節點的前驅節點 } } int SearchMapPath(vexnode* Graphicmap,int projectnumber,int activenumber ,int& totaltime) //求出最大路徑,並打印出關鍵路徑 { int i,j,k,m=0; int front=-1,rear=-1; int* topologystack=(int*)malloc(projectnumber*sizeof(int));//用來儲存拓撲排列 int* vl=(int*)malloc(projectnumber*sizeof(int));//用來表示在不推遲整個工程的前提下,VJ允許最遲發生的時間 int* ve=(int*)malloc(projectnumber*sizeof(int));//用來表示Vj最早發生時間 int* l=(int*)malloc(activenumber*sizeof(int));//用來表示活動Ai最遲完成開始時間 int* e=(int*)malloc(activenumber*sizeof(int));//表示活動最早開始時間 edgenode *p; //邊表頭的指標 totaltime=0; //存放整個工程的最短時間 for(i=0;i<projectnumber;i++) ve[i]=0;//先把每個工程的最早發生時間初始化為零 for(i=0;i<projectnumber;i++) { if(Graphicmap[i].id==0) { topologystack[++rear]=i;//讓所有的頭節點入佇列 m++; //記錄入佇列的頂點個數 } } while(front!=rear) { front++; //出佇列 j=topologystack[front]; //拓撲排序的節點依次出佇列 m++; //記錄入佇列的節點個數 p=Graphicmap[j].link ; //指向頂點指向的下一個頂點 while(p) { k=p->adjvex ; // 鄰接點編號 Graphicmap[k].id --;//讓入度減一,相當於刪除一個入度為零的前驅節點,和相關的弧 if(ve[j]+p->dut >ve[k])//將最長的路徑賦給VE[K] ve[k]=ve[j]+p->dut ; if(Graphicmap[k].id ==0)//如果入度為零,則入佇列 topologystack[++rear]=k; p=p->next ; //指向下一個節點 } } if(m<projectnumber)//如果有環,則不能遍歷每個節點 { printf("\n本程式所建立的圖有迴路不可計算出關鍵路徑!\n"); printf("將退出本程式!\n"); return 0; } totaltime=ve[projectnumber-1];//最短完成時間即為最後一個節點所累加的時間之和 for(i=0;i<projectnumber;i++) vl[i]=totaltime; for(i=projectnumber-2;i>=0;i--)// 用逆拓撲排序來求活動Ai最遲完成開始時間,即從最後一個節點減去最短的時間 { j=topologystack[i]; p=Graphicmap[j].link ; while(p) { k=p->adjvex ; if((vl[k]-p->dut )<vl[j]) vl[j]=vl[k]-p->dut ; p=p->next ; } } i=0; printf("\n"); printf("| 起點 | 終點 | 最早開始時間 | 最遲完成時間 | 差值 | 備註 \n"); for(j=0;j<projectnumber;j++) { p=Graphicmap[j].link; while(p) { k=p->adjvex ; e[++i]=ve[j]; l[i]=vl[k]-p->dut; printf("| %4d | %4d | %11d | %11d | %3d |",Graphicmap[j].projectname +1,Graphicmap[k].projectname +1,e[i],l[i],l[i]-e[i]); if(l[i]==e[i]) //當差值為零時,則為關鍵路徑 printf(" 關鍵活動 <%2d,%4d>", Graphicmap[j].projectname +1,Graphicmap[k].projectname +1); printf("\n"); p=p->next ; } } return 1; } void seekkeyroot()//求關鍵路徑的主函式 { int projectnumber,activenumber,totaltime=0; printf("\n"); printf("輸入符合標準,歡迎進入求關鍵路徑的系統!\n"); printf("\n"); printf("請輸入這個專案的AOE-網的節點數: "); scanf("%d",&projectnumber); printf("請輸入這個專案的AOE-網的活動個數: "); scanf("%d",&activenumber); vexnode* Graphicmap=(vexnode*)malloc(projectnumber*sizeof(vexnode)); CreateGraphic(Graphicmap,projectnumber,activenumber);//建立鄰接圖 SearchMapPath(Graphicmap,projectnumber,activenumber,totaltime);//求出最大路徑,並打印出關鍵路徑 printf("\n"); printf("整個工程所用的最短時間為:%d個單位時間\n",totaltime); system("pause"); } int main() { char ch; for(;;) { do { system("cls"); printf("☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ \n"); printf(" 歡迎進入求關鍵路徑演算法程式 \n"); printf("☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★ \n"); printf("%s","\ns(start)開始輸入工程的節點資料並求出關鍵路徑\n"); printf("\n"); printf("%s","e(exit)退出\n"); printf("\n"); printf("%s","請輸入選擇:"); scanf("%c",&ch); ch=toupper(ch); }while(ch!='S'&&ch!='E'); switch(ch) { case'S': seekkeyroot(); break; case'E': return 1; } } }