1. 程式人生 > >資料結構---圖(鄰接表)

資料結構---圖(鄰接表)

// Graph_Adjacency List.cpp : Defines the entry point for the console application.
/*-----CODE FOR FUN---------------
-------CREATED BY Dream_Whui------
-------2015-2-12--------------------*/

#include "stdafx.h"
#include <iostream>
#include <queue>
using namespace std;

#define      MAX_VERTEX_NUM    20

#define   TRUE             1
#define   FALSE            0
#define   OK               1
#define   ERROR            0
#define   OVERFLOW          -2
#define   INFEASIBLE      -1

typedef        char*    VertexType;
typedef        int        InfoType;

typedef enum
{
    DG,DN,UDG,UDN//有向圖,有向網,無向圖,無向網
}GraphKind;

typedef struct ArcNode
{    
    int                adjvex;        //該弧所指向的頂點的位置
    struct ArcNode    *nextarc;    //指向下一條弧的指標
    InfoType        *info;        //該弧相關資訊的指標
}ArcNode;

typedef struct VNode
{
    VertexType        data;        //頂點資訊
    ArcNode            *firstarc;    //指向第一條依附該頂點的弧的指標
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct
{
    AdjList    vertices;
    int        vexnum,arcnum;        //頂點數,弧數
    int        kind;                //圖的種類標記
}ALGraph;

bool visited[MAX_VERTEX_NUM];

int CreateDG(ALGraph &G);//構造有向圖
int CreateDN(ALGraph &G);//構造有向網
int CreateUDG(ALGraph &G);//構造無向圖
int CreateUDN(ALGraph &G);//構造無向網

int CreateGraph(ALGraph &G)//採用鄰接表表示法,構造圖G
{
    int n;
    cout<<"建立有向圖(0),有向網(1),無向圖(2),無向網(3)"<<endl;
    cin>>n;
    switch(n)
    {
    case DG:
        G.kind = DG;
        return CreateDG(G);//有向圖
    case DN:
        G.kind = DN;
        return CreateDN(G);//有向網
    case UDG:
        G.kind = UDG;
        return CreateUDG(G);//無向圖
    case UDN:
        G.kind = UDN;
        return CreateUDN(G);//無向網
    default:
        return ERROR;
    }
}

int LocateVex(ALGraph G, VertexType v)    //頂點v在圖中的位置
{
    int i;
    for(i=0; i<G.vexnum; i++)
    {
        if(strcmp(G.vertices[i].data,v)==0)
            return i;
    }
    return -1;
}

void CreateSub(ALGraph &G, int i, int j, int* w)//建立圖(網)的輔助函式,構建第i個頂點到第j個頂點,權值w
{
    ArcNode *e, *p, *pre;
    e = (ArcNode*)malloc(sizeof(ArcNode));
    p = (ArcNode*)malloc(sizeof(ArcNode));
    pre = (ArcNode*)malloc(sizeof(ArcNode));
    e->adjvex = j;                        //
    e->nextarc = NULL;
    e->info = w;
    if(!G.vertices[i].firstarc)            //在頭結點後插入
            G.vertices[i].firstarc = e;
        else                            
        {
            p = G.vertices[i].firstarc;
            if(p->adjvex < j)            //在第一個結點前插入(第一個結點指頭結點後面的那個結點)
            {
                e->nextarc = p;
                G.vertices[i].firstarc = e;
            }
            else                        //在第以個結點後插入
            {
                pre = p;
                p = p->nextarc;
                while(p)
                {
                    if(p->adjvex < j)
                    {
                        e->nextarc = p;
                        pre->nextarc = e;
                        break;
                    }
                    pre = p;
                    p = p->nextarc;
                }
                if(!p)                    //在尾結點後插入
                    pre->nextarc = e;
            }
        }
}

int CreateDG(ALGraph &G)//構造有向圖
{
    cout<<"輸入頂點數,邊數:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//構造頂點向量
    {
        cout<<"輸入第"<<i+1<<"個頂點的名稱:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"輸入相連的邊(v1,v2):";
        cin>>v1>>v2;
        i = LocateVex(G,v1);//弧尾
        j = LocateVex(G,v2);//弧頭
        w = 1;
        CreateSub(G,i,j,&w);
    }
    G.kind = DG;
    return OK;
}

int CreateUDG(ALGraph &G)//構造無向圖
{
    cout<<"輸入頂點數,邊數:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//構造頂點向量
    {
        cout<<"輸入第"<<i+1<<"個頂點的名稱:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"輸入相連的邊(v1,v2):";
        cin>>v1>>v2;
        i = LocateVex(G,v1);//邊的起點
        j = LocateVex(G,v2);//邊的終點
        CreateSub(G,i,j,&w);
        CreateSub(G,j,i,&w);
    }
    G.kind = UDG;
    return OK;
}

int CreateDN(ALGraph &G)//構造有向網
{
    cout<<"輸入頂點數,邊數:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//構造頂點向量
    {
        cout<<"輸入第"<<i+1<<"個頂點的名稱:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"輸入相連的邊及權值(v1,v2,w):";
        cin>>v1>>v2>>w;
        i = LocateVex(G,v1);//弧尾
        j = LocateVex(G,v2);//弧頭
        CreateSub(G,i,j,&w);
    }
    G.kind = DN;
    return OK;
}

int CreateUDN(ALGraph &G)//構造無向網
{
    cout<<"輸入頂點數,邊數:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//構造頂點向量
    {
        cout<<"輸入第"<<i+1<<"個頂點的名稱:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"輸入相連的邊及權值(v1,v2,w):";
        cin>>v1>>v2>>w;
        i = LocateVex(G,v1);//邊的起點
        j = LocateVex(G,v2);//邊的終點
        CreateSub(G,i,j,&w);
        CreateSub(G,j,i,&w);
    }
    G.kind = UDN;
    return OK;
}

VertexType GetVex(ALGraph G, int v)//返回圖中第V個頂點
{
    if(v<0 || v>G.vexnum)
        return NULL;
    return G.vertices[v-1].data;
}

int PutVex(ALGraph &G, VertexType v, VertexType value)//修改圖中頂點v的名稱為value
{
    int i;
    i = LocateVex(G,v);
    if(i<0)
        return ERROR;
    else
        strcpy(G.vertices[i].data,value);
    return OK;
}

ArcNode* FirstAdjVex(ALGraph G, VertexType v)//返回頂點V的第一個鄰接點
{
    int i;
    i = LocateVex(G,v);
    if(i<0)
        return NULL;
    else
        return G.vertices[i].firstarc;
}

ArcNode* NextAdjVex(ALGraph G, VertexType v, VertexType w)//返回頂點V的(相對於w)下一個鄰接點
{
    int i,j,k;
    i = LocateVex(G,v);
    j = LocateVex(G,w);
    if(i<0 || j<0)
        return NULL;
    ArcNode *p;
    p = G.vertices[i].firstarc;
    while(p)
    {
        if(p->adjvex == j)
            return p->nextarc;
        p = p->nextarc;
    }
}

void InsertVex(ALGraph &G, VertexType v)//插入頂點
{
    G.vertices[G.vexnum].data = (VertexType)malloc( sizeof(char) );
    strcpy(G.vertices[G.vexnum].data,v);
    G.vertices[G.vexnum].firstarc = NULL;
    G.vexnum++;
}

int DeleteVex(ALGraph &G, VertexType v)//刪除頂點
{
    int i,k,j;
    k = LocateVex(G,v);
    if(G.kind < 2)//有向
        j = 1;
    else        //無向
        j = 0;
    if(v<0)
        return ERROR;
    ArcNode *p,*q;
    p = G.vertices[k].firstarc;//p指向頂點v的連結串列
    while(p)                    //刪除頂點v的連結串列
    {
        q = p;
        G.vertices[k].firstarc = p->nextarc;
        p = p->nextarc;
        free(q);
        G.arcnum--;            //邊數減1
    }
    for(i=0; i<G.vexnum; i++)//對鄰接表其餘頂點連結串列操作,刪除有頂點v的指標
    {
        p = G.vertices[i].firstarc;
        if(p)            
        {
            if(p->adjvex == k)    //刪除第一個結點(頂點v是第一個結點)
            {
                G.vertices[i].firstarc = p->nextarc;
                free(p);
                G.arcnum = G.arcnum - j;
            }
            else                //刪除第一個後的結點(頂點v不是第一個結點)
            {    
                q = p;
                p = p->nextarc;
                while(p)
                {
                    if(p->adjvex == k)
                    {
                        q->nextarc = p->nextarc;
                        free(p);
                        G.arcnum = G.arcnum - j;//有向:邊再減1;無向:不用再減1
                        break;
                    }
                    q = p;
                    p = p->nextarc;
                }
            }
        }
    }
    for(i=k; i<G.vexnum-1; i++)//鄰接表第k個位置後都往前移
        G.vertices[i] = G.vertices[i+1];
    G.vexnum--;                    //頂點數減1
    for(i=0; i<G.vexnum; i++)    //由於鄰接表位置的挪動,導致各頂點連結串列中的adjvex域都錯位,應重新調整
    {
        p = G.vertices[i].firstarc;
        while(p)
        {
            if(p->adjvex > k)    //第k個位置後的連結串列都往前移了,因此p->adjvex > k的情況下,都減1
                p->adjvex = p->adjvex -1;
            p = p->nextarc;
        }
    }
}

int InsertArc(ALGraph &G, VertexType v, VertexType w)//插入一條邊或弧
{
    int i,j,weight;
    i = LocateVex(G,v);//尾
    j = LocateVex(G,w);//頭
    if(i<0 || j<0)
        return ERROR;
    G.arcnum++;
    if(G.kind % 2 == 1)//網
    {
        cout<<"輸入權值:";
        cin>>weight;
    }
    else            //圖
        weight = 1;
    if(G.kind < 2)//有向
        CreateSub(G,i,j,&weight);
    else         //無向
    {
        CreateSub(G,i,j,&weight);
        CreateSub(G,j,i,&weight);
    }
    return OK;
}

void DeleteSub(ALGraph &G, int i, int j)//刪除邊或弧的輔助函式
{
    ArcNode *p, *pre;
    p = G.vertices[i].firstarc;
    if(p->adjvex == j)
    {    
        G.vertices[i].firstarc = p->nextarc;
        free(p);
    }
    else
    {
        pre = p;
        p = p->nextarc;
        while(p)
        {
            if(p->adjvex == j)
            {
                pre->nextarc = p->nextarc;
                free(p);
                break;
            }
            pre = p;
            p = p->nextarc;
        }
    }
}

int DeleteArc(ALGraph &G, VertexType v, VertexType w)//刪除一條邊
{
    int i,j,k;
    i = LocateVex(G,v);//尾
    j = LocateVex(G,w);//頭
    if(i<0 || j<0)
        return ERROR;
    if(G.kind < 2)//有向
        DeleteSub(G,i,j);
    else        //無向
    {
        DeleteSub(G,i,j);
        DeleteSub(G,j,i);
    }
    G.arcnum--;
    return OK;
}

void Display(ALGraph G)
{
    int i;
    ArcNode *t;
    cout<<"邊數:"<<G.arcnum<<endl;
    cout<<"頂點數:"<<G.vexnum<<endl;
    for(i=0; i<G.vexnum; i++)
    {
        cout<<i+1<<": "<<G.vertices[i].data;
        t = G.vertices[i].firstarc;
        while(t)
        {
            cout<<G.vertices[t->adjvex].data;
            t = t->nextarc;
        }
        cout<<endl;
    }
}

void Visit(VertexType e)
{
    cout<<e;
}

void DFS(ALGraph G, int i)
{
    visited[i] = TRUE;
    Visit(G.vertices[i].data);
    ArcNode *w;
    for(w=FirstAdjVex(G,G.vertices[i].data); w!=NULL; w=NextAdjVex(G,G.vertices[i].data,G.vertices[w->adjvex].data))
    {
        if(!visited[w->adjvex])
            DFS(G,w->adjvex);
    }
}


void DFSTraverse(ALGraph G, void(*Visit)(VertexType))//深度優先遍歷
{
    int i;
    for(i=0; i<G.vexnum; i++)
        visited[i] = FALSE;
    for(i=0; i<G.vexnum; i++)
    {
        if(!visited[i])
            DFS(G,i);
    }
    cout<<endl;
}

void BFSTraverse(ALGraph G, void(*Visit)(VertexType))//廣度優先搜尋演算法
{
    int i,u;
    ArcNode *w;
    for(i=0; i<G.vexnum; i++)
        visited[i] = FALSE;
    queue<int> Q;
    for(i=0; i<G.vexnum; i++)
    {
        if(!visited[i])
        {
            visited[i] = TRUE;
            Visit(G.vertices[i].data);
            Q.push(i);
            while(!Q.empty())
            {
                u = Q.front();
                Q.pop();
                for(w=FirstAdjVex(G,G.vertices[u].data); w!=NULL; w=NextAdjVex(G,G.vertices[u].data,G.vertices[w->adjvex].data))
                {
                    if(!visited[w->adjvex])
                    {
                        visited[w->adjvex] = TRUE;
                        Visit(G.vertices[w->adjvex].data);
                        Q.push(w->adjvex);
                    }
                }
            }
        }
    }
    cout<<endl;
}

int main(int argc, char* argv[])
{
    ALGraph G;
    CreateGraph(G);
    Display(G);
    DFSTraverse(G,Visit);
    BFSTraverse(G,Visit);
    return 0;
}

相關推薦

資料結構---鄰接

// Graph_Adjacency List.cpp : Defines the entry point for the console application. /*-----CODE FOR FUN--------------- -------CREATED BY D

18_資料結構與演算法_鄰接_Python實現

# Title : TODO # Objective : TODO # Created by: Chen Da # Created on: 2018/11/10 #頂點類 class Vertex(object): def __init__(self,key): s

python-資料結構程式碼 鄰接

  class Vertex: def __init__(self,key): self.id=key self.connectedTo={} def addNeighbor(self,nbr,weight=0): s

資料結構---鄰接建立、列印、深度優先遍歷,廣度優先遍歷C語言

當一個圖為稀疏圖時,使用鄰接矩陣會浪費大量儲存空間。 鄰接表法結合了順序儲存和鏈式儲存方法,減少了不必要的浪費。 鄰接表 1)對圖G的每個頂點vi建立一個單鏈表,第i個單鏈表中的結點表示依附於頂點vi的邊(對於有向圖則是以頂點vi為尾的弧)。這個單鏈表就稱為頂點vi

python-數據結構代碼 鄰接

contain cte elf span list values ice connected self. class Vertex: def __init__(self,key): self.id=key self.connec

資料結構 鄰接儲存結構及DFS/BFS遍歷

//鄰接表 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define INF 999 using namespace std; typedef

資料結構 鄰接表示轉換成鄰接矩陣表示的演算法

圖的鄰接表表示轉換成鄰接矩陣表示的演算法。 下面這個是有向圖鄰接表表示轉換成鄰接矩陣 #include <stdio.h> #include <string.h> #include <stdlib.h> int a[100][100];

資料結構線性

緒論中我們大體介紹了資料結構的概念,接下來我們就從邏輯結構具體介紹幾種結構。 我們知道資料結構分為邏輯結構、儲存結構、資料的運算。既然我們從邏輯結構方面具體介紹各個資料結構,那麼接下來,我們只用掌握它的儲存結構和基本操作運算就好啦。 首先介紹的是線性結構中的線性表。 一、儲存結構

資料結構 鄰接

呃,下面該寫鄰接表了.......最近感覺資料結構比以前難了,難道是我想寫網頁的原因麼,哈哈鄰接表的出現是因為圖若是稀疏圖,用鄰接矩陣會造成空間的浪費,畢竟你要開闢一個一維陣列和一個二維陣列嘛,而且還是大開小用的那種。鄰接表為了避免記憶體的浪費引入了鏈式儲存,它的處理辦法是:

資料結構鄰接 稀疏

<!DOCTYPE html> <html> <head>     <title>鄰接表</title>     <meta charset="utf-8">

資料結構鄰接儲存 c++實現

#include <iostream> #include <string> #include <queue> using namespace std; #define MAXVEX 10 #define INFINITY 0XFFFFF

資料結構鄰接儲存,DFS和BFS遍歷

     來看下面的一個簡單的圖,       那麼這樣的一個圖,我們應該用什麼儲存結構來儲存它呢?常用的是鄰接矩陣和鄰接表,這裡鄰接矩陣不做講解,如下所有程式碼都是以鄰接表作為儲存結構,所以這裡就只講解下鄰接表。那麼什麼是鄰接表呢?如何構造呢?       鄰接表是一

資料結構資料結構C語言的實現【鄰接

圖(鄰接表法) /* * 鄰接表的建立和圖的遍歷的程式碼實現 */ #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define O

資料結構鄰接實現C++

一、圖的鄰接表實現 1.實現了以頂點順序表、邊連結串列為儲存結構的鄰接表; 2.實現了圖的建立(有向/無向/圖/網)、邊的增刪操作、深度優先遞迴/非遞迴遍歷、廣度優先遍歷的演算法; 3.採用頂點物件列表、邊(弧)物件列表的方式,對圖的建立進行初始化;引用 "ObjArr

資料結構——2——的儲存和表示方式.md

圖的儲存方式 在實踐中,圖最常見的策略是: 將每個節點的連線儲存在鄰接列表中。 將整個圖形的連線儲存在鄰接矩陣中。 用鄰接連結串列來表示圖之間的關係 在圖中表示連線的最簡單方法是在每個節點的資料結構中儲存與其連線的節點的列表。該結構稱為鄰接列表。 例如

資料結構——3——深度優先搜尋演算法DFS思想

圖的遍歷 圖由頂點及其邊組成,圖的遍歷主要分為兩種: 遍歷所有頂點 遍歷所有邊 我們只討論第一種情況,即不重複的列出所有的頂點,主要有兩種策略:深度優先搜尋(DFS),廣度優先搜尋(BFS) 為了使深度和廣度優先搜尋的實現演算法的機制更容易理解,假設提

資料結構——1——的簡單介紹

圖的簡介 我們先回顧一下之前介紹的樹的概念,在樹的定義中,每個節點只能有一個父類,並且樹中不能出現有環形。但是你可曾想過,當一棵樹沒有任何規則的時候,會發生什麼嗎? 現在,我們給圖(graph)下一個定義: 圖,是一種用節點和邊來表示相互關係的數學模型。(A graph is a

資料結構——7——最短路徑與Dijkstra's Algorithm

帶權圖 在圖中,給每一條路徑帶上一定的權重,這樣的圖我們稱為帶權圖。如下圖所示: 我們現在來回顧一下BFS跟DFS的基本思想: 深度優先搜尋:繼續沿著路徑搜尋,直到我們需要回溯,但這種方式不保證最短路徑。 廣度優先搜尋:檢視包含距離1的鄰居,然後是距離2的鄰

資料結構——6——深入分析BFS演算法

DFS的不足和BFS演算法 雖然我們知道根據DFS演算法我們可以找到所有的,由起始節點到目標節點的所有路徑,但並不代表那條路是最短的或者是最佳的。就像我們上篇文章所說的一樣,對於同一幅圖,非遞迴演算法找到的路徑就明顯比遞迴演算法找的要短。 回顧我們之前提到的BFS的基本思想:從起始頂

資料結構——5——深入分析DFS演算法

對DFS的過程分析 在前面的文章中我們提到了這樣的一幅圖: 我們知道,在DFS中,我們採用的是遞迴的方式進行實現的,並且給每一個遍歷過的點都做上了標記,目的是為了防止程式進入死迴圈。(為什麼樹可以不需要呢?因為樹沒有環) 利用之前專欄提到的遞迴模式,我們可以寫出下面的虛擬碼: