人非生而知之者,孰能無惑?
阿新 • • 發佈:2019-01-31
老規矩,1.你必須明白,什麼是圖?
2.圖是幹什麼的?
3.圖的最基本的物理儲存有哪些?
4.遍歷圖到底是在幹什麼?有哪些方式?
弄清楚這些,我這裡介紹一種,圖的鄰接表儲存方式實現的,完成初始化,輸出,和兩種遍歷方式。上程式碼,自己看
寫了兩種初始化方式,你可以呼叫由鍵盤輸入生成圖的方式,也可以由檔案資料生成圖的方式#include<iostream> #include<fstream> #include"sq_Queue.h" using namespace std; template <class T1> struct node{ int num; T1 val; node *next; }; template <class T1,class T2> struct gpnode{ T2 data; node<T1> *link; }; template <class T1,class T2> class Link_GP{ private: int nn; gpnode<T1,T2> *gp; public: Link_GP(){gp=NULL;return;} void create_Link_GP(int,T2[]); void create_Link_GP(int ,T2[],char *); void prt_Link_GP(); void dfs_Link_GP(); void bfs_Link_GP(); }; template <class T1,class T2> void Link_GP<T1,T2>::create_Link_GP(int n,T2 d[]){ node<T1> *p; int k,m; T1 v; nn=n; gp=new gpnode<T1,T2>[nn]; for(k=0;k<n;k++){ (gp+k)->data=d[k]; (gp+k)->link=NULL; cout<<"input the "<<k<< "after the node the info:"<<endl; cin>>m>>v; while(m>=0){ p=new node<T1>; p->num=m;p->val=v; p->next=(gp+k)->next; (gp+k)->link=p; cin>>m>>v; } } return; } template <class T1,class T2> void Link_GP<T1,T2>::create_Link_GP(int n,T2 d[],char *filename){ node<T1> *p; int k,m; T1 v; ifstream infile(filename,ios::in); nn=n; gp=new gpnode<T1,T2>[nn]; for(k=0;k<n;k++){ (gp+k)->data=d[k]; (gp+k)->link=NULL; infile>>m>>v; while(m>=0){ p=new node<T1>; p->num=m;p->val=v; p->next=(gp+k)->link; (gp+k)->link=p; infile>>m>>v; } } return; } template <class T1,class T2> void Link_GP<T1,T2>::prt_Link_GP(){ node<T1> *q; int k; for(k=0;k<nn;k++){ cout<<(gp+k)->data; q=(gp+k)->link; while(q!=NULL){ cout<<"-->"; cout<<q->num<<","<<q->val; q=q->next; } cout<<endl; } return; } template <class T1,class T2> void Link_GP<T1,T2>::dfs_Link_GP(){ int k,*mark; mark=new int[nn]; for(k=0;k<nn;k++) mark[k]=0; for(k=0;k<nn;k++) if(mark[k]==0) dfs(gp,k,mark); cout<<endl; delete mark; return ; } template <class T1,class T2> static dfs(gpnode<T1,T2> *q,int k,int *mark){ node<T1> *p; cout<<(q+k)->data<<" "; mark[k]=1; p=(q+k)->link; while(p!=NULL) { if(mark[p->num-1]==0) dfs(q,p->num-1,mark); p=p->next; } return 0; } template <class T1,class T2> void Link_GP<T1,T2>::bfs_Link_GP(){ int *mark,k; sq_Queue<int> q(nn); node<T1> *p; mark=new int[nn]; for(k=0;k<nn;k++) mark[k]=0; for(k=0;k<nn;k++) { if(mark[k]==0) { mark[k]=1; cout<<gp->data<<" "; q.ins_sq_Queue(k); while(q.flag_sq_Queue()) { k=q.del_sq_Queue(); p=(gp+k)->link; while(p!=NULL) { k=p->num-1; if(mark[k]==0) { cout<<(gp+k)->data<<" "; mark[k]=1; q.ins_sq_Queue(k); } p=p->next; } } } } cout<< endl; delete mark; return; }
其中,f1.txt就放在當前專案的目錄下,輸入內容如下:#include"Link_GP.h" int main(){ char d[8]={'A','B','C','D','E','F','G','H'}; Link_GP<int,char> g; g.create_Link_GP(8,d,"f1.txt"); cout<<"A=1,B=2,C=3,D=4,E=5,F=6,G=7,H=8"<<endl; cout<<endl; cout<<"圖g鄰接表:"<<endl; g.prt_Link_GP(); cout<<"DFS :"<<endl; g.dfs_Link_GP(); cout<<"BFS :"<<endl; g.bfs_Link_GP(); return 0; }
6 35 8 20 4 55 3 30 -1 -1
7 35 4 45 3 10 -1 -1
2 10 1 30 8 25 6 35 5 30 -1 -1
2 45 1 55 7 55 5 10 -1 -1
4 10 3 30 7 50 6 15 -1 -1
5 15 3 35 8 20 1 35 -1 -1
5 50 4 55 8 15 2 35 -1 -1
1 20 3 25 6 20 7 15 -1 -1
關於初始化:
其實,這個沒什麼難的,主要你明白圖的順序儲存空間結點,和單鏈表結點,這兩種型別,是怎麼回事?那麼初始化就很自然了。
關於深度遍歷:
1.要記住,它是遞迴 的深度遍歷。
需要一個輔助陣列,來標記它裡面的元素是否,被查詢過,具體怎麼找?
那就是遞迴的找,找到第一個點之後,找這個點鄰接的第一個點,這個點繼續找鄰接的鄰接的第一個點,有點繞,不過,你要首先明白,深度遍歷幹什麼?
假如,不理解遞迴,也可以這樣想:
1.我找一個結點作為當前結點
2.我找它的第一個後件結點,那麼現在判斷:1)假如它已經標記找到,那麼找當前節點的第二個結點
2)沒標記過,那麼呼叫這個函式,來遍歷它。
就這麼簡單,因為遞迴就是一個迴圈,假如你繞亂了,你就這麼簡單的邏輯想就好了。
關於廣度遍歷:
2.千萬記住,這個遍歷,需要一種資料結構,就是前面說的佇列,為什麼要用呢?你自己看看廣度遍歷到底在幹什麼,相信我就不用說了
1.找一個結點把它進佇列
2.把它出佇列,然後,找到它依次的後件結點,繼續把它們進佇列
3.把剛才這些的點,繼續出佇列,然後同樣的把後件進佇列
4.重複這個過程,值得標誌陣列,都為1,說明都找完了
附個結果圖,大家看看:
可以這樣講,假如你看不懂,最重要的一點就是,你根本不明白,深度遍歷,和廣度遍歷的過程,它們到底怎麼工作的。