adjacency list

adjacency list

basic concept

When the graph is sparse and represented by an adjacency matrix, the utilization rate of the adjacency matrix is ​​too low, resulting in a certain waste of resources. The adjacency list is a chain storage structure proposed to save the storage space of the graph. In this chain structure, a singly linked list is established for each vertex Vertex in the graph. In this singly linked list, each node consists of three chain domains: adjvex adjacency point, nextarc pointing to the next edge, and information info corresponding to the edge. As shown below:


In addition, in order to represent all the vertices in the graph, a structure array AdjList[num] is used in the adjacency list structure. The array element is a structure with two chain fields (the vertex information and the corresponding first arc for that vertex). It is as follows:


As shown in the following undirected graph, there are 4 vertices V={v1, v2, v3, v4}, 4 edges E={(v1, v2), (v1, v3), (v3, v4), (v4, v1)}.


When the above graph is represented by an adjacency list, as shown in the following figure:

As can be seen from the above figure, the singly linked list 1 represents 3 arcs connected to the first vertex v1, and the first link field in each node in the linked list represents the other vertices adjacent to the node at the vertex position in the array. Connected to the first vertex v1 are vertex 2, vertex 3 and vertex 4, so the first link domains of the three nodes in the linked list are 3, 2 and 1 respectively. Others follow and so on. Also, note that adjacency lists represent some of the differences between directed and undirected graphs.

Basic operation

1. Adjacency list of construction graph
Status createGraph(ALGraph &G, string kind, int vertexNum, int arcNum){
	//Construct a graph using an adjacency list (directed or undirected)
	G.kind = kind;

	G.vertexNum = vertexNum;
	G.arcNum = arcNum;
	
	//Initialize vertex information
	for(int i = 0; i<G.vertexNum; i++){
		cin>>G.vertices[i].data;
		G.vertices[i].firstArc = NULL;
	}

	cout<<"Try to input arcs info"<<endl;
	for(int j = 0; j<G.arcNum; j++){
		cout<<"please input two nodes of "<<j+1<<"-th arc"<<endl;

		VertexNode node1, node2;
		cin>>node1.data>>node2.data;
		insertArc(G, node1, node2);//Insert arc
	}
	return 1;
}
2. Print the adjacency graph
Status printALGraph(ALGraph &G){
	for(int i = 0; i<G.vertexNum; i++){
		cout<<i<<" "<<G.vertices[i].data;
		ArcNode *arc = G.vertices[i].firstArc;

		while(arc){
			cout<<"-->"<<arc->adjvex;
			arc = arc->nextArc;
		}
		cout<<"-->NULL"<<endl;
	}
	return 1;
}
3. Insert an arc between two vertices
Status insertArc(ALGraph &G, VertexNode node1, VertexNode node2){
	int nodeNum1 = locateNode(G, node1);//i and j represent the position in AdjList[MAX_VERTEX_NUM]
	int nodeNum2 = locateNode(G, node2);
	if(nodeNum1<0 || nodeNum2<0) exit(-1);
	
	if(G.kind == "DG")//Directed graph, insert once
		insertArcAction(G, nodeNum1, nodeNum2);
	else{//The undirected graph is inserted twice
		insertArcAction(G, nodeNum1, nodeNum2);
		insertArcAction(G, nodeNum2, nodeNum1);
	}
	return 1;
}

void insertArcAction(ALGraph &G, int nodeNum1, int nodeNum2){
	ArcNode * p;
	ArcNode *arc;

	arc = new ArcNode[1];
	arc->adjvex = nodeNum2;

	p = G.vertices[nodeNum1].firstArc;//Equivalent to the insertion of a linked list
	if(!p){
		G.vertices[nodeNum1].firstArc = arc;
		arc->nextArc = NULL;
	}
	else{
		G.vertices[nodeNum1].firstArc = arc;
		arc->nextArc = p;
	}
}
4. Delete arc
Status deleteArc(ALGraph &G, VertexNode node1, VertexNode node2){
	//node1 is the arc tail, node2 is the arc head: node1 ----> node2
	
	int index1 = locateNode(G, node1);
	int index2 = locateNode(G, node2);
	if(index1 < 0 || index2 < 0) exit(-1);

	if(G.kind == "DG"){
		//Delete arc from directed graph, delete once
		deleteArcAction(G, index1, index2);
	}
	else{
		//Undirected graph delete arc, delete twice
		deleteArcAction(G, index1, index2);
		deleteArcAction(G, index2, index1);
	}
	return 1;
}

void deleteArcAction(ALGraph &G, int index1, int index2){
	ArcNode *cur = G.vertices[index1].firstArc;
	ArcNode *pre = cur;
	int count = 0;
	if(!cur)
		return;
	else{
		while(cur){
			count++;

			if(cur->adjvex == index2)
				break;
			pre = cur;
			cur = cur->nextArc;
		}
	}
	if(!cur)
		return;//The node has no corresponding arc
	else if(count <=1)
		G.vertices[index1].firstArc = pre->nextArc;
	else
		pre->nextArc = cur->nextArc;
}
5. Delete vertices
Status deleteVertex(ALGraph &G, VertexNode node){
	int index = locateNode(G, node);
	
	for(int i = 0; i<G.vertexNum; i++){
		if(i == index)
			continue;
		else{
			VertexNode node1 = G.vertices[i];
			deleteArc(G, node1, node);//Delete the arc corresponding to this node as the arc head
		}
	}
	G.vertices[index].firstArc = NULL;//Delete all arcs from this node
	G.vertices[index].data = INT_FIN;//Use a large number to indicate that the node is deleted
	return 1;
}
6. Position the vertex
int locateNode(ALGraph &G, VertexNode node){
	for(int i=0; i<G.vertexNum;i++){
		if(node.data == G.vertices[i].data)
			return i;
	}
	return -1;
}
7. All codes
#include "stdafx.h"  
#include <iostream>  
#include <string>  
  
#define MAX_VERTEX_NUM 20  
#define INT_FIN 500  
  
using namespace std;  
  
typedef int infoType;//Arc info  
typedef char vertexType;//Vertex save character information  
typedef int Status;  
  
typedef struct ArcNode{  
    int adjvex;  
    struct ArcNode *nextArc;  
    infoType *info;  
}ArcNode;  
  
typedef struct VertexNode{  
    vertexType data;  
    ArcNode *firstArc;  
}VertexNode, AdjList[MAX_VERTEX_NUM];  
  
typedef struct ALGraph{  
    AdjList vertices;  
    int vertexNum, arcNum;  
    string kind;  
}ALGraph;  
  
int locateNode(ALGraph &G, VertexNode node){  
    for(int i=0; i<G.vertexNum;i++){  
        if(node.data == G.vertices[i].data)  
            return i;  
    }  
    return -1;  
}  
  
void insertArcAction(ALGraph &G, int nodeNum1, int nodeNum2);  
Status insertArc(ALGraph &G, VertexNode node1, VertexNode node2);  
  
Status createGraph(ALGraph &G, string kind, int vertexNum, int arcNum){  
    //Construct a graph using an adjacency list (directed or undirected)  
    G.kind = kind;  
  
    G.vertexNum = vertexNum;  
    G.arcNum = arcNum;  
      
    //Initialize vertex information  
    for(int i = 0; i<G.vertexNum; i++){  
        cin>>G.vertices[i].data;  
        G.vertices[i].firstArc = NULL;  
    }  
  
    cout<<"Try to input arcs info"<<endl;  
    for(int j = 0; j<G.arcNum; j++){  
        cout<<"please input two nodes of "<<j+1<<"-th arc"<<endl;  
  
        VertexNode node1, node2;  
        cin>>node1.data>>node2.data;  
        insertArc(G, node1, node2);  
    }  
    return 1;  
}  
  
Status insertVertex(ALGraph &G, VertexNode node){  
    G.vertexNum = G.vertexNum + 1;  
    G.vertices[G.vertexNum - 1].data = node.data;  
    G.vertices[G.vertexNum - 1].firstArc = NULL;  
    return 1;  
}  
  
void insertArcAction(ALGraph &G, int nodeNum1, int nodeNum2){  
    ArcNode * p;  
    ArcNode *arc;  
  
    arc = new ArcNode[1];  
    arc->adjvex = nodeNum2;  
  
    p = G.vertices[nodeNum1].firstArc;//Equivalent to the insertion of a linked list  
    if(!p){  
        G.vertices[nodeNum1].firstArc = arc;  
        arc->nextArc = NULL;  
    }  
    else{  
        G.vertices[nodeNum1].firstArc = arc;  
        arc->nextArc = p;  
    }  
}  
  
Status insertArc(ALGraph &G, VertexNode node1, VertexNode node2){  
    int nodeNum1 = locateNode(G, node1);//i and j represent the position in AdjList[MAX_VERTEX_NUM]  
    int nodeNum2 = locateNode(G, node2);  
    if(nodeNum1<0 || nodeNum2<0) exit(-1);  
      
    if(G.kind == "DG")  
        insertArcAction(G, nodeNum1, nodeNum2);  
    else{  
        insertArcAction(G, nodeNum1, nodeNum2);  
        insertArcAction(G, nodeNum2, nodeNum1);  
    }  
    return 1;  
}  
  
Status printALGraph(ALGraph &G){  
    for(int i = 0; i<G.vertexNum; i++){  
        cout<<i<<" "<<G.vertices[i].data;  
        ArcNode *arc = G.vertices[i].firstArc;  
  
        while(arc){  
            cout<<"-->"<<arc->adjvex;  
            arc = arc->nextArc;  
        }  
        cout<<"-->NULL"<<endl;  
    }  
    return 1;  
}  
  
void deleteArcAction(ALGraph &G, int index1, int index2);  
Status deleteArc(ALGraph &G, VertexNode node1, VertexNode node2);  
  
Status deleteVertex(ALGraph &G, VertexNode node){  
    int index = locateNode(G, node);  
      
    for(int i = 0; i<G.vertexNum; i++){  
        if(i == index)  
            continue;  
        else{  
            VertexNode node1 = G.vertices[i];  
            deleteArc(G, node1, node);//Delete the arc corresponding to this node as the arc head  
        }  
    }  
    G.vertices[index].firstArc = NULL;//Delete all arcs from this node  
    G.vertices[index].data = INT_FIN;//Use a large number to indicate that the node is deleted  
    return 1;  
}  
  
void deleteArcAction(ALGraph &G, int index1, int index2){  
    ArcNode *cur = G.vertices[index1].firstArc;  
    ArcNode *pre = cur;  
    int count = 0;  
    if(!cur)  
        return;  
    else{  
        while(cur){  
            count++;  
  
            if(cur->adjvex == index2)  
                break;  
            pre = cur;  
            cur = cur->nextArc;  
        }  
    }  
    if(!cur)  
        return;//The node has no corresponding arc  
    else if(count <=1)  
        G.vertices[index1].firstArc = pre->nextArc;  
    else  
        pre->nextArc = cur->nextArc;  
}  
  
Status deleteArc(ALGraph &G, VertexNode node1, VertexNode node2){  
    //node1 is the arc tail, node2 is the arc head: node1 ----> node2  
      
    int index1 = locateNode(G, node1);  
    int index2 = locateNode(G, node2);  
    if(index1 < 0 || index2 < 0) exit(-1);  
  
    if(G.kind == "DG"){  
        //Delete arc from directed graph, delete once  
        deleteArcAction(G, index1, index2);  
    }  
    else{  
        //Undirected graph delete arc, delete twice  
        deleteArcAction(G, index1, index2);  
        deleteArcAction(G, index2, index1);  
    }  
    return 1;  
}  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
    ALGraph G;  
    string kind = "UDG";  
    int vertexNum = 4;  
    int arcNum = 4;  
  
    cout<<"Try to create a Adjacency list Graph ..."<<endl;  
    createGraph(G, kind, vertexNum, arcNum);  
      
    cout<<"Try to print a Adjacence list Graph ..."<<endl;  
    printALGraph(G);  
  
    cout<<"Try to insert two nodes into  a Adjacence list Graph ..."<<endl;  
    VertexNode node1;  
    node1.data = 'E';  
    insertVertex(G, node1);  
      
    VertexNode node2;  
    node2.data = 'F';  
    insertVertex(G, node2);  
    printALGraph(G);  
  
    cout<<"Try to insert a arc into a Adjacence list Graph ..."<<endl;  
    insertArc(G, node1, node2);  
    printALGraph(G);  
  
    cout<<"Try to delete a arc of a Adjacence list Graph ..."<<endl;  
    VertexNode node3;  
    node3.data = 'A';  
    VertexNode node4;  
    node4.data = 'D';  
    deleteArc(G, node3, node4);  
    printALGraph(G);  
  
    cout<<"Try to delete a node of a Adjacence list Graph ..."<<endl;  
    deleteVertex(G,node3);  
    printALGraph(G);  
  
    system("pause");  
    return 0;  
}
8. Test results


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325834457&siteId=291194637