【数据结构笔记】6:无向图的邻接多重表存储结构

来源:互联网 发布:域名赎回期 编辑:程序博客网 时间:2024/06/06 04:11

邻接多重表的实现。这次研讨确实有难度,除了实现这个还要完成最小生成树。

直接上代码吧。

*边节点Arc.h

#ifndef ARC_H#define ARC_H#ifndef NULL#define NULL 0#endifstruct 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

*顶点节点Vex.h

#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

*邻接多重表NetWork.h

#ifndef NETWORK_H#define NETWORK_H#include "Vex.h"#include <iostream>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,可以作为新边的next1q->nextArc2 = arrayVex[j].firstArc;//j的first边一定具有j,可以作为新边的next2arrayVex[i].firstArc = q;//头插这条边arrayVex[j].firstArc = q;//头插这条边}//如果不存在这条边,什么都不做}}}//删除边a<->bvoid 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还是next2bool find = 0,next=0;int c;Arc* p,*q,*r;if (a > b)//交换使得a<b{c = b;b = a;a = c;}//先考虑a->b(从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;elsep = 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;elsep = p->nextArc2;next = 1;//下一次,p要向右走才能找到q}else//能运行到这时一定找到了a->b{if (next == 0)//p要向下走才能找到qp->nextArc1 = q->nextArc1;else//p要向右走才能找到qp->nextArc2 = q->nextArc1;find = 1;//找到了a->bbreak;//做完,跳出循环}}}if (find == 0)//如果从a找不到a<->b,那说明这条边并不存在{cout << "要删除的边不存在" << endl;return;}//再考虑b->a(从b开始找a<->b),改指针并且删边节点q==rif (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;elsep = 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;elsep = p->nextArc2;next = 1;//下次p要向右走才能找到r}else//r找到了那条边,即r==q{if (next == 0)//p要向下走才能找到rp->nextArc1 = r->nextArc2;else//p要向右走才能找到rp->nextArc2 = r->nextArc2;delete q;//也就是delete rbreak;//做完,跳出循环}}}}//插入边a<->bvoid 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)//交换使得a<b{c = b;b = a;a = c;}//先检查是否存在a<->b,只要检查从a是否能找到a<->bp = arrayVex[a].firstArc;while (p != NULL){if (p->adjVex1 == a && p->adjVex2 != b)//即a<->非bp = p->nextArc1;//向下走else if (p->adjVex2 == a)//即非b<->ap = p->nextArc2;//向右走else//找到了a<->bbreak;}if (p != NULL)//如果找到了{cout << "要插入的边已经存在" << endl;return;}else//如果没找到,做插入{q = new Arc(numK, a, b);//建立这个边q->nextArc1 = arrayVex[a].firstArc;//i的first边一定具有i,可以作为新边的next1q->nextArc2 = arrayVex[b].firstArc;//j的first边一定具有j,可以作为新边的next2arrayVex[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)//交换使得a<b{c = b;b = a;a = c;}//先检查是否存在a<->b,只要检查从a是否能找到a<->bp = arrayVex[a].firstArc;while (p != NULL){if (p->adjVex1 == a && p->adjVex2 != b)//即a<->非bp = p->nextArc1;//向下走else if (p->adjVex2 == a)//即非b<->ap = p->nextArc2;//向右走else//找到了a<->bbreak;}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 << "<--"<<p->weight<<"-->" << arrayVex[p->adjVex2].data << ",";if (p->adjVex1 == i)//判断向下还是向右走p = p->nextArc1;elsep = p->nextArc2;}cout << endl;}}#endif

*主程序lzh2.cpp

// 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<<endl << "尝试删除2<->4即C<->E" << endl;k->DeleteEdge(2, 4);k->Show();cout <<endl<< "尝试删除0<->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 <<endl<< "尝试删除1<->1即A<->A" << endl;k->DeleteEdge(1, 1);k->Show();cout <<endl<< "尝试删除2<->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;}

运行结果:




最小生成树我还没写,明天想去动物园也不知道能不能去了。




0 0
原创粉丝点击