dhu 图 邻接表ADT实现

28 篇文章 5 订阅
6 篇文章 0 订阅

目的:使用C++模板设计并逐步完善图的邻接矩阵抽象数据类型(ADT)。

内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接矩阵ADT。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。)

(2)使用构造函数,构造一个具有结点和边的有权图。

注意:DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)

题解

不了解接口怎么写的可以参考我另一篇邻接矩阵ADT的博客

/* 边表的结点定义 */
template<class TypeOfEdge>
struct edgeNode
{
    int data;
    TypeOfEdge weight;
    edgeNode<TypeOfEdge>* next;
    edgeNode(const int& d, edgeNode<TypeOfEdge>* ptr = NULL) //构造函数,用于构造其他结点(无权图) 
    //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
    {
        next = ptr;
        data = d;
        weight = 0;
    }
    edgeNode(const int& d, const TypeOfEdge& w, edgeNode<TypeOfEdge>* ptr = NULL) //构造函数,用于构造其他结点(带权图) 
    //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
    {
        next = ptr;
        data = d;
        weight = w;
    }
    int getData() { return data; }  //取得结点的序号(顶点集) 
    TypeOfEdge getWeight() { return weight; }  //取得边集中对应边的权值 
    void SetLink(edgeNode<TypeOfEdge>* link) { next = link; }  //修改结点的next域 
    void SetData(int value) { data = value; }   //修改结点的序号(顶点集) 
    void SetWeight(TypeOfEdge value) { weight = value; }   //修改边集中对应边的权值   
};
//图的邻接表类
template<class TypeOfVer, class TypeOfEdge>
struct verNode
{
    TypeOfVer ver;
    edgeNode<TypeOfEdge>* head;
    verNode(edgeNode<TypeOfEdge>* h = NULL) { head = h;  }
    TypeOfVer getVer() { return ver; }  //取得结点值(顶点集) 
    edgeNode<TypeOfEdge>* getHead() { return head; }  //取得对应的边表的头指针 
    void setVer(TypeOfVer value) { ver = value; }  //设置结点值(顶点集) 
    void setHead(edgeNode<TypeOfEdge>* value) { head = value; }  //设置对应的边表的头指针
};
template <class TypeOfVer, class TypeOfEdge>
class adjlist_graph {
private:
    int Vers;           //顶点数 
    int Edges;          //边数 
    verNode<TypeOfVer, TypeOfEdge>* verList;
    string GraphKind;     //图的种类标志 
    bool Delete_Edge(int u, int v)
    {
        edgeNode <TypeOfEdge>* p = verList[u].head;
        while (p->next != NULL) {
            if (p->data == v) {
                break;
            }
            if (p->next == NULL)
                break;
            p = p->next;
        }
        edgeNode <TypeOfEdge>* q = verList[u].head;
        if (q!=p)
            while (q->next != p) {
                q = q->next;
            }
        q->next = p->next;
        delete p;
        return 1;
    }
    bool DFS(int u, int& num, int visited[]) //DFS遍历(递归部分)
    {
        int i = u;
        edgeNode <TypeOfEdge>* p = verList[i].head;
        while (p != NULL) {
            if (visited[p->data] == 0) {
                cout << "->" << verList[p->data].ver;
                visited[p->data] = 1;
                num++;
                DFS( p->data,num, visited);
            }
            if (p->next == NULL)
                break;
                p = p->next;
        }
        return 1;
    }
    bool w1;
public:
    void display()//测试用
    {
        for (int i = 0; i < Vers; i++) {
            cout << verList[i].ver;
            if (i != Vers - 1)
                cout << " ";
        }
        cout << endl;
        for (int i = 0; i < Vers; i++) {
            edgeNode <TypeOfEdge> * p = verList[i].head;
            cout << verList[i].ver << ":";
            while (p != NULL) {
                cout << p->data <<":"<<p->weight;
                if (p->next == NULL)
                    break;
                cout << "->";
                p = p->next;
            }
            if (i != Vers - 1)
                cout << endl;
        }
    }
    adjlist_graph(const string& kd, int vSize, const TypeOfVer d[])
    { //构造函数构造一个只有结点没有边的图。
        GraphKind = kd; Vers = vSize; w1 = 0;
        verList=new verNode<TypeOfVer,TypeOfEdge> [Vers];
            for(int i=0;i<Vers;++i)
                verList[i].ver=d[i];
    }
    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e)
    { //构造函数构造一个无权图。5个参数的含义:图的类型、结点数、边数、结点集和边集 
        GraphKind = kd; Vers = vSize; w1 = 0;
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
            verList[i].ver = d[i];
        Edges = eSize;
        for (int i = 0; i < eSize; i++) {
            edgeNode<TypeOfEdge> *p = new edgeNode<TypeOfEdge>(e[i][1]);
            if ( kd == "DG") {
                p->next = verList[e[i][0]].head;
                verList[e[i][0]].head = p;
            }
            else {
                p->next = verList[e[i][0]].head;
                verList[e[i][0]].head = p;
                edgeNode<TypeOfEdge>*q = new edgeNode<TypeOfEdge>( e[i][0]);
                q->next = verList[e[i][1]].head;
                verList[e[i][1]].head = q;
            }
        }
    }
    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e, const TypeOfEdge w[]) //构造函数构造一个有权图。
    {
        GraphKind = kd; Vers = vSize; w1 = 1;
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
            verList[i].ver = d[i];
        Edges = eSize;
        for (int i = 0; i < eSize; i++) {
            edgeNode<TypeOfEdge>* p = new edgeNode<TypeOfEdge>(e[i][1]);
            p->weight = w[i];
            if (kd == "DN") {
                p->next = verList[e[i][0]].head;
                verList[e[i][0]].head = p;
            }
            else {
                p->next = verList[e[i][0]].head;
                verList[e[i][0]].head = p;
                edgeNode<TypeOfEdge>* q = new edgeNode<TypeOfEdge>(e[i][0]);
                q->weight = w[i];
                q->next = verList[e[i][1]].head;
                verList[e[i][1]].head = q;
            }
        }
    }
    bool GraphisEmpty() { return Vers == 0; }  //判断图空否
    string GetGraphKind() { return GraphKind; }
    bool GetVer(int u, TypeOfVer& data) //取得G中指定顶点的值 
    {
        data = verList[u].ver;
        return 1;
    }
    int GetFirstAdjVex(int u, int& v) //返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1
    {
        if (u<0 || u>Vers - 1) {
            v = -1;
            return -1;
        }
        if (verList[u].head != NULL) {
            v = verList[u].head->data;
            return 1;
        }
        v = -1;
        return -1;
    }
    int GetNextAdjVex(int u, int v, int& w) //返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false
    {
        if (u<0 || u>Vers - 1) {
            v = -1;
            return -1;
        }
        edgeNode <TypeOfEdge>* p = verList[u].head;
        while (p != NULL) {
            if (p->data == v) {
                w = verList[u].head->data;
                return 1;
            }
            if (p->next == NULL)
                break;
            p = p->next;
        }
        w = -1;
        return -1;
    }
    bool PutVer(int u, TypeOfVer data) //对G中指定顶点赋值 
    {
        verList[u].ver = data;
        return 1;
    }
    bool InsertVer(const TypeOfVer& data) //往G中添加一个顶点 
    {
        verNode<TypeOfVer, TypeOfEdge>* verList2 = new verNode<TypeOfVer, TypeOfEdge>[Vers + 1];
        for (int i = 0; i < Vers; i++) {
            verList2[i] = verList[i];
            verList[i] = NULL;
        }
        verList2[Vers].ver = data;
        verList2[Vers].head = NULL;
        delete verList;
        verList = verList2;
        Vers++;
        return 1;
    }
    int LocateVer(TypeOfVer data) //返回G中指定顶点的位置 
    {
        for (int i = 0; i < Vers; i++) {
            if (verList[i].ver == data)
                return i;
        }
        return -1;
    }
    bool ExistEdge(int u, int v) //没写注释,我猜是判断边是否存在?
    {
        edgeNode <TypeOfEdge>* p = verList[u].head;
        while (p != NULL) {
            if (p->data == v)
                return 1;
            if (p->next == NULL)
                break;
            p = p->next;
        }
        p = verList[v].head;
        while (p != NULL) {
            if (p->data == u)
                return 1;
            if (p->next == NULL)
                break;
            p = p->next;
        }
        return 0;
    }
    bool PrintVer()  //输出顶点集 
    {
        for (int i = 0; i < Vers; i++) {
            cout << verList[i].ver;
            if (i != Vers - 1)
                cout << " ";
        }
        return 1;
    }
    bool PrintAdjList()  //输出邻接矩阵(?) 
    {
        if (w1 == 0)
            for (int i = 0; i < Vers; i++) {
                edgeNode <TypeOfEdge>* p = verList[i].head;
                cout << verList[i].ver << "->";
                while (p != NULL) {
                    cout << p->data << "->";
                    if (p->next == NULL)
                        break;
                    p = p->next;
                }
                cout << "nullptr";
                if (i != Vers - 1)
                    cout << endl;
            }
        else
            for (int i = 0; i < Vers; i++) {
                edgeNode <TypeOfEdge>* p = verList[i].head;
                cout << verList[i].ver << "->";
                while (p != NULL) {
                    cout << p->data <<"("<<p->weight<<")" << "->";
                    if (p->next == NULL)
                        break;
                    p = p->next;
                }
                cout << "nullptr";
                if (i != Vers - 1)
                    cout << endl;
            }
        return 1;
    }
    int GetVerNum() { return Vers; }    //取得当前顶点数 
    int GetEdgeNum() { return Edges; }  //取得当前边数 
    bool Insert_Edge(int u, int v) //无权图插入一条边
    {
        edgeNode <TypeOfEdge>* o = verList[u].head;
        while (o != NULL) {
            if (o->data == v)
                return 0;
            o = o->next;
        }
        if (GraphKind == "DG") {
            edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v);
            p->next = verList[u].head;
            verList[u].head = p;
        }
        else {
            edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v);
            p->next = verList[u].head;
            verList[u].head = p;
            edgeNode <TypeOfEdge>* q = new edgeNode <TypeOfEdge>(u);
            q->next = verList[v].head;
            verList[v].head = q;
        }
        Edges++;
        return 1;
    }
    bool Insert_Edge(int u, int v, TypeOfEdge w) //有权图插入一条边
    {
        if (GraphKind == "DG") {
            edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v,w);
            p->next = verList[u].head;
            verList[u].head = p;
        }
        else {
            edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v,w);
            p->next = verList[u].head;
            verList[u].head = p;
            edgeNode <TypeOfEdge>* q = new edgeNode <TypeOfEdge>(u,w);
            q->next = verList[v].head;
            verList[v].head = q;
        }
        Edges++;
        return 1;
    }
    bool DeleteVer(const TypeOfVer& data) //往G中删除一个顶点 
    {
        int u = LocateVer(data);
        verNode<TypeOfVer, TypeOfEdge>* verList2 = new verNode<TypeOfVer, TypeOfEdge>[Vers - 1];
        for (int i = 0, k = 0; i < Vers; i++) {
            if (i != u) {
                verList2[k] = verList[i];
                verList[i] = NULL;
                k++;
            }
        }
        delete verList;
        verList = verList2;
        Vers--;
        edgeNode <TypeOfEdge>* p = NULL;
        edgeNode <TypeOfEdge>* q = NULL;
        for (int i = 0; i < Vers; i++) {
            p = verList[i].head;
            if (p != NULL  && p->next == NULL) {
                if (p->data == u) {
                    verList[i].head == NULL;
                    delete p;
                }
                else if (p->data > u) {
                    p->data=p->data-1;
                }
                continue;
            }
            p = p->next;
            q = verList[i].head;
            while (p!=NULL) {
                if (p->data == u) {
                    q = p->next;
                    delete p;
                    p = q->next;
                }
                else if (p->data > u) {
                    p->data = p->data - 1;
                }
                if (p->next != NULL) {
                    p = p->next;
                    q = q->next;
                }
            }
            q = verList[i].head;
            if (q->data == u) {
                verList[i].head = q->next;
                delete q;
            }
            else if (q->data > u) {
                q->data = q->data - 1;
            }
        }
        return 1;
    }
    bool DeleteEdge(int u, int v) //删除边 (外壳:有向(删除1条边), 无向(删除2条边))
    {
        if (GraphKind == "DN" || GraphKind == "DG")
            Delete_Edge(u,v);
        else {
            Delete_Edge(u, v);
            Delete_Edge(v, u);
        }
        return 1;
    }
    void DFS_Traverse(int u) //DFS遍历(外壳部分)
    {
        int s[1000] = { 0 };
        cout << verList[u].ver;
        s[u] = 1;
        for (int i = u; i < Vers; i++) {
            if (s[i] != 0 && i != u) {
                continue;
            }
            s[i] = 1;
            DFS(u, i, s);
        }
        for (int i = 0; i < u; i++) {
            if (s[i] != 0) {
                continue;
            }
            s[i] = 1;
            DFS(u, i, s);
        }
        cout << endl;
    }
    void BFS_Traverse(int u) //BFS遍历
    {
        int s[1000] = { 0 };
        cout << verList[u].ver;
        s[u] = 1;
        for (int i = u; i < Vers; i++) {
            edgeNode <TypeOfEdge>* p = verList[i].head;
            if (s[i] == 0) {
                cout << "->" << verList[i].ver;
                s[i] = 1;
            }
            while (p != NULL) {
                if (s[p->data] == 0) {
                    s[p->data] = 1;
                    cout << "->" << verList[p->data].ver;
                }
                p = p->next;
            }
        }
        for (int i = 0; i < u; i++) {
            edgeNode <TypeOfEdge>* p = verList[u].head;
            if (s[i] == 0) {
                cout << "->" << verList[i].ver;
                s[i] = 1;
            }
            while (p != NULL) {
                if (s[p->data] == 0) {
                    s[p->data] = 1;
                    cout << "->" << verList[p->data].ver;
                }
                p = p->next;
            }
        }
    }
    int GetDegree(int u)
    {
        if (u < 0 || u >= Vers)
            return -1;
        int num = 0;
        edgeNode <TypeOfEdge>* p = verList[u].head;
        while (p != NULL) {
            num++;
            p = p->next;
        }
        return num;
    }
    bool GetWeight(int u, int v, int& w)
    {
        edgeNode <TypeOfEdge>* p = verList[u].head;
        while (p != NULL) {
            if (p->data == v) {
                w = p->weight;
                return 1;
            }
            if (p->next == NULL)
                break;
            p = p->next;
        }
        p = verList[v].head;
        while (p != NULL) {
            if (p->data == u) {
                w = p->weight;
                return 1;
            }
            if (p->next == NULL)
                break;
            p = p->next;
        }
        return 0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值