邻接表十字链表
鄰接表:
每一行都可以看成一個單鏈表,第一行中,v0-1-3可以得到,v0的出度為v1和v3。
鄰接表完整代碼:
#include <iostream> using namespace std;const int MAX_V = 15;//邊節點 typedef struct Edge_node {char data;Edge_node *next; }Enode,*pEnode;//表節點 typedef struct List_node {char data;Edge_node *firstEdge; }Lnode, *pLnode;int main() {void AddEdge( char v1, char v2, pLnode list, int V );void display( pLnode list, int V );void clear( pLnode list, int V);int V,E;cout << "input vertex number and edge number:\n";//輸入頂點數和邊數cin >> V >> E;Lnode list[MAX_V];//建立數組for( int i=0; i<V; ++i ){list[i].firstEdge = NULL;}cout << "input vertex:\n";//輸入頂點for( int i=0; i<V; ++i )cin >> list[i].data;cout << "input edges, eg: a b \n";char v1,v2;for( int i=0; i<E; ++i ){cin >> v1 >> v2;AddEdge( v1, v2, list, V);}//輸出cout <<"display:\n";display( list, V );cout << "clear:\n";clear( list, V );return 0; }void AddEdge( char v1, char v2, pLnode list, int V ) {for( int i=0; i<V; ++i ){if( v1==list[i].data ){//生成新的邊節點pEnode newEdge = new Enode;newEdge->data = v2;newEdge->next = NULL;newEdge->next = list[i].firstEdge;list[i].firstEdge = newEdge;break;}} }void display( pLnode list, int V ){for( int i=0; i<V; ++i ){cout << list[i].data <<": ";pEnode p = list[i].firstEdge;while( p ){cout << p->data << ' ';p = p->next;}cout <<endl;} }void clear( pLnode list, int V){for( int i=0; i<V; ++i ){pEnode p = list[i].firstEdge;pEnode todel;while( NULL!=p ){todel = p;cout <<"delete is "<< todel->data << ' ';p = p->next;delete todel;}cout << endl;}}但對于有向圖來說,鄰接表是有缺陷的,關心了出度問題,想了解入度就必須要遍歷整個圖才能知道,反之,逆鄰接表解決了入度的情況。
而十字鏈表可以同時解決出度和入度的問題。
十字鏈表
重新定義表節點結構:增加了兩個指針firstIn,firstOut。分別用來指向該頂點的入(出)邊表中第一個結點。
firstin表示入邊表頭指針,指向該頂點的入邊表中第一個結點;
firstout表示出邊表頭指針,指向該頂點的出邊表中第一個結點;
tailvex是指弧起點在頂點的下標,
headvex是指弧終點在頂點表中的下標,
headlink是指入邊表指針域,指向終點相同的一下條邊
taillink是指出邊表指針域,指向起點相同的下一條邊。
對比
與鄰接表相比,這里的 tailLink 指針就相當于鄰接表里的那個指針,指向出度的下一個節點。而這里的 headLink 就是新增加的用來記錄入度的指針。
首先,橫著看:每一行都可以看出單鏈表,把從 firstOut 出來的串起來就是出度(類似鄰接表);
豎著看(不太明顯):從 headLink 出來的指針指向串起來,都是入度節點。
那為什么要重復存儲節點信息呢?例如圖中的0存了2次,1存了3次等。這是為了方便找入度節點。試想,鄰接表用一個指針一個節點信息來存儲方便找出度,那么要是出度入度都方便找,自然要給入度也加上一個指針(headLink)和一個數據域(tailVex)。這樣當找到入度的邊接節點,取出 headLink 就找到入度節點了。
將邊節點結構分割:
入度:headLink + tailVex;
出度:tailLink + headVex;
十字鏈表代碼:
#include <iostream> #include <cstring> using namespace std;const int MAX_V = 15; //邊節點 typedef struct Edge_node {char tailVex,headVex; //tailvex是指弧起點在頂點的下標,headvex是指弧終點在頂點表中的下標,Edge_node *tailLink, *headLink;//headlink指向弧頭相同的下一條弧。taillink指向弧尾相同的下一條弧. }Enode,*pEnode;//表節點 typedef struct List_node {char data;Edge_node *firstIn, *firstOut;//firstin表示入邊表頭指針,指向該頂點的入邊表中第一個結點. }Lnode, *pLnode;int main() {void AddEdge( char v1, char v2, pLnode list, int V );void display( pLnode list, int V );void clear( pLnode list, int V);int V,E;cout << "input vertex number and edge number:\n";//輸入頂點數和邊數cin >> V >> E;Lnode list[MAX_V];//建立數組for( int i=0; i<V; ++i ){list[i].firstIn = NULL;list[i].firstOut = NULL;}//輸入頂點cout << "input vertex:\n";for( int i=0; i<V; ++i )cin >> list[i].data;//輸入邊cout << "input edges, eg: a b \n";char v1,v2;for( int i=0; i<E; ++i ){cin >> v1 >> v2;AddEdge( v1, v2, list, V);}//輸出cout <<"display:\n";display( list, V );cout << "clear:\n";clear( list, V );return 0; }void AddEdge( char v1, char v2, pLnode list, int V ){int getIndex( char x , pLnode list , int V );int v1_index = getIndex( v1 , list, V );int v2_index = getIndex( v2, list ,V );pEnode newEdge = new Enode;newEdge->tailVex = v1;newEdge->headVex = v2;//添加出度newEdge->tailLink = list[v1_index].firstOut;list[v1_index].firstOut = newEdge;//添加入度newEdge->headLink = list[v2_index].firstIn;list[v2_index].firstIn = newEdge; } int getIndex( char x, pLnode list, int V ){for( int i=0; i<V; ++i ){if( x==list[i].data )return i;} }void display( pLnode list, int V ){for( int i=0; i<V; ++i ){cout << list[i].data <<" out : ";pEnode p = list[i].firstOut;while( p ){cout << p->headVex << ' ';p = p->tailLink;}cout <<endl;cout << list[i].data <<" in : ";p = list[i].firstIn;while( p ){cout << p->tailVex << ' ';p = p->headLink;}cout <<endl;}}void clear( pLnode list, int V){for( int i=0; i<V; ++i ){pEnode p = list[i].firstOut;pEnode todel;while( NULL!=p ){todel = p;cout <<"delete is "<< todel->headVex << ' ';p = p->tailLink;delete todel;}cout << endl;} }總結
- 上一篇: python时间计算_python计算两
- 下一篇: 解决Unity3D导出apk失败:Fai