图的基本操作
#include <iostream>
#include <assert.h>
using namespace std;
//采用邻接链表的方式
#define InfoTypde int
#define VertexType int
const int UNDIGRAPH = 0;
const int DIGRAPH = 1;
const int MAX_VERTEX_NUM = 20;
typedef struct ArchNode
{
int vertexIndex; //该弧指向顶点在图中顶点数组的索引,对应vertexs[20]的下标
ArchNode *nextarc; //指向下一条弧的指针
InfoTypde info; //比如弧的权重
}ArchNode;
typedef struct Vertex
{
VertexType data; //顶点信息
ArchNode *firstarc; //指向第一条弧的指针
}Vertex;
//这样定义图有个坏处,一旦定义好,图中结点的个数就固定了!
typedef struct Graph
{
Vertex *vertexs[MAX_VERTEX_NUM]; //存储顶点的数组,存放的是指向顶点的指针
int vexNum; //当前图中的定点数
int arcNum; //当前图中的弧的个数
int kind; //图的种类,有向图还是无向图
}Graph;
void createGraph(Graph *&G,int kind)
{
if(G) G = NULL;
G = (Graph *)malloc(sizeof(struct Graph));
assert(NULL != G);
for(int i = 0; i < MAX_VERTEX_NUM; ++i)
{
G->vertexs[i] = NULL; //初始化指向顶点的指针为NULL
}
G->kind = kind; //设置图的种类
G->vexNum = 0; //初始化图中顶点的个数
G->arcNum = 0; //初始化图中弧的个数
}
void destoryGraph(Graph *&G)
{
ArchNode *cur,*next;
//遍历顶点
for(int i = 0; i < G->vexNum; ++i)
{
if(!G->vertexs[i])
continue;
next = G->vertexs[i]->firstarc;
cur = G->vertexs[i]->firstarc;
while(cur)
{
next = cur->nextarc;
free(cur);
cur = next;
}
G->vertexs[i]->firstarc = NULL;
}
free(G);
G = NULL;
}
//向图中增加结点
void addVertexToGraph(Graph *&G,VertexType data)
{
if(G->vexNum >= MAX_VERTEX_NUM)
{
cout << "Too many vertex!" << endl;
return ;
}
for(int i = 0; i < G->vexNum; ++i)
{
if(!G->vertexs[i])
continue;
if(G->vertexs[i]->data == data)
{
cout << "Already exists!" << endl;
return; //不允许重复
}
}
Vertex *pVeterx;
pVeterx = (Vertex *)malloc(sizeof(struct Vertex));
pVeterx->data = data;
pVeterx->firstarc = NULL;
G->vertexs[G->vexNum] = pVeterx;
G->vexNum++;
}
//从图中删除一个结点
void delVertexFromGraph(Graph *&G,VertexType data)
{
bool haveThisVertex = false;
ArchNode *cur,*next,*temp,*pre;
Vertex *anotherVertex;
if(NULL == G)
return;
if(G->vexNum <= 0)
{
cout << "Have no vertex!" << endl;
return ;
}
for(int i = 0; i < G->vexNum; ++i)
{
if(!G->vertexs[i])
continue;
if(G->vertexs[i]->data == data)
{
haveThisVertex = true;
//以下循环用来删除顶点所指向的弧链表
next = cur = G->vertexs[i]->firstarc;
if(G->kind == DIGRAPH) //如果是有向图
{
while(cur)
{
next = cur->nextarc;
free(cur);
G->arcNum --; //弧的个数减一
cur = next;
}
G->vertexs[i] = NULL;
}
else if(G->kind == UNDIGRAPH) //如果是无向图,这个麻烦点
{
while(cur)
{
//找到待删除的弧的另一个结点,将它的弧链表中指向被删除结点的弧也删掉
anotherVertex = G->vertexs[cur->vertexIndex]; //找到待删除弧对应的另一个结点
temp = anotherVertex->firstarc,pre = NULL;
while(temp) //这个循环是为了删除另一个结点中保存弧信息
{
if(temp->vertexIndex == i)
{
//如果是首节点
if(NULL == pre) //或者if(NULL == pre)
{
anotherVertex->firstarc = temp->nextarc;
free(temp);
}
else
{
pre->nextarc = temp->nextarc;
free(temp);
}
break; //找到即停止循环
}
pre = temp;
temp = temp->nextarc;
}
next = cur->nextarc;
free(cur);
G->arcNum --; //弧的个数减一
cur = next;
}
G->vertexs[i] = NULL;
}
for(int j = i; j < G->vexNum - 1; ++j)
{
G->vertexs[j] = G->vertexs[j + 1];
}
G->vertexs[j] = NULL; //
G->vexNum-- ; //结点的个数减一
break;
}
}
if(!haveThisVertex)
cout << "没有该结点!" << endl;
}
//从图中查找一个值为指定值的结点的索引
int findVertexIndexInGraph(const Graph *G,VertexType data)
{
if(NULL == G)
return -1;
for(int i = 0; i < G->vexNum; ++i)
{
if(!G->vertexs[i])
continue;
if(G->vertexs[i]->data == data)
{
return i;
break;
}
}
return -1;
}
//向图中增加一条弧
void addArchToGraph(Graph *&G,VertexType startData,VertexType endData,InfoTypde weight = 0)
{
ArchNode *pArchNode,*cur;
//先要找到start和end
if(NULL == G)
return;
int startVertexIndex = findVertexIndexInGraph(G,startData);
int endVertexIndex = findVertexIndexInGraph(G,endData);
cur = G->vertexs[startVertexIndex]->firstarc;
while(cur)
{
if(cur->vertexIndex == endVertexIndex)
{
cout << "Already have this arch!" << endl;
return ;
}
cur = cur->nextarc;
}
if(startVertexIndex >= 0 && endVertexIndex >= 0)
{
if(G->kind == DIGRAPH) //如果是有向图
{
pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //创建一个弧结点
pArchNode->info = weight;
pArchNode->nextarc = NULL;
pArchNode->vertexIndex = endVertexIndex;
cur = G->vertexs[startVertexIndex]->firstarc;
if(NULL == cur)
{
G->vertexs[startVertexIndex]->firstarc = pArchNode;
}
else
{
while(cur->nextarc)
{
cur = cur->nextarc;
}
cur->nextarc = pArchNode;
}
G->arcNum ++; //弧的条数加一
}
else if(G->kind == UNDIGRAPH) //如果是无向图
{
pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //创建一个弧结点
pArchNode->info = weight;
pArchNode->nextarc = NULL;
pArchNode->vertexIndex = endVertexIndex;
cur = G->vertexs[startVertexIndex]->firstarc;
if(NULL == cur)
{
G->vertexs[startVertexIndex]->firstarc = pArchNode;
}
else
{
while(cur->nextarc)
{
cur = cur->nextarc;
}
cur->nextarc = pArchNode;
}
pArchNode = (ArchNode *)malloc(sizeof(struct ArchNode)); //再创建一个弧结点
pArchNode->info = weight;
pArchNode->nextarc = NULL;
pArchNode->vertexIndex = startVertexIndex;
cur = G->vertexs[endVertexIndex]->firstarc;
if(NULL == cur)
{
G->vertexs[endVertexIndex]->firstarc = pArchNode;
}
else
{
while(cur->nextarc)
{
cur = cur->nextarc;
}
cur->nextarc = pArchNode;
}
G->arcNum ++; //弧的条数加一
}
}
else
{
cout << "起点或终点不存在!" << endl;
return ;
}
}
//从图中删除一条弧
void delArchFromGraph(Graph *&G,VertexType startData,VertexType endData)
{
ArchNode *cur,*pre;
//先要找到start和end
if(NULL == G)
return;
int startVertexIndex = findVertexIndexInGraph(G,startData);
int endVertexIndex = findVertexIndexInGraph(G,endData);
if(startVertexIndex >= 0 && endVertexIndex >= 0)
{
if(G->kind == DIGRAPH)
{
cur = G->vertexs[startVertexIndex]->firstarc,pre = NULL;
while(cur)
{
if(cur->vertexIndex == endVertexIndex)
{
break;
}
pre = cur;
cur = cur->nextarc;
}
if(NULL == cur)
{
cout << "这两个结点之间没有弧!" << endl;
return ;
}
else
{
if(NULL == pre) //是首节点
G->vertexs[startVertexIndex]->firstarc = cur->nextarc;
else
pre->nextarc = cur->nextarc;
free(cur);
G->arcNum --;
}
}
else if(G->kind == UNDIGRAPH)
{
cur = G->vertexs[startVertexIndex]->firstarc,pre = NULL;
while(cur)
{
if(cur->vertexIndex == endVertexIndex)
{
break;
}
pre = cur;
cur = cur->nextarc;
}
if(NULL == cur)
{
cout << "这两个结点之间没有弧!" << endl;
return ;
}
else
{
if(NULL == pre) //是首节点
G->vertexs[startVertexIndex]->firstarc = cur->nextarc;
else
pre->nextarc = cur->nextarc;
free(cur);
//G->arcNum --;
}
cur = G->vertexs[endVertexIndex]->firstarc,pre = NULL;
while(cur)
{
if(cur->vertexIndex == startVertexIndex)
{
break;
}
pre = cur;
cur = cur->nextarc;
}
if(NULL == cur)
{
cout << "这两个结点之间没有弧!" << endl;
return ;
}
else
{
if(NULL == pre) //是首节点
G->vertexs[endVertexIndex]->firstarc = cur->nextarc;
else
pre->nextarc = cur->nextarc;
free(cur);
G->arcNum --;
}
}
}
else
{
cout << "起点或终点不存在!" << endl;
return ;
}
}
//深度优先遍历
void DFSdetails(const Graph *G,int i,int satusArr[])
{
ArchNode *cur;
if(satusArr[i] == 1 )
return;
cout << G->vertexs[i]->data << " ";
satusArr[i] = 1;
cur = G->vertexs[i]->firstarc;
while(cur)
{
DFSdetails(G,cur->vertexIndex,satusArr);
cur = cur->nextarc;
}
}
void DFS(const Graph *G)
{
int satusArr[MAX_VERTEX_NUM] = {0};
cout << "深度优先遍历:";
if(NULL == G)
return;
for(int i = 0; i < G->vexNum; ++i)
{
DFSdetails(G,i,satusArr);
}
cout << endl;
}
//广度优先遍历
/*
BFSdetails(const Graph *G,int i,int satusArr[])
{
ArchNode *cur;
int index[MAX_VERTEX_NUM];
if(satusArr[i] == 1)
return;
cout << G->vertexs[i]->data << " ";
satusArr[i] = 1;
cur = G->vertexs[i]->firstarc;
while(cur)
{
//将下标入队
}
while(队不空)
{
BFSdetails
}
}
void BFS(const Graph *G)
{
int satusArr[MAX_VERTEX_NUM] = {0};
if(NULL == G)
return;
cout << "广度优先遍历:";
for(int i = 0; i < G->vexNum; ++i)
{
BFSdetails(G,i,satusArr);
}
cout << endl;
}
*/
void prim(Graph *G,int arr[MAX_VERTEX_NUM][MAX_VERTEX_NUM],int vertexNums)
{
int U[MAX_VERTEX_NUM] = {-1};//代表集合为空
int V[MAX_VERTEX_NUM] = {0};
if(vertexNums > MAX_VERTEX_NUM || NULL == arr)
return;
if(G)
free(G);
}