| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3502 人关注过本帖, 2 人收藏
标题:再发邻接表实现的带权无向图的抽象数据类型,及其相关算法的实现,(oop)大家多 ...
只看楼主 加入收藏
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
结帖率:100%
收藏(2)
 问题点数:0 回复次数:25 
再发邻接表实现的带权无向图的抽象数据类型,及其相关算法的实现,(oop)大家多探讨:
涉及到的成员函数实现的算法在类的声明中已经详细列出了,大家参考,这里基本涉及到了我们常见的无向图的所有算法:
#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是起始结点
    int* Path;                              //用于存放最短路径的辅助数组
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);                   //非递归深度优先遍历当前图
    void Dijkstra(int v);                         //求v到其他顶点的最短路径
    void DisplayPath(int v,E* d);                 //显示当前图中从顶点v到其他所有顶点的最短路径
    int DFSArticul(int v0,int* dfn,int* low);     //递归:从顶点v0出发DFS当前图,查找并输出关节点
    void FindArticul();                           //找出当前图中所有的关节点

    //友元重载输出运算符
    friend ostream& operator<<(ostream& os,Graphlink<T,E>& G);
    //友元重载输入运算符
    friend istream& operator>>(istream& is,Graphlink<T,E>& G);
};
/////////////////////Graphlink<T,E>类模板声明结束
搜索更多相关主题的帖子: oop 算法 类型 数据 探讨 
2008-12-07 20:24
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//默认构造函数
/////////////////////////////////////////////////
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;
};
/////////////////////////////////默认构造函数结束
2008-12-07 20:25
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//析构函数
//释放所有的边链表的内存以及结点数组的内存
/////////////////////////////////////////////////
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;                 //释放结点内存
        };
    };
};
/////////////////////////////////////析构函数结束
2008-12-07 20:25
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()公有成员函数结束
2008-12-07 20:26
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()函数结束
2008-12-07 20:26
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()函数结束
2008-12-07 20:26
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()公有成员函数结束
2008-12-07 20:27
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()函数结束
2008-12-07 20:27
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()函数结束
2008-12-07 20:27
geninsf009
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:613
专家分:95
注 册:2008-8-16
收藏
得分:0 
/////////////////////////////////////////////////
//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()函数结束
2008-12-07 20:28
快速回复:再发邻接表实现的带权无向图的抽象数据类型,及其相关算法的实现,(oop) ...
数据加载中...
 
   



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

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