C++实现有向权图的基本操作,界面友好,操作方便,运行流畅

Ⅰ.功能: 

          1.创建图
          2.展示全图
          3.添加顶点
          4.添加边
          5.删除顶点
          6.删除边
          7.查看指定边权值
          8.修改指定边权值
          9.输出两点间的所有简单路及路径对应权值
          10.销毁图
           ps:关于9,如果不存在任何简单路,输出“不存在任何简单路”。简单路:不含重复顶点的路。如
               1 2 3 4 5是简单路,1 2 3 1 4  5不是简单路。可以想见,对于大多数问题,非简单路是没有
              研究意义的。如从北京到上海的路线,多次经过同一地点的路线是没有研究价值的。
 Ⅱ.不足:
            1.代码冗长,复用率低。原因是有些操作基本相同但又有细微不同(如goto mark6;goto
               mark7;),难以封装成一个函数。在此请求大神给出好的解决办法。
            2.类的成员函数的实现也写在了头文件中,使头文件过长。原因是前几次代码使用了模板,(看
              过在下前几篇博文的读者应该知道)而用模板的话,就要求要么将类的成员函数的实现和类放
              在一起,要么放在main函数中(尽管听有人说《C++Primer》中说不这样也行,但在下实测的 

              结果是——必须这样)。在下写习惯了,写完后才发现对于此次代码,将类的成员函数的实现
              另放一个文件好。但代码已经写完,就暂时不改了,万一再改出bug来,没准又得调半天,这里
              和大家说一声,求原谅。
            3.使用了goto语句(前几次也一样),有人对goto严格禁止,但依在下愚见,小范围内使用还是
               可以的,再说,在下也是迫不得已,实在没有更好的办法了。还是那句话,求大神指教。
            4.时空复杂性较高,特别是时间复杂性,懂这方面的读者一看在下的代码便知。主要是顶点和边
              都是用链表实现的,动不动就要遍历,但话说回来,至今在下还没找到比用链表实现更好的方
              法,还请高人指教。
 Ⅲ.优点:
             1.程序在多处用了控制,保证了程序的健壮性和友好,可重复操作,体验良好。
             2.仅提供Operate()函数一个接口,较大限度地实现了封装。
 Ⅳ.博主推荐
            1.找两点间所有简单路并输出路径总权值有一定思维量和技巧性,有兴趣的读者可自行分析相
              关代码,体会其思想。此代码为本人原创(当然不排除读者在其它地方见到相似代码,尽管在
              下未参考任何书籍或网络资源)。
 Ⅴ.代码:
//.h文件
#ifndef GRAPH_H
 #define GRAPH_H
 #include<iostream>
 #include<iomanip>
 using namespace std;

 struct Edge       //边结构体
{
     int egnum;    //结点编号
    int weight;   //权值
    Edge* enext;  //下一边结点
    Edge(int enm, int wgt, Edge* enxt);
 };
 Edge::Edge(int enm, int wgt, Edge* enxt)   //边结构体构造函数
{
     egnum = enm;
     weight = wgt;
     enext = enxt;
 }

 struct Vertices      //顶点结构体
{
     int number;      //结点编号
    Edge* state;       //顶点状态,用于标记顶点是否被遍历
    Edge* eghead;    //边链表头结点
    Vertices* vnext; //下一顶点结点
    Vertices(int num,Edge* sta, Edge* eghed, Vertices* vnxt);
 };
 Vertices::Vertices(int num,Edge* sta,Edge* eghed, struct Vertices* vnxt)   //顶点结构体构造函数
{
     number = num;
     state = sta;
     eghead = eghed;
     vnext = vnxt;
 }

 class Graph               //图类
{
private:
     int  vsize;           //记录顶点个数
    int  esize;           //记录边个数
    Vertices* vhead;      //顶点链表头指针
    Vertices* vtail;      //顶点链表尾指针
public:
     Graph();
     ~Graph();
     void Operate();       //封装操作
private:
     Vertices* Revads(const int num); //返回某顶点地址,同时用于检测某顶点是否存在
    int Creat();   //创建图
    Edge* IfEdge(const int vfrom, const int vto);  //查看两顶点间是否存在边
    bool Addvt();  //添加顶点
    int Addeg();  //添加边
    void ShowAll(); //展示全图
    int Getweit(const int vfrom, const int vto);   //查看指定边权值
    bool FinRoad(const int vfrom, const int vto);    //查找两点间所有简单路
    void Destory();  //销毁图
};
Graph::Graph()            //图类构造函数
{
     vsize = 0;
     esize = 0;
     vhead = NULL;
     vtail = NULL;
 }

 Graph::~Graph()           //图类析构函数
{
     Destory();
 }
 Vertices* Graph::Revads(const int num)                //返回某顶点地址,同时用于检测某顶点是否存在
{
     Vertices* pt = vhead;   bool flag = false;
     while (pt)
     {
         if (pt->number == num){ flag = true; break; }
         pt = pt->vnext;
     }
     if (flag)return pt;
     else return NULL;
 }

 Edge* Graph::IfEdge(const int vfrom, const int vto)         //查看两顶点间是否存在边
{
     Vertices* pt = Revads(vfrom);
     Edge* pte = pt->eghead;
     while (pte)
     {
         if (pte->egnum == vto)
         {
             return pte;
         }
         pte = pte->enext;
     }
     return NULL;
 }

 bool Graph::Addvt()                     //添加顶点
{
     cout << "请您输入要添加顶点的个数,程序将自动从当前图中顶点的最大编号往下顺次为新添加顶点编号:" << endl;
     int sum; cin >> sum;
     int itnum = vtail->number + 1;
     int begin = itnum;
     for (int i = 0; i < sum;i++)
     {
         vtail->vnext = new Vertices(itnum, NULL, NULL, NULL);
         if (!vtail->vnext){ cout << "申请空间失败!" << endl; return false; }
         vtail = vtail->vnext;
         itnum++;
         vsize++;
     }
     cout << "顶点添加成功!" << endl;
     cout << "新顶点编号从" << begin << "到" << itnum-1 << ",目前图中共有顶点" << vsize << "个。" << endl;
     cout << "当前新顶点为孤立顶点,建议您通过选项4添加指向新顶点的边和由新顶点发出的边。" << endl;
     return true;
 }

 int Graph::Addeg()                       //添加边
{
     cout << "提示:" << endl;
     cout << "输入时,请您依次输入边的起点编号、终点编号和边的权值,中间以空格相隔,例如:1 2 20。并且,请您务必输入正整数,";
     cout << "如果您未按规定输入,由此造成的一切后果,将由您个人承担,程序开发者概不负责!" << endl;
     bool sign = true, flag = true;
     int from, to, weit, choice, abandon,abandon1,abandon2;      //标签
    Vertices* pt=NULL;
     while (sign)
     {
         while (flag)
         {
             abandon = 0; abandon1 = 0; abandon2 = 0;       //只要重新输入,就要进行一次初始化
            cout << "请您依次输入边的起点、终点和权值:" << endl;
             cin>> from >> to >> weit;
             if (from == to)     //如果起、止点相同,不进行进一步检查,直接进行选择
            {
                 cout << "起点编号与终点编号不得相同!重新输入请按1,放弃本次输入请按0:" << endl;
                 cin >> choice;
                 if (choice == 0){ abandon1 = 1; abandon = 1; }
                 else  { abandon1 = 1; flag = false; }
             }
             if (!abandon1)  //如果起、止点不同,检查起、止点是否正确及两点间是否有边
            {
                 pt = Revads(from);
                 if (!pt)  //如果起点不存在,不进行进一步检查,直接进行选择
                {
                     cout << "您输入的起点不存在!重新输入请按1,放弃本次输入请按0:" << endl;
                     cin >> choice;
                     if (choice == 0){ abandon2 = 1; abandon = 1; }
                     else  { abandon2 = 1; flag = false; }
                 }
                 else  //如果起点存在,检查终点,若果终点不存在,不进行进一步检查,直接进行选择
                {
                     if (!Revads(to))
                     {
                         cout << "您输入的终点不存在!重新输入请按1,放弃本次输入请按0:" << endl;
                         cin >> choice;
                         if (choice == 0){ abandon2 = 1; abandon = 1; }
                         else { abandon2 = 1; flag = false; }
                     }
                 }
                 if (!abandon2)//如果两点输入正确且都存在,检查两点间是否有边,若无,进行选择
                {
                     Edge* ifedge = IfEdge(from, to);
                     if (ifedge)
                     {
                         cout << "从顶点" << from << "到顶点" << to << "的边已经存在,本程序部允许重复添加!重新输入请按1,放弃本次输入请按0:" << endl;
                         cin >> choice;
                         if (choice == 0)abandon = 1;
                         else  flag = false;
                     }
                 }
             }
             if (flag)flag = false;
             else flag = true;
         }   //控制输入正确的起点和终点
        //插入边
        if (!abandon)   //如果起点和终点输入正确,开始插入边
        {
             Edge* pte = new Edge(to, weit, NULL);
             if (!pte){ cout << "申请空间失败!" << endl; goto marka; }
             if (!pt->eghead)
             {
                 pt->eghead = pte;
             }
             else
             {
                 Edge* pter = pt->eghead;
                 while (pter->enext)
                     pter = pter->enext;
                 pter->enext = pte;
             }
             esize++;
             cout << "添加成功!目前图中有边" <<esize<< "条。" << endl;
         }
         cout << "是否继续添加边?是请按1,否则请按0:" << endl;
         cin >> choice;
         if (choice == 1)flag = true;
         else sign = false;
     }
     cout << "边添加完毕!目前图中共有边" <<esize<< "条。"<<endl;
     marka:
         return 0;
 }

 int Graph::Creat()                              //创建图
{
     bool sign = false, flag = true;
     int choice1;
     cout << "请您输入欲创建图的顶点的个数,程序将为您创建顶点并为顶点从1开始顺序编号:" << endl;
     cout << "(注意:请您务必输入正整数,否则后果自负!)" << endl;
     int numofv; cin >> numofv;
     int i;
     for (i = 1; i <= numofv;i++)
     {
         if (!vhead)
         {
             vhead = vtail = new Vertices(i, NULL,NULL, NULL);
             if (!vhead){ cout << "申请空间失败!" << endl; goto markc;}
         }
         else
         {
             vtail->vnext = new Vertices(i,NULL, NULL, NULL);
             if (!vtail->vnext){ cout << "申请空间失败!" << endl; goto markc; }
             vtail = vtail->vnext;
         }
     }
     vsize = i - 1;
     cout << "顶点创建成功!编号从1到" <<vsize<<"。"<< endl;
     cout << "是否添加边?是请按1,否则请按0:" << endl;
     cin >> choice1;
     if (choice1 == 1)Addeg();
     if (choice1 == 0)cout << "图创建成功,但图中无边!" << endl;
     else cout << "图创建成功!" << endl;
 markc:
     return 0;
 }

 void Graph::ShowAll()                       //展示全图
{
     cout << "<>内为顶点编号,[]内为权值:" << endl;
     cout << "顶点    " << "相邻顶点及边的权值" << endl;
     Vertices* pt = vhead;
     while (pt)
     {
         cout << setiosflags(ios::left);
         cout << "<"<<setw(2)<<pt->number <<">"<< "    ";
         Edge* pte = pt->eghead;
         while (pte)
         {
             cout << "<" << setw(2)<<pte->egnum << ">" << "[" <<setw(3)<< pte->weight << "]" << "   ";
             pte = pte->enext;
         }
         cout << endl;
         pt = pt->vnext;
     }
 }

 int Graph::Getweit(const int vfrom, const int vto)   //查看指定边权值
{
     Vertices* pt = Revads(vfrom);
     Edge* pte = pt->eghead;
     while (pte)
     {
         if (pte->egnum == vto)
             return pte->weight;
         pte = pte->enext;
     }
     return 0;
 }

 bool Graph::FinRoad(const int vfrom, const int vto)         //查找两点间所有简单路
{
     bool road = false, right, repeat, goon1, goon2;
     Vertices* pt = NULL;
     Edge* pte = NULL;
     int* array = new int[vsize];
     array[0] = vfrom;
     int top = 0;
     while (top>=0)
     {
         right = false; repeat = false; goon1 = true; goon2 = true;
         pt = Revads(array[top]);
         pte = pt->state;
         if (!pte)
         {
             pt->state = pt->eghead; top--; goon1 = false;
         }
         if (goon1)
         {
             while (!right&&pte)
             {
                 int item = pte->egnum;
                 for (int i = 0; i <= top;i++)
                 {
                     if (array[i] == item)
                     {
                         repeat = true;
                         break;
                     }
                 }
                 if (repeat)
                 {
                     repeat = false;
                     pte = pte->enext;
                 }
                 else right = true;
             }//内层while结束
            if (!pte)
             {
                 pt->state = pt->eghead; top--; goon2 = false;
             }
             if (goon2)
             {
                 array[++top] = pte->egnum;
                 pt->state = pte->enext;
                 if (pte->egnum == vto)
                 {
                     road = true;
                     int sum = 0;
                     for (int i = 0, j = 1; j <= top;i++,j++)
                     {
                         sum = sum + Getweit(array[i], array[j]);
                     }
                     for (int i = 0; i <= top; i++)
                     {
                         cout << array[i] << "  ";
                     }
                     cout << "权值:" << sum;
                     cout << endl;
                     top--;
                 }
             }//goon2结束
        }//goon1结束
    }//外层while结束
    delete[]array;
     return road;
 }

 void Graph::Destory()                  //销毁图
{
     while (vhead)
     {
         Edge* pte = vhead->eghead;
         while (pte)
         {
             Edge* iteme = pte;
             pte = pte->enext;
             delete iteme;
         }
         Vertices* itemv = vhead;
         vhead = vhead->vnext;
         delete itemv;
     }
     vhead = NULL;
     vtail = NULL;
     vsize = 0;
     esize = 0;
 }

 void Graph::Operate()              //封装操作
{
     bool flager = true;
     while (flager)
     {
         cout << "请您选择操作(输入操作前的数字进行选择):" << endl;
         cout << "1.创建图" << endl;
         cout << "2.展示全图" << endl;
         cout << "3.添加顶点" << endl;
         cout << "4.添加边" << endl;
         cout << "5.删除顶点" << endl;
         cout << "6.删除边" << endl;
         cout << "7.查看指定边权值" << endl;
         cout << "8.修改指定边权值" << endl;
         cout << "9.查找两点间所有简单路" << endl;
         cout << "10.销毁图" << endl;
         int chonum;         //choice number
         cin >> chonum;
         switch (chonum)
         {
          //创建图
        case 1:
         {
                   if (vhead){ cout << "图已经创建,无需再建!若想新建,请您先销毁旧图!" << endl; break; }
                   Creat();
                   break;
         }
         //展示全图
        case 2:
         {
                   if (!vhead){ cout << "图还未创建或已被销毁!无法执行展示全图操作!" << endl; break; }
                   ShowAll();
                   break;
         }
         //添加顶点
        case 3:
         {
                   if (!vhead){ cout << "图还未创建或已被销毁!无法在此处执行添加顶点操作!您可通过选项1来添加顶点。" << endl; break; }
                   Addvt();
                   break;
         }
         //添加边
        case 4:
         {
                   if (!vhead){ cout << "图还未创建或已被销毁!无法执行添加边操作!" << endl; break; }
                   Addeg();
                   break;
         }
         //删除顶点
        case 5:
         {
                   if (!vhead){ cout << "图还未创建或已被销毁!无法执行删除顶点操作!" << endl; break; }
                   int choice5,ver;
                   Vertices* pt = NULL;
                   cout << "警告:" << endl;
                   cout << "删除顶点操作存在风险!本程序在删除顶点的同时,将自动删除与该顶点直接相连的所有边(包括指向该顶点的和由该顶点发出的),";
                   cout << "因此,删除顶点操作可能产生较为严重的后果(如使连通的图一分为二或产生孤立点等)。请您慎重考虑!";
                   cout << "为安全起见,本操作一次只允许删除一个顶点,若您想删除多个顶点,可重复执行本操作。" << endl;
                   cout << "您确定要删除顶点吗?确定请按1,取消请按0:" << endl;
                   cin >> choice5;
                   if (choice5 == 0)break;
                   cout << "提示:" << endl;
                   cout << "输入顶点编号时,请您务必输入正整数,如果您未按规定输入,由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
                   bool sign5 = true;
                   while (sign5)      //控制输入正确的顶点编号
                  {
                       cout << "请您输入顶点编号:" << endl;
                       cin >> ver;
                       pt = Revads(ver);
                       if (!pt)
                       {
                           cout << "您输入的顶点在当前图中不存在!重新输入请按1,退出删除顶点操作请按0:" << endl;
                           cin >> choice5;
                           if (choice5 == 0)goto mark5;
                           else sign5 = false;
                       }
                       if (sign5)sign5 = false;
                       else sign5 = true;
                   }//while(sign5)结束
                  //删除
                  //将欲删除顶点及其边单拿出来
                  if (pt == vhead)
                       vhead = vhead->vnext;
                   else
                   {
                       Vertices* ptv = vhead;
                       while (ptv)     //找到pt的前驱
                      {
                           if (ptv->vnext == pt)
                               break;
                           ptv = ptv->vnext;
                       }
                       ptv->vnext = pt->vnext;
                   }
                   //删除顶点指向的边
                  Edge* pte = pt->eghead;
                   while (pte)
                   {
                       Edge* iteme = pte;
                       pte = pte->enext;
                       delete iteme;
                       esize--;
                   }
                   //删除顶点
                  delete pt;
                   vsize--;
                   //删除指向该顶点的边
                  Vertices* ptrv = vhead;
                   while (ptrv)
                   {
                       int item = ptrv->number;
                       Edge* ptre = IfEdge(item, ver);
                       if (ptre)
                       {
                           if (ptre==ptrv->eghead)
                           {
                               ptrv->eghead = ptre->enext;
                               delete ptre;
                               esize--;
                           }
                           else
                           {
                               Edge* pre = ptrv->eghead;
                               while (pre)
                               {
                                   if (pre->enext == ptre)
                                       break;
                                   pre = pre->enext;
                               }
                               pre->enext = ptre->enext;
                               delete ptre;
                               esize--;
                           }
                       }
                       ptrv = ptrv->vnext;
                   }//while(ptrv)结束
                  cout << "删除成功!目前图中共有顶点" << vsize << "个,边" << esize << "条。" << endl;
               mark5:
                   break;
         }
         //删除边
        case 6:
         {
                   if (!vhead){ cout << "图还未创建或已被销毁!无法执行删除边操作!" << endl; break; }
                   int choice6,from,to;
                   Vertices* pt=NULL;
                   Edge* ifedge=NULL;
                   cout << "警告:" << endl;
                   cout << "删除边操作存在风险!(如使连通的图一分为二或产生孤立点等)请您慎重考虑!为安全起见,本操作一次只允许删除一条边,";
                   cout << "若您想删除多条边,可重复执行本操作。" << endl;
                   cout << "您确定要删除边吗?确定请按1,取消请按0:" << endl;
                   cin >> choice6;
                   if (choice6 == 0)break;
                   cout << "提示:" << endl;
                   cout << "输入时,请您依次输入起点编号和终点编号,务必输入正整数,并以空格相隔,例如:1 2。如果您未按规定输入,";
                   cout << "由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
                   bool flag6=true,control6,control61;
                   while (flag6)
                   {
                       control6 = true; control61 = true;
                       cout << "请您依次输入边的起点编号和终点编号:" << endl;
                       cin >> from >> to;
                       if (from == to)
                       {
                           cout << "起点编号与终点编号不得相同!重新输入请按1,退出删除操作请按0:" << endl;
                           cin >> choice6;
                           if (choice6 == 0)goto mark6;
                           else  { control6 = false; flag6 = false; }
                       }
                       if (control6)
                       {
                           pt = Revads(from);
                           if (!pt)
                           {
                               cout << "您输入的起点不存在!重新输入请按1,退出删除操作请按0:" << endl;
                               cin >> choice6;
                               if (choice6 == 0)goto mark6;
                               else  { control61 = false; flag6 = false; }
                           }
                           else
                           {
                               if (!Revads(to))
                               {
                                   cout << "您输入的终点不存在!重新输入请按1,退出删除操作请按0:" << endl;
                                   cin >> choice6;
                                   if (choice6 == 0)goto mark6;
                                   else { control61 = false; flag6 = false; }
                               }
                           }
                           if (control61)
                           {
                               ifedge = IfEdge(from, to);
                               if (!ifedge)
                               {
                                   cout << "不存在从顶点" << from << "到顶点" << to << "的边,无法执行删除操作!重新输入请按1,退出删除操作请按0:" << endl;
                                   cin >> choice6;
                                   if (choice6 == 0)goto mark6;
                                   else  flag6 = false;
                               }
                           }
                       }
                       if (flag6)flag6 = false;
                       else flag6 = true;
                   }   //控制输入正确的起点和终点
                  //删除
                  if (ifedge==pt->eghead)
                   {
                       Edge* item = ifedge;
                       ifedge = ifedge->enext;
                       pt->eghead = ifedge;
                       delete item;
                   }
                   else
                   {
                       Edge* pter = pt->eghead;
                       while (pter)
                       {
                           if (pter->enext = ifedge)
                               break;
                       }
                       pter->enext = ifedge->enext;
                       delete ifedge;
                   }
                   esize--;   //边数减1
                   cout << "从顶点" << from << "到顶点" << to << "的边已成功删除!目前图中共有边" <<esize<<"条。"<< endl;
               mark6:
                   break;
         }
//查看指定边权值
        case 7:
        {
                  if (!vhead){ cout << "图还未创建或已被销毁!无法执行查询操作!" << endl; break; }
                  cout << "提示:" << endl;
                  cout << "输入时,请您依次输入起点编号和终点编号,务必输入正整数,并以空格相隔,例如:1 2。如果您未按规定输入,";
                  cout << "由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
                  bool control = true,sign7=true,flag7,flag71;
                  int vf, vt, choice7;
                  Vertices* ptv = NULL;
                  Edge* ifedge = NULL;
                  while (sign7)
                  {
                      while (control)        //控制输入正确的起点编号和终点编号
                      {
                          flag7 = true; flag71 = true;
                          cout << "请您依次输入起点编号和终点编号:" << endl;
                          cin >> vf >> vt;
                          if (vf == vt)
                          {
                              cout << "起点编号与终点编号不得相同!重新输入请按1,退出查找操作请按0:" << endl;
                              cin >> choice7;
                              if (choice7 == 0)goto mark7;
                              else { flag7 = false; control = false; }
                          }
                          if (flag7)
                          {
                              ptv = Revads(vf);
                              if (!ptv)
                              {
                                  cout << "您输入的起点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                                  cin >> choice7;
                                  if (choice7 == 0)goto mark7;
                                  else { flag71 = false; control = false; }
                              }
                              else
                              {
                                  if (!Revads(vt))
                                  {
                                      cout << "您输入的终点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                                      cin >> choice7;
                                      if (choice7 == 0)goto mark7;
                                      else { flag71 = false; control = false; }
                                  }
                              }
                              if (flag71)
                              {
                                  ifedge = IfEdge(vf, vt);
                                  if (!ifedge)
                                  {
                                      cout << "不存在从顶点" << vf << "到顶点" << vt << "的边,无法执行查找操作!重新输入请按1,退出删除操作请按0:" << endl;
                                      cin >> choice7;
                                      if (choice7 == 0)goto mark7;
                                      else  control = false;
                                  }
                              }
                          }
                          if (control)control = false;
                          else control = true;
                      }//while循环结束
                      int itemw = ifedge->weight;
                      cout << "从顶点" << vf << "到顶点" << vt << "的边的权值为" << itemw << endl;
                      cout << "是否继续查询?是请按1,否则请按0:" << endl;
                      cin >> choice7;
                      if (choice7 == 0)sign7 = false;
                      else control = true;
                  }
              mark7:
                  break;
        }
        //修改指定边权值
        case 8:
        {
                  if (!vhead){ cout << "图还未创建或已被销毁!无法执行修改操作!" << endl; break; }
                  cout << "提示:" << endl;
                  cout << "输入时,请您依次输入要修改权值的边的起点编号和终点编号,务必输入正整数,并以空格相隔,例如:1 2。如果您未按规定输入,";
                  cout << "由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
                  bool control = true, sign8 = true,flag8,flag81;
                  int vf, vt, choice8;
                  Vertices* ptv = NULL;
                  Edge* ifedge = NULL;
                  while (sign8)
                  {
                      while (control)        //控制输入正确的起点编号和终点编号
                      {
                          flag8 = true; flag81 = true;
                          cout << "请您依次输入起点编号和终点编号:" << endl;
                          cin >> vf >> vt;
                          if (vf == vt)
                          {
                              cout << "起点编号与终点编号不得相同!重新输入请按1,退出查找操作请按0:" << endl;
                              cin >> choice8;
                              if (choice8 == 0)goto mark8;
                              else { flag8 = false; control = false; }
                          }
                          if (flag8)
                          {
                              ptv = Revads(vf);
                              if (!ptv)
                              {
                                  cout << "您输入的起点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                                  cin >> choice8;
                                  if (choice8 == 0)goto mark8;
                                  else { flag81 = false; control = false; }
                              }
                              else
                              {
                                  if (!Revads(vt))
                                  {
                                      cout << "您输入的终点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                                      cin >> choice8;
                                      if (choice8 == 0)goto mark8;
                                      else { flag81 = false; control = false; }
                                  }
                              }
                              if (flag81)
                              {
                                  ifedge = IfEdge(vf, vt);
                                  if (!ifedge)
                                  {
                                      cout << "不存在从顶点" << vf << "到顶点" << vt << "的边,无法执行查找操作!重新输入请按1,退出删除操作请按0:" << endl;
                                      cin >> choice8;
                                      if (choice8 == 0)goto mark8;
                                      else  control = false;
                                  }
                              }
                          }
                          if (control)control = false;
                          else control = true;
                      }//while循环结束
                      cout << "请您输入新权值(务必输入正整数,否则后果自负!):" << endl;
                      int oldwt,newwt; cin >> newwt;
                      oldwt = ifedge->weight;
                      ifedge->weight = newwt;
                      cout << "修改成功!" << endl;
                      cout << "该边权值从" << oldwt << "修改为" << newwt << "。" << endl;
                      cout << "是否继续修改?是请按1,否则请按0:" << endl;
                      cin >> choice8;
                      if (choice8 == 0)sign8 = false;
                      else control = true;
                  }
              mark8:
                  break;
        }
        //查找两点间所有简单路
        case 9:
        {
                  cout << "提示:" << endl;
                  cout << "输入时,请您依次输入起点编号和终点编号,务必输入正整数,并以空格相隔,例如:1 2。如果您未按规定输入," ;
                  cout << "由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
                  bool control=true,flag9;
                  int vf, vt,choice9;
                  Vertices* ptv = NULL;
                  while (control)        //控制输入正确的起点编号和终点编号
                  {
                      flag9 = true;
                      cout << "请您依次输入起点编号和终点编号:" << endl;
                      cin >> vf >> vt;
                      if (vf == vt)
                      {
                          cout << "起点编号与终点编号不得相同!重新输入请按1,退出查找操作请按0:" << endl;
                          cin >> choice9;
                          if (choice9 == 0)goto mark9;
                          else { flag9 = false; control = false; }
                      }
                      if (flag9)
                      {
                          ptv = Revads(vf);
                          if (!ptv)
                          {
                              cout << "您输入的起点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                              cin >> choice9;
                              if (choice9 == 0)goto mark9;
                              else control = false;
                          }
                          else
                          {
                              if (!Revads(vt))
                              {
                                  cout << "您输入的终点编号在当前图中不存在!重新输入请按1,退出查找操作请按0:" << endl;
                                  cin >> choice9;
                                  if (choice9 == 0)goto mark9;
                                  else control = false;
                              }
                          }
                      }
                      if (control)control = false;
                      else control = true;
                  }//while循环结束
                  //顶点状态初始化
                  Vertices* ptr = vhead;
                  while (ptr)
                  {
                      ptr->state = ptr->eghead;
                      ptr = ptr->vnext;
                  }//初始化完成
                  bool ifroad = FinRoad(vf, vt);   //执行查找函数
                  if (ifroad)
                  {
                      cout << "以上为从" << vf << "到" << vt << "的所有简单路及路径对应权值!" << endl;
                  }
                  else cout << "不存在从" <<vf<<"到"<<vt<<"的任何简单路!"<< endl;
                  //状态还原
                  Vertices* ptrv = vhead;
                  while (ptrv)
                  {
                      ptrv->state = NULL;
                      ptrv = ptrv->vnext;
                  }//还原完成
              mark9:
                  break;
        }
        //销毁图
        case 10:
        {
                   if (!vhead){ cout << "图还未创建或已被销毁!不能再销毁!" << endl; break; }
                   cout << "您确定销毁该图吗?确定请按1,取消请按0:" << endl;
                   int choice10; cin >> choice10;
                   if (choice10 == 1)
                       Destory();
                   cout << "图已销毁!" << endl;
                   break;
        }
        //处理用户错误输入
        default:
        {
                   cout << "您的输入有误,无法进行操作!" << endl;
                   break;
        }
        }//switch结束
        //循环控制
        cout << "是否继续?继续请按1,退出请按0:" << endl;
        int ifgoon;
        cin >> ifgoon;
        if (ifgoon == 0)flager = false;
    }//while结束
}

#endif
//.cpp文件
#include<iostream>
#include"graph.h"
using namespace std;

int main()
{
    //是否进入程序
    int uscho;   bool flag = true;//uscho:user choice的缩写
    cout << "敬告;请您务必按提示要求操作,如果您进行了规定以外的操作,由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
    cout << "是否进入程序?进入请按1,否则按0;" << endl;
    cin >> uscho;
    if (uscho == 0) return 0;
    Graph graph;
    graph.Operate();
    return 0;
}

    Ⅵ.结语
       代码已经过测试,在VS2013上成功运行!
       发此文有两大目的:
       1.和大家交流经验,供需要的人参考。
       2.在下菜鸟,代码中难免有不妥之处,恳求大神批评指正。您的批评就是在下提高
       的起点,对于您的批评,在下将不胜感激!
时间: 2024-10-05 22:02:17

C++实现有向权图的基本操作,界面友好,操作方便,运行流畅的相关文章

每日一题28:图的基本操作

本文记录了基于邻接表表示的有向有权图的基本操作.邻接表表示的图的结构就是用一个散列表存储图的节点,而每个节点后面跟着从节点出发的所有边的集合,这些边用链表连接起来,所以在这样的图中寻找一个节点发出的边是容易的,但是寻找进入一个节点的边是困难的,需要遍历所有的边.删除一条边也比较容易,删除一个节点则需要寻找与该节点相关的所有边,并将这些边也删除. #ifndef _NOWEIGHTGRAPH_H_ #define _NOWEIGHTGRAPH_H_ #include "../include/Vec

带权图的最短路径算法(Dijkstra)实现

一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带权的.不带权的Dijkstra算法要简单得多(可参考我的另一篇:无向图的最短路径算法JAVA实现):而对于带权的Dijkstra算法,最关键的是如何“更新邻接点的权值”.本文采用最小堆主辅助,以重新构造堆的方式实现更新邻接点权值. 对于图而言,存在有向图和无向图.本算法只需要修改一行代码,即可同时实

算法10 之带权图

上一节我们已经看到了图的边可以有方向,这一节里,我们将探讨边的另一个特性:权值.例如,如果带权图的顶点代表城市,边的权可能代表城市之间的距离,或者城市之间的路费,或者之间的车流量等等. 带权图归根究底还是图,上一节那些图的基本操作,例如广度优先搜索和深度优先搜索等都是一样的,在这一节里,我们主要来探讨一下带权图的最小生成树最短路径问题. 最小生成树问题 首先探讨下最小生成树问题,它与上一节所提到的最小生成树不同.上一节的最小生成树是个特例,即所有边的权值都一样.那么算法如何设计呢?建议用优先级队

Java数据结构——带权图

带权图的最小生成树——Prim算法和Kruskal算法 带权图的最短路径算法——Dijkstra算法 package graph; // path.java // demonstrates shortest path with weighted, directed graphs 带权图的最短路径算法 // to run this program: C>java PathApp ////////////////////////////////////////////////////////////

用无向带权图实现校园导航系统

学校数据结构的课程实验之一. 用到的数据结构:无向带权图 用到的算法:Floyd最短路径算法,深度优先搜索(递归实现) 需求分析: 设计一个校园导航程序,为访客提供各种信息查询服务: 1. 以图中各顶点表示校内各单位地点,存放单位名称,代号,简介等信息:以边表示路径,存放路径长度等相关信息. 2. 图中任意单位地点相关信息的查询. 3. 图中任意单位的问路查询,即查询任意两个单位之间的一条最短的路径. 2. 从图中任意单位地点出发的一条深度优先遍历路径. 主函数: 1 #include <ios

数据结构 【实验9 图的基本操作】

实验9  图的基本操作 实验目的 1.  掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表存储结构. 2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和广度优先遍历算法,复习栈和队列的应用. 实验内容 程序1 /* 定义邻接矩阵类型 */ typedef int  adjmatrix[n+1][n+1]; /* 建立图的邻接矩阵 */ void CreatMatrix(adjmatrix GA) /* 从初始点v出发深度优先遍历邻接矩阵GA表示的图 */ void DfsMatr

带负权图的单源最短路径算法:Bellman-Ford算法

算法简介 前面介绍过图的单源最短路径算法Dijkstra算法,然而Dijkstra算法无法判断含负权边的图的最短路.如果遇到负权,在没有负权回路存在时(负权回路的含义是,回路的权值和为负.)即便有负权的边,也可以采用Bellman-Ford算法正确求出最短路径. Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数 w是 边集 E 的映射.对图G运行Bellman-Ford算法的结果是一个布尔值,表

邻接矩阵表示有向带权图

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef char VertexType[5]; //存储顶点值 #define MaxSize 50 #define INIT 10000 typedef struct //邻接矩阵,存储弧的信息 {     int adj; }ArcNode,AdjMatrix[MaxSize][MaxSize]; typedef struct   //图的类

Dijkstra求含权图最短通路;试探与回溯保证枚举的不遗漏不重复;国际象棋八皇后问题

求两节点的最短通路,对于无权图,可以通过图的广度优先遍历求解.含权图一般通过Dijkstra算法求解. import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class Shortest { static class Cell{ int node;//连接到哪个节点 int weight