邻接多重表的实现。这次研讨确实有难度,除了实现这个还要完成最小生成树。
直接上代码吧。
#ifndef ARC_H
#define ARC_H
#ifndef NULL
#define NULL 0
#endif
struct Arc
{
bool tag;
int weight;
int adjVex1, adjVex2;
Arc* nextArc1;
Arc* nextArc2;
Arc(int w, int ad1, int ad2, Arc* next1 = NULL, Arc* next2 = NULL);//3~5参构造器
};
Arc::Arc(int w, int ad1, int ad2, Arc* next1, Arc* next2)
{
tag = 0;
weight = w;
adjVex1 = ad1;
adjVex2 = ad2;
nextArc1 = next1;
nextArc2 = next2;
}
#endif
#ifndef VEX_H
#define VEX_H
#include "Arc.h"
struct Vex
{
char data;
Arc* firstArc;
Vex();
Vex(char myData, Arc* myFirstArc);
};
Vex::Vex()//无参的构造器
{
data = '?';
firstArc = NULL;
}
Vex::Vex(char myData, Arc* myFirstArc) //给1~2个参数的构造器
{
data = myData;
firstArc = myFirstArc;
}
#endif
#ifndef NETWORK_H
#define NETWORK_H
#include "Vex.h"
#include
using namespace std;
struct NetWork
{
Vex* arrayVex;
int size;
NetWork(int mySize, char myVex[], int **myArc);//构造函数
void DeleteEdge(int a, int b);//删除a<->b这条边
void InsertEdge(int a, int b,int numK);//插入a<->b这条边
void ChangeEdge(int a, int b, int numK);//修改a<->b这条边的权值
void Show();//显示
};
//3参数构造器
NetWork::NetWork(int mySize, char myVex[], int **myArc)
{
arrayVex = new Vex[size = mySize]; //分配顶点数组的空间
for (int i = 0; i < size; i++)
{
arrayVex[i].data = myVex[i]; //顶点的字符
}
Arc *q;//辅助指针,q用于记录new对象的地址
int numK;//辅助数字,简化计算
//该循环建立全部边节点
for (int i = 0; i < size; i++)
{
for (int j = i+1; j < size; j++)
{
numK = *((int *)myArc + size*i + j); //即numK=myArc[i][j]
if (numK>0) //如果存在这条边
{
q = new Arc(numK, i, j);//建立这个边
q->nextArc1 = arrayVex[i].firstArc;//i的first边一定具有i,可以作为新边的next1
q->nextArc2 = arrayVex[j].firstArc;//j的first边一定具有j,可以作为新边的next2
arrayVex[i].firstArc = q;//头插这条边
arrayVex[j].firstArc = q;//头插这条边
}
//如果不存在这条边,什么都不做
}
}
}
//删除边a<->b
void NetWork::DeleteEdge(int a, int b)
{
if (a == b || a < 0 || b < 0 || a >= size || b >= size)
{
cout << "输入不合法!" << endl;
return;
}
//find记录是否找到a->b,如果找不到的话就不需要找b->a了
//next记录q(或r)是p的next1还是next2
bool find = 0,next=0;
int c;
Arc* p,*q,*r;
if (a > b)//交换使得ab(从a开始找a<->b),改指针而暂时不删边节点
q = arrayVex[a].firstArc;
if (q == NULL)
{
cout << "要删除的边不存在" << endl;
return;
}
if (q->adjVex1 == a && q->adjVex2 == b)//如果第一个边节点就是
{
arrayVex[a].firstArc = q->nextArc1;
find = 1;
}
else//如果不是第一个边节点的话
{
//先初始化,p在q前
p = arrayVex[a].firstArc;
if (p->adjVex1 == a)
{
q = p->nextArc1;
next = 0;//表示q是p的next1
}
else
{
q = p->nextArc2;
next = 1;//表示q是p的next2
}
//然后进行循环
while (q != NULL)
{
if (q->adjVex1 == a && q->adjVex2 != b)//即如果是a->非b
{
q = q->nextArc1;//q向下走
//p紧随其后,但是p向下还是向右才能找到q要看next的记录了
if (next == 0)
p = p->nextArc1;
else
p = p->nextArc2;
next = 0;//下一次,p要向下走才能找到q
}
else if (q->adjVex2 == a)//即如果是非b->a(因为b比a大所以adjVex2==a时adjVex1一定不是b)
{
q = q->nextArc2;//q向右走
//p紧随其后,但是p向下还是向右才能找到q要看next的记录了
if (next == 0)
p = p->nextArc1;
else
p = p->nextArc2;
next = 1;//下一次,p要向右走才能找到q
}
else//能运行到这时一定找到了a->b
{
if (next == 0)//p要向下走才能找到q
p->nextArc1 = q->nextArc1;
else//p要向右走才能找到q
p->nextArc2 = q->nextArc1;
find = 1;//找到了a->b
break;//做完,跳出循环
}
}
}
if (find == 0)//如果从a找不到a<->b,那说明这条边并不存在
{
cout << "要删除的边不存在" << endl;
return;
}
//再考虑b->a(从b开始找a<->b),改指针并且删边节点q==r
if (arrayVex[b].firstArc->adjVex1 == a && arrayVex[b].firstArc->adjVex1 == b)//如果第一个边节点就是
{
arrayVex[b].firstArc = arrayVex[b].firstArc->nextArc2;
}
else//如果不是第一个边节点的话
{
p = arrayVex[b].firstArc;
if (p->adjVex1 == b)
{
r = p->nextArc1;
next = 0;
}
else
{
r = p->nextArc2;
next = 1;
}
while (r != NULL)
{
if (r->adjVex1 == b)//即如果是b->?(?显然不是a)
{
r = r->nextArc1;//r向下走
if (next == 0)
p = p->nextArc1;
else
p = p->nextArc2;
next = 0;//下次p要向下走才能找到r
}
else if (r->adjVex1 != a && r->adjVex2==b)//即如果是非a->b
{
r = r->nextArc2;//r向右走
if (next == 0)
p = p->nextArc1;
else
p = p->nextArc2;
next = 1;//下次p要向右走才能找到r
}
else//r找到了那条边,即r==q
{
if (next == 0)//p要向下走才能找到r
p->nextArc1 = r->nextArc2;
else//p要向右走才能找到r
p->nextArc2 = r->nextArc2;
delete q;//也就是delete r
break;//做完,跳出循环
}
}
}
}
//插入边a<->b
void NetWork::InsertEdge(int a, int b,int numK)
{
if (a == b || a < 0 || b < 0 || a >= size || b >= size)
{
cout << "输入不合法!" << endl;
return;
}
int c;
Arc *p,*q;
if (a > b)//交换使得ab,只要检查从a是否能找到a<->b
p = arrayVex[a].firstArc;
while (p != NULL)
{
if (p->adjVex1 == a && p->adjVex2 != b)//即a<->非b
p = p->nextArc1;//向下走
else if (p->adjVex2 == a)//即非b<->a
p = p->nextArc2;//向右走
else//找到了a<->b
break;
}
if (p != NULL)//如果找到了
{
cout << "要插入的边已经存在" << endl;
return;
}
else//如果没找到,做插入
{
q = new Arc(numK, a, b);//建立这个边
q->nextArc1 = arrayVex[a].firstArc;//i的first边一定具有i,可以作为新边的next1
q->nextArc2 = arrayVex[b].firstArc;//j的first边一定具有j,可以作为新边的next2
arrayVex[a].firstArc = q;//头插这条边
arrayVex[b].firstArc = q;//头插这条边
}
}
//修改a<->b这条边的权值
void NetWork::ChangeEdge(int a, int b, int numK)
{
if (a == b || a < 0 || b < 0 || a >= size || b >= size)
{
cout << "输入不合法!" << endl;
return;
}
int c;
Arc *p;
if (a > b)//交换使得ab,只要检查从a是否能找到a<->b
p = arrayVex[a].firstArc;
while (p != NULL)
{
if (p->adjVex1 == a && p->adjVex2 != b)//即a<->非b
p = p->nextArc1;//向下走
else if (p->adjVex2 == a)//即非b<->a
p = p->nextArc2;//向右走
else//找到了a<->b
break;
}
if (p != NULL)//如果找到了
{
p->weight = numK;
}
else//如果没找到
{
cout << "要修改的边不存在" << endl;
}
}
//显示
void NetWork::Show()
{
Arc* p;
cout << "无向图有" << size << "个点,分别为:";
for (int i = 0; i < size; i++)
cout << arrayVex[i].data << " ";
cout << endl;
for (int i = 0; i < size; i++)
{
cout<<"和" << arrayVex[i].data << "有关的边:";
p = arrayVex[i].firstArc;
while (p != NULL)
{
cout << arrayVex[p->adjVex1].data << "<--"<weight<<"-->" << arrayVex[p->adjVex2].data << ",";
if (p->adjVex1 == i)//判断向下还是向右走
p = p->nextArc1;
else
p = p->nextArc2;
}
cout << endl;
}
}
#endif
// lzh2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "NetWork.h"
int _tmain(int argc, _TCHAR* argv[])
{
char a[5] = { 'A', 'B', 'C', 'D', 'E' };
int b[5][5] = {
{ 0, 1, 3, 0, 0 },
{ 1, 0, 0, 0, 1 },
{ 3, 0, 0, 2, 0 },
{ 0, 0, 2, 0, 9 },
{ 0, 1, 0, 9, 0 } };
NetWork *k = new NetWork(5, a, (int**)b);
k->Show();
cout<4即C<->E" << endl;
k->DeleteEdge(2, 4);
k->Show();
cout <2即A<->C" << endl;
k->DeleteEdge(2, 0);
k->Show();
cout << endl << "尝试插入2<->4即C<->E" << endl;
k->InsertEdge(2, 4, 30);
k->Show();
cout <1即A<->A" << endl;
k->DeleteEdge(1, 1);
k->Show();
cout <3即C<->D" << endl;
k->DeleteEdge(3, 2);
k->Show();
cout << endl << "尝试插入2<->4即C<->E" << endl;
k->InsertEdge(4, 2, 10);
k->Show();
cout << endl << "尝试修改3<->4即D<->E" << endl;
k->ChangeEdge(3, 4, 20);
k->Show();
system("pause");
return 0;
}
运行结果:
最小生成树我还没写,明天想去动物园也不知道能不能去了。