| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3508 人关注过本帖, 2 人收藏
标题:再发邻接表实现的带权无向图的抽象数据类型,及其相关算法的实现,(oop)大家多 ...
只看楼主 加入收藏
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()公有函数结束
2008-12-07 20:31
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//Dijkstra()公有成员函数,Dijkstra求最短路径的算法
//求当前图中从结点v出发到其它所有顶点的路径长度
//T是关键码的数据类型,E是路径长度的数据类型
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::Dijkstra(int v)
{
    /*初始化工作*/
    int n=numVertices;         //图的当前顶点的个数
    E* dist=new E[n];          //定义存放最短路径长度的数组
    Path=new int[n];           //开辟最短路径数组的空间
    for(int i=0;i<n;i++)
        dist[i]=maxWeight;
    bool* s=new bool[n];       //当前已经求出最短路径的顶点集合
    for(i=0;i<n;i++)
        s[i]=false;            //初始并未全部加入
    if(v>=n)                   //如果开始的结点号溢出
        return;
    for(i=0;i<=n-1;i++)        //对dist[]数组进行初始化
    {
        dist[i]=getWeight(v,i);//把所有开始与v相邻接的边的长度加入dist[]
        if(dist[i]<maxWeight
            && dist[i]!=0)     //把当前处理的顶点的前驱顶点放入Path[]数组   
            Path[i]=v;
        else
            Path[i]=-1;
    }
    s[v]=true;                 //先把结点v加入到集合中去
    dist[v]=0;
    /*依次把图中其他
    的结点加入s求
    出他它们的最短
    路径*/
    int count=1;
    int min;                   //求当前dist[]数组中的最小值
    int k;                     //存放当前从dist[]找出的最小值的标号
    for(int p=1;p<=n-1;p++)    //一共有n-1个顶点要陆续加入到s中
    {
        int isfirst=1;
        /*找要加入s的结点即
        当dist[]中权最小点*/
        for(i=0;i<=n-1;i++)    //遍历dist[]数组
        {
            if(s[i]!=true
                && isfirst==1) //如果结点i还没有加进s
            {
                min=dist[i];
                k=i;
                isfirst=0;
                continue;
            };
            if(s[i]!=true && dist[i]<min)
            {
                min=dist[i];   //找权值最小的及其标号
                k=i;
            };
        };
        s[k]=true;             //把找到的k加入到s中去
        /*修改dist[]数组的值*/
        for(i=0;i<=n-1;i++)
        {
            if(s[i]!=true)     //如果结点i还没有被加入s
            {                  //则需要被修改
                if(dist[i]>dist[k]+getWeight(k,i))
                {
                    dist[i]=dist[k]+getWeight(k,i);
                    Path[i]=k; //把顶点i的当前最短路径上的前驱加入Path[]中
                };
            };
        };
    };
    /*显示生成的每条最短路径*/
    DisplayPath(v,dist);
    /*释放辅助的存储空间*/
    delete [] dist;
    delete [] Path;
};
/////////////////////////////////Dijkstra()函数结束

///////////////////////////////////////////////////
//DisplayPath()公有成员函数
//显示当前图的从定点v到其他定点的所有最短路径
//即把当前Path数组中的最短路径显示出来
///////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::DisplayPath(int v,E* d)
{
    int n=numVertices;
    for(int i=0;i<n;i++)       //遍历除v以外的所有的定点
    {
        if(i!=v)               //显示从v到i的最短路径
        {
            cout<<"从"<<i<<"到"<<v<<"的最短路径:";
            cout<<"其长度是:"<<d[i]<<';'<<"路径是:";
            int p=i;           //游标指针从v开始
            cout<<'{'<<p<<"<-";
            do
            {
                cout<<Path[p]; //显示 最短路径的前驱
                p=Path[p];
                if(p!=v)
                    cout<<"<-";//路径上的最后一个结点不需要显示','
            }while(p!=v);      //到i表示循环结束
            cout<<'}';
        };
        cout<<endl;
    };
};
////////////////////////////DisplayPath()函数结束
2008-12-07 20:32
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//友元重载<<输出运算符
/////////////////////////////////////////////////
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;
};
///////////////////////////////////<<友元重载结束
2008-12-07 20:32
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//友元重载>>输入运算符
/////////////////////////////////////////////////
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;
};
/////////////////////////////>>输入运算符重载结束
2008-12-07 20:33
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//DFSArticul()公有成员函数
//递归:从v0出发,通过深度优先遍历当前图,
//查找并输出该深度优先生成树上的所有关节点
//算法描述概要:定义了dfn[]函数,存放结点的DFS遍历
//序数,low[]函数存放通过,当前结点可以
/////////////////////////////////////////////////
template<class T,class E>
int Graphlink<T,E>::DFSArticul(int v0,int* dfn,int* low)
{
    static int count=0;        //得到DFS序数的计数器
    count++;                  
    int min=count;             //当前访问的结点v0的DFS序数
    dfn[v0]=count;             //得到当前访问顶点的DFS序数
    for(int ptr=getFirstNeighbor(v0)  
        ;ptr!=-1               //遍历结点v0所有的邻接结点
        ;ptr=getNextNeighbor(v0,ptr))
    {
        int w=ptr;             //w是v0的邻接结点,w也是v0的子结点
        if(dfn[w]==0)          //如果v0的子结点w没有被访问过
        {
            DFSArticul(        //递归:对以w为开始顶点的子图进行递归求关节点
                w,dfn,low);
            if(low[w]<min)     //退出递归以后,如果子结点u能达到的顶点DFS序数比
                min=low[w];    //比v0能达到的更小
            if(low[w]>=dfn[v0])//如果子结点u所能到达的顶点的DFS序数还没有v0大
                cout<<v0<<":"  //说明v0就是一个关节点
                <<getValue(v0)
                <<"是一个关节点."<<endl;
        }
        else if(dfn[w]<min)    //如果w的DFS序数比当前v0的最小回边系数更小
            min=dfn[w];        //说明w已经在v0之前访问过了<v0,w>是一条回边
    }
    low[v0]=min;               //得到当前结点v0的low[]函数值
    return count;              //返回当前遍历过的顶点的个数
};
/////////////////////DFSArticul()公有成员函数结束

/////////////////////////////////////////////////
//FindArticul()公有成员函数
//调用DFSArticul()函数找出当前图的
//所有的关节点,并显示出来,思想:首先判断根结点
//是否有多于一个子树,如果是说明根也是关节点,然后
//以根的每棵子树根结点为起点继续找关节点
/////////////////////////////////////////////////
template<class T,class E>
void Graphlink<T,E>::FindArticul()
{
    int n=numVertices;
    int* dfn=new int[n];        //dfn[]函数的数组
    int* low=new int[n];        //low[]函数的数组
    for(int i=0;i<n;i++)        //初始化dfn[]函数
        dfn[i]=0;
    dfn[0]=1;                   //以0号顶点为遍历的根结点
    int p=getFirstNeighbor(0);  //获取根结点0的第一个子结点
    int k=DFSArticul(p,dfn,low);//对第一棵子树进行寻找,得到第一棵子树顶点个数
    if(k!=n-1)                  //如果顶点个数不是总顶点数-1
    {                           //怎说明根结点是关节点
        cout<<0<<":"<<getValue(0)
            <<"是一个关节点."<<endl;
        p=getNextNeighbor(0,p); //获得子树p的兄弟子树
        while(p!=-1)            //对其他的子树进行再次的关节点寻找
        {
            if(dfn[p]==0)       //如果p还没有被访问过,就从该顶点开始寻找
                DFSArticul(p,dfn,low);
            p=getNextNeighbor(0,p);
        };
    };
};
////////////////////////////FindArticul()函数结束

#endif
2008-12-07 20:33
xihuazhoujin
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-6-6
收藏
得分:0 
请问老师能否把#include"BaseGraph.h"的内容写出来么???还有,设计一个主函数能否??
谢谢!!
2010-06-06 22:54
快速回复:再发邻接表实现的带权无向图的抽象数据类型,及其相关算法的实现,(oop) ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.053357 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved