乖乖,这个两个代码可长啦,
Graphlink.h,是图的邻接表的类模板,
Graphmtx.h,是图的邻接矩阵的类模板,
都是写了很长时间的,
Graphlink.h代码如下:
#ifndef GRAPHLINK_H
#define GRAPHLINK_H
#include"BaseGraph.h"
#include<iostream.h>
#include<stdlib.h>
#include"LinkedQueue.h"
#include"GenTree.h"
#include"Forest.h"
/////////////////////////////////////////////////
//Edge 边结点结构的定义
/////////////////////////////////////////////////
template<class T,class E>
struct Edge
{
    int dest;
             //目的结点的结点号
    E cost;
               //边对应的权值
    Edge<T,E>* link;
      //下一条边结点的指针
    Edge(){};
             //默认构造函数
    Edge(int num,E weight)//带参数的构造函数
    :dest(num),cost(weight),link(NULL){};
    bool operator!=(Edge<T,E>& R)const
    {
                     //成员重载运算符
        if(R.dest==dest)
  //判断两个边结点是否相等
            return true;
        else
            return false;
    };
};
///////////////////////////Edge边结点结构定义结束
/////////////////////////////////////////////////
//Vertex结构 图的顶点结点的定义 
/////////////////////////////////////////////////
template<class T,class E>
struct Vertex
{
    T data;
        //结点的数据域
    Edge<T,E>* adj;//边链表的首指针
};
///////////////////////////Vertex顶点结构定义结束
/////////////////////////////////////////////////
//Graphlink<T,E>类模板的实现
//以邻接链表方式实现的图的类模板的声明和实现
//该类以Graph<T,E>为虚基类
//T是顶点数据域类型,E是边的权值类型
/////////////////////////////////////////////////
template<class T,class E>
class Graphlink:public Graph<T,E>
{
private:
    Vertex<T,E>* NodeTable;
                 //顶点表数组
    int getVertexPos(const T vertex)
        //给出指定顶点Vertex的结点号
    {
        for(int i=0;i<numVertices;i++)
      //遍历所有的邻接顶点
            if(NodeTable[i]==vertex)
                return i;
        return -1;
                          //没有找到
    };
    bool* visited;
                          //用于标记第i个结点是否被访问的数组
    void DFS(int start);
                    //递归:深度优先遍历本图,start是起始结点
public:
    Graphlink(int sz=DefaultVertices);
      //默认构造函数
    ~Graphlink();
                           //析构函数
    T getValue(int i)
                       //取结点号为i的结点里的数据
    {
        if(i>=0 && i<maxVertices)
            return NodeTable[i].data;
        else
            return 0;
    };
    
    E getWeight(int v1,int v2);
              //取得边(v1,v2)上的权值
    bool insertVertex(const T vertex);
       //在图中插入一个顶点vertex
    bool removeVertex(int v);
                //在图中删除指定结点号v的结点
    bool insertEdge(int v1,int v2,E cost);
   //插入一条边以及对应的权值
    bool removeEdge(int v1,int v2);
          //删除边(v1,v2)
    int getFirstNeighbor(int v);
             //取得结点v的第一个邻接结点
    int getNextNeighbor(int v,int w);
        //取得v的邻接结点中w后的那个邻接结点
    void DFSGraphic(int start);
              //深度优先遍历当前图所有结点
    void BFSGraphic();
                       //广度优先遍历
    void Find_Connected_Component();
         //求图的所有的连通分量顶点集
    TreeNode<T>* DFSTree(int v);
             //递归:得到以v为出发点的深度优先生成树TS
    void DisplayDFSTree(int v);
              //调用上面的递归函数求图的深度优先生成树
    TreeNode<T>* DFSForest(int v);
           //则求其所有连通分量的的深度优先生成森林
    void Find_DFSForest(int v)
               //得到非连通图的深度优先生成森林
    {
        Forest<char> F;
        F.setRoot(DFSForest(0));
        cout<<"深度优先生成森林是:"<<endl;
        F.Display();
    };
    int getFirstUnvisit(int p,bool* visited);
     //得到当前未访问的第一个邻接结点
    int getNextUnvisit(int p,int v,bool* visited);//得到下个未访问的邻接结点
    void DepthFirst(int start);
                   //非递归深度优先遍历当前图
    //友元重载输出运算符
    friend ostream& operator<<(ostream& os,Graphlink<T,E>& G);
    //友元重载输入运算符
    friend istream& operator>>(istream& is,Graphlink<T,E>& G);
};
/////////////////////Graphlink<T,E>类模板声明结束
/////////////////////////////////////////////////
//默认构造函数
/////////////////////////////////////////////////
template<class T,class E>
Graphlink<T,E>::Graphlink(int sz)
{
    maxVertices=sz;
     //图中最大的顶点数
    numEdges=0;
         //初始边数
    numVertices=0;
      //初始顶点数
    
    //顶点表数组开辟内存区域
    NodeTable=new Vertex<T,E>[sz];
    if(NodeTable==NULL)
    {
        cout<<"内存分配失败!"<<endl;
        exit(1);
    };
    //初始化顶点数组里的内容
    for(int i=0;i<maxVertices;i++)
        //把每个边链表的手指指针初始化为空
        NodeTable[i].adj=NULL;
};
/////////////////////////////////默认构造函数结束
/////////////////////////////////////////////////
//析构函数结束
//释放所有的边链表的内存以及结点数组的内存
/////////////////////////////////////////////////
template<class T,class E>
Graphlink<T,E>::~Graphlink()
{
    //首先遍历每条边链表的首结点
    for(int i=0;i<numVertices;i++)
    {
        Edge<T,E>*& ptr=NodeTable[i].adj;//游标指针
        Edge<T,E>* pre;
                  //前个边结点的指针
        while(ptr!=NULL)
        {
            pre=ptr;
                     //保留当前边结点
            ptr=ptr->link;
               //指向下个边结点
            delete
  pre;
                 //释放结点内存
        };
    };
};
/////////////////////////////////////析构函数结束
/////////////////////////////////////////////////
//getWeight()公有成员函数
//得到指定边(v1,v2)上的权值
/////////////////////////////////////////////////
template<class T,class E>
E Graphlink<T,E>::getWeight(int v1,int v2)
{
    Edge<T,E>* ptr=NodeTable[v1].adj;//得到v1结点的边链表的首指针
    while(ptr!=NULL)
                 //遍历该边链表找结点v2
    {
        if(ptr->dest==v2)
            //如果找到就返回
            return ptr->cost;
        ptr=ptr->link;
    }
    return maxWeight;
                //即这两点之间不存在边
};
//////////////////////getWeight()公有成员函数结束
/////////////////////////////////////////////////
//insertVertex()公有成员函数
//在图中插入一个顶点
/////////////////////////////////////////////////
template<class T,class E>
bool Graphlink<T,E>::insertVertex(const T vertex)
{
    if(numVertices<maxVertices)
      //结点表不满则插入新结点
    {
         NodeTable[numVertices++].data=vertex;
        return true;
                 //插入成功
    } 
    else
        return false;
                //表满插入失败
};
///////////////////////////insertVertex()函数结束
/////////////////////////////////////////////////
//removeVertex()公有成员函数
//在图中删除指定结点号的结点v,也删除和v关联的边
/////////////////////////////////////////////////
template<class T,class E>
bool Graphlink<T,E>::removeVertex(int v)
{
    if(v<0 || v>=numVertices)
       //如果给出的结点号不存在
        return false;
    /*首先删除和结点v相关联的边链表*/
    Edge<T,E>* ptr=NodeTable[v].adj;//游标指针
    Edge<T,E>* pre;
                 //指向释放的前一个结点
    while(ptr!=NULL)
                //释放边链表中所有结点
    {
        pre=ptr;
        ptr=ptr->link;
        delete pre;
        numEdges--;
                 //每删去一个边结点,numEdges减1
    };
    NodeTable[v].adj=NULL;
          //该与结点的边链表置空
    /*在其他的边链表中也对称删除dest为v的边结点*/
    for(int i=0;i<numVertices;i++)
  //遍历每一个边链表
    {
        ptr=NodeTable[i].adj;
       //取得每个边链表的首指针
        if(ptr==NULL)
               //如果边链表是空的
            continue;
        else if(ptr!=NULL
           //如果是在头部删除
            && ptr->dest==v)
        {
            NodeTable[i].adj=ptr->link;
            delete ptr;
        }
        else
        {
            while(ptr->link!=NULL)
            {
                if(ptr->link->dest==v)
                {
                   //如果找到该结点
                    pre=ptr->link;
                    ptr->link=ptr->link->link;
                    delete pre;
                    break;
                };
                ptr=ptr->link;
      //指针向后推进一格
            };
        };
    };
    /*把NodeTable中的最后一个元素填补到v对应的位置*/
    NodeTable[v].data=NodeTable[numVertices-1].data;
    NodeTable[v].adj=NodeTable[numVertices-1].adj;
    NodeTable[numVertices-1].adj=NULL;
    
    /*把所有的原来结点号是numVertices-1的结点
    的结点号改为v*/
    int p=numVertices-1;
            //原来最后一个结点的结点号
    for(i=0;i<numVertices-1;i++)
    //遍历所有的边链表
    {
        ptr=NodeTable[i].adj;
       //游标指针
        while(ptr!=NULL)
            //遍历每个边结点
        {
            if(ptr->dest==p)
        //原来目的结点是p的
                ptr->dest=v;
        //现在改为v
            ptr=ptr->link;
        };
    };
    numVertices--;
                  //结点的个数减1
    return true;
                    //删除成功
};
///////////////////////////removeVertex()函数结束
/////////////////////////////////////////////////
//insertEdge()公有成员函数
  
//在结点v1和v2之间建立一条边,同时对称建立边链表结点
/////////////////////////////////////////////////
template<class T,class E>
bool Graphlink<T,E>::insertEdge(int v1,int v2,E cost)
{
    if(v1<0 || v2<0 || v1>=numVertices || v2>=numVertices)
        return false;
    /*在v1的边链表中插入v2*/
    Edge<T,E>* ptr=NodeTable[v1].adj;
         //游标指针
    Edge<T,E>* newEdge1=new Edge<T,E>(v2,cost);//新建边链表
    
    if(NodeTable[v1].adj==NULL)
               //如果边链表本来是空的
    {
        NodeTable[v1].adj=newEdge1;
    }
    else if(v2<NodeTable[v1].adj->dest)
       //在头部插入
    {
        newEdge1->link=NodeTable[v1].adj;
        NodeTable[v1].adj=newEdge1;
    }
    else
    {
        while(ptr->link!=NULL)
                //寻找位置插入
        {
            if(ptr->dest<v2 && ptr->link->dest>v2)
            {
                newEdge1->link=ptr->link;
                ptr->link=newEdge1;
                break;
            }
            ptr=ptr->link;
        };
        if(ptr->link==NULL)
                   //如果在尾部插入
            ptr->link=newEdge1;
    };
    /*在v2的边链表中插入v1*/
    ptr=NodeTable[v2].adj;
    Edge<T,E>* newEdge2=new Edge<T,E>(v1,cost);//新建边链表
    
    if(NodeTable[v2].adj==NULL)
               //如果边链表本来是空的
    {
        NodeTable[v2].adj=newEdge2;
    }
    else if(v1<NodeTable[v2].adj->dest)
       //在头部插入
    {
        newEdge2->link=NodeTable[v2].adj;
        NodeTable[v2].adj=newEdge2;
    }
    else
    {
        while(ptr->link!=NULL)
                //寻找位置插入
        {
            if(ptr->dest<v1 && ptr->link->dest>v1)
            {
                newEdge2->link=ptr->link;
                ptr->link=newEdge2;
                break;
            }
            ptr=ptr->link;
        };
        if(ptr->link==NULL)
                   //如果在尾部插入
            ptr->link=newEdge2;
    };
    numEdges++;
                               //边数加1
    return true;
};
/////////////////////insertEdge()公有成员函数结束
/////////////////////////////////////////////////
//removeEdge()公有成员函数
//删除图中指定的一条变
/////////////////////////////////////////////////
template<class T,class E>
bool Graphlink<T,E>::removeEdge(int v1,int v2)
{
    if(v1<0 || v1>=maxWeight
              //如果v1和v2是合法的
    || v2<0 || v2>=maxWeight)
        return false;
                     //删除失败
    Edge<T,E>* ptr;
                       //游标指针
    Edge<T,E>* pre;
                       //前一个结点
    /*在v1的边链表中删除边结点v2*/
    ptr=NodeTable[v1].adj;
                //v1边链表的首指针
    if(NodeTable[v1].adj==NULL)
           //比边链表是空的
        return false;
                     //删除失败
    else if(NodeTable[v1].adj->dest==v2)
  //如果是在头部删
    {
                                     //删除结点
        pre=NodeTable[v1].adj;
        NodeTable[v1].adj=NodeTable[v1].adj->link;
        delete pre;
    }
    else
                                  //如果是在头结点以外结点删除
    {
        int flag=0;
                       //是否有结点删除
        while(ptr->link!=NULL)
            //寻找要删除的v2边结点
        {
            if(ptr->link->dest==v2)
       //删除v2边结点
            {
                flag=1;
                   
                pre=ptr->link;
                ptr->link=ptr->link->link;
                delete pre;
                break;
            };
            ptr=ptr->link;
                //指针向后推进一格
        };
        if(flag==0)
                       //如果没有找到边结点v2
        {
            cout<<"该边不存在!"<<endl;
            return false;
                 //该边不存在删除失败
        };
    };
    /*在v2的边链表中删除边结点v1*/
    ptr=NodeTable[v2].adj;
                //v1边链表的首指针
    if(NodeTable[v2].adj==NULL)
           //比边链表是空的
        return false;
                     //删除失败
    else if(NodeTable[v2].adj->dest==v1)
  //如果是在头部删
    {
                                     //删除结点
        pre=NodeTable[v2].adj;
        NodeTable[v2].adj=NodeTable[v2].adj->link;
        delete pre;
    }
    else
                                  //如果是在头结点以外结点删除
    {
        int flag=0;
                       
        while(ptr->link!=NULL)
            //寻找要删除的v2边结点
        {
            if(ptr->link->dest==v1)
       //删除v2边结点
            {
                flag=1;
                pre=ptr->link;
                ptr->link=ptr->link->link;
                delete pre;
                break;
            };
            ptr=ptr->link;
                //指针向后推进一格
        };
        if(flag==0)
        
            //该边不存在
            return false;
                 //删除失败
    };
    numEdges--;
                           //边的个数减1
    return true;
};
/////////////////////////////removeEdge()函数结束
/////////////////////////////////////////////////
//getFirstNeighbor()公有成员函数
//得到指定结点v的第一个相邻的结点
/////////////////////////////////////////////////
template<class T,class E>
int Graphlink<T,E>::getFirstNeighbor(int v)
{
    if(v>=0 && v<numVertices)
         //如果指定的结点存在
    {
        Edge<T,E>* p=NodeTable[v].adj;//边链表的首结点指针
        if(p!=NULL)
            return p->dest;
        else
            return -1;
    }
    else
        return -1;
};
///////////////////////getFirstNeighbor()函数结束
/////////////////////////////////////////////////
//getNextNeighbor()公有成员函数
//得到当前结点v的邻接顶点w下个邻接顶点的顶点号
/////////////////////////////////////////////////
template<class T,class E>
int Graphlink<T,E>::getNextNeighbor(int v,int w)
{
    if(v>=0 && v< maxWeight
             //如果结点号合法
    && w>=0 && w< maxWeight)
    {
        Edge<T,E>* ptr=NodeTable[v].adj;//获得和结点v对应的边链表的首指针
        while(ptr!=NULL)
                //遍历该边链表对应的多有的边结点
        {
            if(ptr->dest==w)
            //如果找到目的结点为w的边结点
                break;
                  //结束查找
            ptr=ptr->link;
        };
        if(ptr!=NULL && ptr->link!=NULL)//如果ptr和ptr的下个结点都不空
            return ptr->link->dest;
        else
            return -1;
                  //这样的结点不存在,查找失败
    }
    else
        return -1;
};
////////////////////////getNextNeighbor()函数结束
/////////////////////////////////////////////////
//DFS()私有成员函数 
//递归:深度优先遍历图所有结点,start是起始结点
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::DFS(int start)
{
    cout<<getValue(start)<<" ";
      //访问当前的起始结点
    visited[start]=true;
             //把对应的访问标志置为"已访问"
    int p=getFirstNeighbor(start);
   //获取start的第一个邻接结点
    while(p!=-1)
                     //递归访问start的所有邻接结点
    {
        if(visited[p]==false)
        //如果neighbor没有被访问过
            DFS(p);
                  //以neighbor为当前结点继续递归访问
        p=getNextNeighbor(start,p);
  //获取下个邻接结点的结点号
    };
};
////////////////////////////DFS()私有成员函数结束
/////////////////////////////////////////////////
//DFSGraphic()公有成员函数
//深度优先遍历图所有结点,通过键盘输入起始结点
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::DFSGraphic(int start)
{
    visited=new bool[numVertices];
    for(int i=0;i<numVertices;i++)
        visited[i]=false;//把每个结点的访问标志置为否
    cout<<endl<<"深度优先遍历的结果是:"<<endl;
    if(start>=0 && start<numVertices)
         DFS(start);
      //如果输入的结点号合法就开始遍历
    else
        exit(1);
    delete [] visited;
   //释放标记数组的内存空间
};
/////////////////////DFSGraphic()公有成员函数结束
/////////////////////////////////////////////////
//BFSGraphic()公有成员函数
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::BFSGraphic()
{
    cout<<"请输入遍历的起始顶点号:";
    int start;
                         //起始的结点号
    cin>>start;
    visited=new bool[numVertices];
     //开辟标记数组的内存空间
    for(int i=0;i<numVertices;i++)
        visited[i]=false;
              //把标记数组置为未访问
    LinkedQueue<int> Q;
                //用于存放结点号的队列
    Q.EnQueue(start);
                  //首先把起始顶点的标号压入队列
    if(start<0 || start>=numVertices)
  //如果起始的结点号不合法
        exit(1);
    int p;
                             //当前正在访问的顶点的顶点号
    int q;
                             //所有邻接结点的游标指针
    while(!Q.IsEmpty())
                //按层次遍历图的所有顶点
    {
        Q.DeQueue(p);
                  //从队列中取出一个结点
        if(visited[p]==false)
          //如果不曾被访问
        {
            cout<<getValue(p)<<" ";
    //访问该结点
            visited[p]=true;
           //已经被访问过
            q=getFirstNeighbor(p);
     //获取当前访问结点的第一个邻接结点
            while(q!=-1)
               //把所有的未被访问过的邻接结点全部送入队列
            {
                if(visited[q]==false)
                    Q.EnQueue(q);
      //如果没有被访问过就压入队列
                q=getNextNeighbor(p,q);//获取下个邻接结点号
            };
        };
    };
    delete [] visited;
                 //释放标记数组的内存空间
};
/////////////////////////BFSGraphic()公有函数结束
/////////////////////////////////////////////////
//Find_Connected_Component()公有成员函数
//寻找当前图的所有的连通分量(极大连通子图)
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::Find_Connected_Component()
{
    visited=new bool[numVertices];
    //开辟标记数组的空间
    for(int i=0;i<numVertices;i++)
        visited[i]=false;
             //标记全部初始化为未被访问
    cout<<"所有连通分量顶点的集合如下:";
    cout<<endl;
    for(i=0;i<numVertices;i++)
    {
        if(visited[i]==false)
         //如果没有被访问,则可以顺次找出
        {
            DFS(i);
                   //连通分量
            cout<<endl;
        }
    };
    delete [] visited;
};
///////Find_Connected_Component()公有成员函数结束
/////////////////////////////////////////////////
//DFSTree()公有成员函数
//递归:得到当前图的深度优先生成树的算法
//其中该树采用FirstChild-NextSibling存储结束
//v是遍历起始的顶点,subTree是以v为当前顶点的生成子树
/////////////////////////////////////////////////
template<class T,class E>
TreeNode<T>* Graphlink<T,E>::DFSTree(int v)
{
    T value=getValue(v);
                 //通过结点v创建一个树的结点
    TreeNode<T>* subTree;
    subTree=new TreeNode<T>(value);
      //作为当前生成子树的根结
    visited[v]=true;
                     //当前结点v已经访问过
    int flag=1;
                          //判断是否是长子结点
    TreeNode<T>* ptr=NULL;
               //获取长子树的树根
    TreeNode<T>* pre=NULL;
               //保留前棵兄弟子树的根结点
    for(int p=getFirstNeighbor(v);
       //递归遍历v的所有未访问的邻接结点
        p!=-1;p=getNextNeighbor(v,p))
    {
                                    
        if(visited[p]==false)
            //如果邻接点p还未被访问过
        {
            ptr=DFSTree(p);
              //递归生成一棵子树
            if(flag==1)
                  //如果是长子结点
            {
                subTree->firstChild=ptr;
                flag=0;
                  //标志表示已经不是长子结点
            }
            else
                pre->nextSibling=ptr;
    //接到前面的子树的后面
            pre=ptr;
        };
    };
    return subTree;
                      //返回根结点指针
};
////////////////////////////////DFSTree()函数结束
/////////////////////////////////////////////////
//DisplayDFSTree()公有成员函数
//调用上面的DFSTree()递归函数求当前图的深度优先生成树
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::DisplayDFSTree(int v)
{
    visited=new bool[numVertices];
    for(int i=0;i<numVertices;i++)
        visited[i]=false;
    cout<<"先根遍历以"<<getValue(v)<<"为起点的深度优先生成树:";
    Tree<T> T;
             //定义一棵空树
    T.setRoot(DFSTree(v)); //设置根结点
    T.pre();
               //先根遍历该树
    cout<<endl<<"深度优先生成树是:";
    T.Display();
    cout<<endl;
    cout<<"广度优先遍历的结果是:";
    T.levelOrder();
    delete [] visited;
};
/////////////////////////DisplayDFSTree()函数结束
/////////////////////////////////////////////////
//DFSForest()公有成员函数
//如果图是非连通的,则求其深度优先生成森林
//即每个连通分量的深度优先树构成的森林
/////////////////////////////////////////////////
template<class T,class E>
TreeNode<T>* Graphlink<T,E>::DFSForest(int v)
{
    visited=new bool[numVertices];
    for(int i=0;i<numVertices;i++)
        visited[i]=false;
            //标志数组清为未访问
    TreeNode<T>* root;
               //森林的根
    TreeNode<T>* ptr;
                //游标指针
    TreeNode<T>* pre;
                //前一棵生成树树的根结点
    int flag=1;
                      //是否是森林里的第一棵树的标志
    for(int p=0;p<numVertices;p++)
   //试着以每个结点开始寻找每个连通分量
    {
                                //的深度优先生成树
        if(visited[p]==false)
        {
            ptr=DFSTree(p);
          //找出以p为根的连通分量的深度优先生成树
            if(flag==1)
              //是森林里的第一棵树
            {
                root=ptr;
            //把ptr作为森林的根
                flag=0;
            }
            else
                pre->nextSibling=ptr;//把树连接入前面已经形成的森林中
            pre=ptr;
                 //保留前棵树的根结点
        };
    };
    delete [] visited;
    return root;
};
//////////////////////////////DFSForest()函数结束
/////////////////////////////////////////////////
//getFirstUnvisit()公有成员函数
//得到p的第一个邻接的结点
/////////////////////////////////////////////////
template<class T,class E>
int Graphlink<T,E>::getFirstUnvisit(int p,bool* visited)
{
    Edge<T,E>* ptr=NodeTable[p].adj; //获得p的边链表的头指针
    while(ptr!=NULL)
                 //搜索该边链表
    {
        int des=ptr->dest;
           //获得每条边的目的结点号
        if(visited[des]==false)
      //如果第一个碰到一个未访问的
            return des;
              //返回结点号
        ptr=ptr->link;
    };
    return -1;
                       //没有找到就返回-1
};
////////////////////////getFirstUnvisit()函数结束
/////////////////////////////////////////////////
//getNextUnvisit()公有成员函数
//得到p的w之后的未访问的邻接结点号
/////////////////////////////////////////////////
template<class T,class E>
int Graphlink<T,E>::getNextUnvisit(int p,int v,bool* visited)
{
    Edge<T,E>* ptr=NodeTable[p].adj;//获得p的边链表的首指针
    int flag=0;
                     //判断是否已经找到v
    while(ptr!=NULL)
                //搜索边链表中v的指针
    {
        int des=ptr->dest;
          //获得每条边的目的结点号
        if(des==v)
                  //如果找到
        {
            flag=1;
                 //已经找到
            break;
        }
        ptr=ptr->link;
    };
    if(flag==0)
                     //边链表中连v都没有
        return -1;
    ptr=ptr->link;
                  //指向v后的第一个结点
    while(ptr!=NULL)
                //从边结点v后的第一个结点开始搜索
    {
        int des=ptr->dest;
          //搜索v后的第一个未被访问的邻接结点
        if(visited[des]==false)
            return des;
        ptr=ptr->link;
    };
    return -1;
};
/////////////////////////getNextUnvisit()函数结束
/////////////////////////////////////////////////
//DepthFirst()公有成员函数
//采用非递归的方式深度遍历当前图
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::DepthFirst(int start)
{
    visited=new bool[numVertices];
   //是否被访问过的标记
    for(int i=0;i<numVertices;i++)
        visited[i]=false;
    LinkedStack<int> Stack;
          //回溯过程中用到的堆栈
    int p=start;
                     //指向当前的结点
    int parent=-1;
                   //指向当前结点的遍历父结点
    int first;
                       //存放获取长子结点号
    int next;
                        //存放下个兄弟结点的地址
    do
    {
        cout<<getValue(p)<<" ";
                //访问当前结点p
        visited[p]=true;
                       //设置已经访问过
        first=getFirstNeighbor(p);
             //获取当前访问结点p的未访问过的第一个邻接结点号
        while(first!=-1 && visited[first]==true)
            first=getNextNeighbor(p,first);
    //继续看下个邻接结点
 
        if(first!=-1)
                          //如果不是根结点而且长子结点不空
        {
            if(p==start)
                       //如果当前访问的结点是根结点
                next=-1;
                       //则没有下个兄弟结点
            else
            {
                next=getNextNeighbor(parent,p);//寻找p之后第一个未被访问的第一个兄弟结点
                while(next!=-1 && visited[next]==true)
                    next=getNextNeighbor(parent,next);
            };
            
            if(next!=-1)
                       //如果p的下个兄弟结点存在,且不在堆栈中
            {
                Stack.Push(parent);
            //先把父结点压入堆栈
                Stack.Push(next);
              //再把该下个兄弟结点压入堆栈
            };
            parent=p;
            p=first;
                           //下个结点
        }
        else
                                   //如果长子结点是空的
        {
            if(p==start)
                       //如果就是根结点
                break;
                         //推出遍历循环
            else
            {
                do
                {
                    Stack.Pop(p);
              //从堆栈中弹出一个结点作为下个结点
                    Stack.Pop(parent);
         //从堆栈中同时获得
                }
                while(visited[p]!=false);
      //弹出的结点如果是已经访问过的,就继续弹
            };
        };
    }while(first!=-1 || !Stack.IsEmpty());
     //如果堆栈和长子结点都空了,说明遍历结束
};
/////////////////////////DepthFirst()公有函数结束
/////////////////////////////////////////////////
//友元重载<<输出运算符
/////////////////////////////////////////////////
template<class T,class E>
ostream& operator<<(ostream& os,Graphlink<T,E>& G)
{
    cout<<"当前图的内容是:"<<endl;
    Edge<T,E>* ptr;
    for(int i=0;i<G.numVertices;i++)
    {
        cout<<"第"<<i<<"个顶点"<<T(G.NodeTable[i].data)<<"边结点:";
        ptr=G.NodeTable[i].adj;
        while(ptr!=NULL)
        {
            cout<<"("<<ptr->dest<<","<<ptr->cost<<")"<<" ";
            ptr=ptr->link;
        };
        cout<<endl;
    };
    cout<<"当前图的总结点数是:"<<G.numVertices<<endl;
    cout<<"当前图的总边的个数:"<<G.numEdges<<endl;
    return os;
};
///////////////////////////////////<<友元重载结束
/////////////////////////////////////////////////
//友元重载>>输入运算符
/////////////////////////////////////////////////
template<class T,class E>
istream& operator>>(istream& is,Graphlink<T,E>& G)
{
    cout<<"通过键盘输入输入顶点和边";
    cout<<"请输入顶点的个数:";
    is>>G.numVertices;
    cout<<endl;
    for(int i=0;i<G.numVertices;i++)
    {
        cout<<"请输入第"<<i<<"个结点的数据内容:";
        is>>G.NodeTable[i].data;
    };
    cout<<"请输入边的个数:";
    is>>G.numEdges;
    cout<<endl;
    int v1,v2;
    E weight;
    for(i=0;i<G.numEdges;i++)
    {
        cout<<"输入起点:";
        is>>v1;
        cout<<"输入终点:";
        is>>v2;
        cout<<"输入权值:";
        is>>weight;
        G.insertEdge(v1,v2,weight);
        cout<<endl;
    }
    return is;
};
/////////////////////////////>>输入运算符重载结束
#endif