大连理工大学软件学院数据结构第四章第九题

/*
 思想:利用拓扑排序来找图中的环,即离散数学中的w过程,
 每次找到一条入度为零的边将其以及其所关联的边删除,
  直到删除到环的时候再也进行不下去,此时将环中的任意
  一个元素开始深度优先遍历即可。
*/

#include <iostream>
#include <queue>
using namespace std;

template<class EdgeType>
class Edge
{
public:
    int start,end;//边的起始节点,终止节点
    EdgeType weight;//边的权重(应该可以定义为int)
    Edge()
    {
       start=0;
        end=0;
        weight=0;
    }
    Edge(int st,int en,int w)
    {
        start=st;
        end=en;
        weight=w;
    }
    bool operator > (Edge oneEdge)
    {
        if(weight>oneEdge.weight)
            return true;
        else
            return false;
    }
    bool operator < (Edge oneEdge)
    {
        if(weight<oneEdge.weight)
            return true;
        else
            return false;
    }
};

template<class EdgeType>
class Graph
{
    public:
    int vertexNum; //图中节点个数
    int edgeNum;   //图中边的个数
    int * Mark;    //标记某节点是否被访问
    Graph(int verNum)
    {
        this->vertexNum=verNum;
        edgeNum=0;
        Mark=new int[vertexNum];
        for(int i=0;i<vertexNum;i++)
        {
            Mark[i]=0; //都没有被访问过
        }
    }
    ~Graph()
    {
        delete [] Mark;
    }
    //virtual Edge<EdgeType> FirstEdge(int oneVertex)=0;
    //virtual Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)=0;
    int verticesNum()
    {
        return vertexNum;
    }
    int EdgesNum()
    {
        return edgeNum;
    }
    bool isEdge(Edge<EdgeType> oneEdge)
    {
        if(oneEdge.end>=0 && oneEdge.start>=0 && oneEdge.weight>0 && oneEdge.start!=oneEdge.end)//判断条件还不清楚
        {
            return true;
        }
        else
        {
          return false;
        }
    }
    int startOfVertex(Edge<EdgeType> oneEdge)
    {
        return oneEdge.start;
    }
    int endOfVertex(Edge<EdgeType> oneEdge)
    {
        return oneEdge.end;
    }
    EdgeType weight(Edge<EdgeType> oneEdge) //返回oneEdge的权重
    {
        return oneEdge.weight;
    }
    //virtual void setEdge(int start,int end,int weight)=0;
    //virtual void deleteEdge(int start,int end)=0;
};

template<class EdgeType>
class AdjGraph : public Graph<EdgeType >
{
 private:
    int ** matrix;
 public:
    AdjGraph(int verNum):Graph<EdgeType>(verNum)
    {
        matrix =new int * [verNum];
        for(int i=0;i<verNum;i++)
        {
            matrix[i]=new int [verNum];
        }
        for(int i=0;i<verNum;i++)
          for(int j=0;j<verNum;j++)
        {
            matrix[i][j]=999;
        }
    }

    AdjGraph(int verNum,int **  a):Graph<EdgeType>(verNum)
    {
        matrix =new int * [verNum];
        for(int i=0;i<verNum;i++)
        {
            matrix[i]=new int [verNum];
        }
        for(int i=0;i<verNum;i++)
          for(int j=0;j<verNum;j++)
          {

            matrix[i][j]=a[i][j];
          }
    }

    EdgeType getIJ(int i,int j)
    {
        if(i<this->vertexNum && i>=0 && j<this->vertexNum && j>=0)
        return matrix[i][j];
        else
        {
            cout<<"邻接矩阵越界"<<endl;
            return 0;
        }

    }
    int EdgesNum()
    {
        int edgeNum=0;
        for(int i=0;i<this->vertexNum;i++)
        {
            for(int j=0;j<this->vertexNum;j++)
                if(matrix[i][j]<999)
                    edgeNum++;
        }
        this->edgeNum=edgeNum;
        return edgeNum;
    }
    void disp()
    {
        cout<<endl;
        cout<<"此图的领接矩阵为"<<endl;
        for(int i=0;i<this->vertexNum;i++)
        {
           for(int j=0;j<this->vertexNum;j++)
           {
             cout<<matrix[i][j]<<" ";
           }
            cout<<endl;
         }
    }
    ~AdjGraph()
    {
        for(int i=0;i<this->vertexNum;i++)
        {
            matrix[i]=new int [this->vertexNum];
        }
        delete [] matrix;
    }
    Edge<EdgeType> FirstEdge(int oneVer) //返回顶点的第一条边
    {
        Edge<EdgeType> tem;
        tem.start=oneVer;
        for(int i=0;i<this->vertexNum;i++)
        {
            if(matrix[oneVer][i]<999)
            {
                tem.end=i;
                tem.weight=matrix[oneVer][i];
                return tem;
                //break;
            }
        }
        tem.weight=-1;
        tem.end=tem.start=0;
        //cout<<"没有符合条件的边"<<endl;
        return tem;
    }
    Edge<EdgeType> NextEdge(Edge<EdgeType> oneEdge)//返回与oneEdg有相同起点的下一条边
    {
        Edge<EdgeType> tem;
        tem.start=oneEdge.start;
        for(int i=oneEdge.end+1;i<this->vertexNum;i++)
        {
              if(matrix[oneEdge.start][i]<999)
              {
                 tem.end=i;
                 tem.weight=matrix[oneEdge.start][i];
                 return tem;
              }
        }
        tem.weight=-1;
        //cout<<"没有符合条件的边"<<endl;
        return tem;
    }
    void visit(int i)
    {
        cout<<i<<" ";
    }

    //深度优先搜索
    void DFS(int i)//从i号节点开始深度优先搜索
    {
        this->Mark[i]=1;
        //cout<<"zhe次从这里开始深度遍历"<<i<<endl;
        visit(i);
        for(Edge<EdgeType> e=FirstEdge(i);this->isEdge(e);e=NextEdge(e))
        {
             if(this->Mark[e.end]==0)
             {
                 //cout<<"下次从这里开始深度遍历"<<e.end<<endl;
               DFS(e.end);
             }
        }

    }
    void DFSGraph()//对图进行深度优先搜索
    {
        for(int i=0;i<this->vertexNum;i++)
        this->Mark[i]=0;  //标记都未访问
        for(int i=0;i<this->vertexNum;i++)
        {
            if(this->Mark[i]==0)
            {
                DFS(i);
            }
        }

    }
    //广度优先搜索
    void BFS(int i)//从i号节点开始广度优先搜索
    {
        queue<int> que;
        que.push(i);
        visit(i);
        this->Mark[i]=1;
        int p;
        while(!que.empty())
        {
            p=que.front();
            que.pop();
            this->Mark[p]=1;
            for(Edge<EdgeType> e=FirstEdge(p);this->isEdge(e);e=NextEdge(e))
            {
                if(this->Mark[e.end]==0)
                {//此处要注意,在节点入队时候就要将Mark置为已访问,否则可能会导致同一节点多次入队
                  visit(e.end);
                  this->Mark[e.end]=1;
                  que.push(e.end);
                }
            }
        }
    }

    void BFSGraph()//对图进行广度优先搜索
    {
        for(int i=0;i<this->vertexNum;i++)
        this->Mark[i]=0;  //标记都未访问
        for(int i=0;i<this->vertexNum;i++)
        {
            if(this->Mark[i]==0)
            {
                BFS(i);
            }
        }
       cout<<endl;
    }

};

//拓扑排序,判断图中是否有环,并输出一个环
template<class EdgeType>
void TopuSortJudeIsExitCricle(AdjGraph<EdgeType>& G,int * SortArray)//从S出发生成最短路径
{
        int n=G.verticesNum();
        int * inderGree= new int [n];
        for(int i=0;i<n;i++)
        {
            G.Mark[i]=0;
            inderGree[i]=0;
            SortArray[i]=-1;
        }

        for(int i=0;i<n;i++)
        {
          for(Edge<EdgeType> e = G.FirstEdge(i);G.isEdge(e);e=G.NextEdge(e))
          {
             //cout<<"e的开头"<<e.start<<endl;
             //cout<<"e的结尾"<<e.end<<endl;
             inderGree[e.end]++;
          }
         }
         cout<<"inder数组"<<endl;
         for(int j=0;j<n;j++)
         {
             cout<<inderGree[j]<<" ";
         }
         cout<<endl;
        for(int i=0;i<n;i++)
        {
            int v;
            for(v=0;v<n;v++)
            {
                if(inderGree[v]==0 && G.Mark[v]==0)
                {
                    cout<<"入度为零的点为"<<v<<endl;
                    break;
                }
            }
            if(v==n)
            {
                cout<<"图中存在环"<<endl;
                cout<<"此时的mark数组"<<endl;
                for(int j=0;j<n;j++)
                {
                    cout<<G.Mark[j]<<" ";
                }
                cout<<endl;
                for(int j=0;j<n;j++)
                {
                    if(G.Mark[j]==0)
                    {
                        cout<<"环从这里开始"<<j<<endl;
                        G.DFS(j);
                        cout<<endl;
                        return;
                    }
                }
            }

            G.Mark[v]=1;
            SortArray[i]=v;

            for(Edge<EdgeType> e = G.FirstEdge(v);G.isEdge(e);e=G.NextEdge(e))
            {
              inderGree[e.end]--;
            }
        }
            delete [] inderGree;
}


int main()
{
    //课本p170的图
    int tem[6][6]={
        {999,  1,  1,  1,  1,  1},
        {999,999,1  ,999,999,999},
        {999,999,999,999,1  ,999},
        {999,999,1  ,999,999,999},
        {999,999,999,1  ,999,999},
        {999,999,999,999,1  ,999},
    };
    int n=6;
    int ** a=new int *[n];
    for(int i=0;i<n;i++)
    {
        a[i]=new int [n];
    }
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++)
    {
        a[i][j]=tem[i][j];
    }

    AdjGraph<int> p(n,a);
    p.disp();
    cout<<"深度优先搜索"<<endl;
    p.DFSGraph();
    cout<<endl;
    cout<<"广度优先搜索"<<endl;
    p.BFSGraph();

    int sortArray[n];
    TopuSortJudeIsExitCricle(p,sortArray);
    cout<<"拓扑序列为"<<endl;
    for(int i=0;i<n;i++)
    {
        if(sortArray[i]>0)
        cout<<sortArray[i]<<" ";
    }

    cout<<endl;
    return 0;
}

已标记关键词 清除标记
相关推荐
数据结构 1800》 第一 绪论 一、选择 1. 算法的计算量的大小称为计算的(B )。【北京邮电大学2000 二、3 (20/8分)】 A.效率 B. 复杂性 C. 现实性 D. 难度 2. 算法的时间复杂度取决于(C )【中科院计算所 1998 二、1 (2分)】 A.问的规模 B. 待处理数据的初态 C. A和 B 3.计算机算法指的是(C),它必须具备(B) 这三个特性。 (1) A.计算方法 B. 排序方法 C. 解决问的步骤序列 D. 调度方法 (2) A.可执行性、可移植性、可扩充性 B. 可执行性、确定性、有穷性 C. 确定性、有穷性、稳定性 D. 易读性、稳定性、安全性 【南京理工大学 1999 一、1(2分) 【武汉交通科技大学 1996 一、1( 4分)】 4.一个算法应该是( B )。【中山大学 1998 二、1(2分)】 A.程序 B.问求解步骤的描述 C.要满足五个基本特性 D.A和 C. 5. 下面关于算法说法错误的是(D )【南京理工大学 2000 一、1(1.5分)】 A.算法最终必须由计算机程序实现 B.为解决某问的算法同为该问编写的程序含义是相同的 C. 算法的可行性是指指令不能有二义性 D. 以上几个都是错误的 6. 下面说法错误的是(C )【南京理工大学 2000 一、2 (1.5分)】 (1)算法原地工作的含义是指不需要任何额外的辅助空间 (2)在相同的规模 n下,复杂度O(n)的算法在时间上总是优于复杂度 O(2 n)的算法 (3)所谓时间复杂度是指最坏情况下,估算算法执行时间的一个上界 (4)同一个算法,实现语言的级别越高,执行效率就越低 A.(1) B.(1),(2) C.(1),(4) D.(3) 7.从逻辑上可以把数据结构分为(C )两大类。【武汉交通科技大学 1996 一 、4(2分)】 A.动态结构、静态结构 B.顺序结构、链式结构 C.线性结构、非线性结构 D.初等结构、构造型结构 8.以下与数据的存储结构无关的术语是(D )。【北方交通大学 2000 二、1(2分)】 A.循环队列 B. 链表 C. 哈希表 D. 栈 9.以下数据结构中,哪一个是线性结构(D)?【北方交通大学 2001 一、1(2分)】 A.广义表 B. 二叉树 C. 稀疏矩阵 D. 串 10.以下那一个术语与数据的存储结构无关?(A )【北方交通大学 2001 一、2(2分)】 A.栈 B. 哈希表 C. 线索树 D. 双向链表 11.在下面的程序段中,对 x的赋值语句的频度为(C )【北京工商大学 2001 一、10(3分)】 FOR i:=1 TO n DO FOR j:=1 TO n DO x:=x+1; A. O(2n) B.O(n) C.O(n2) D.O(log2n) 12.程序段 FOR i:=n-1 DOWNTO 1 DO FOR j:=1 TO i DO IF A[j]>A[j+1] THEN A[j]与A[j+1]对换; 其中 n为正整数,则最后一行的语句频度在最坏情况下是(D ) 郴州都市网 www.0735.cc郴州人才网 www.CZHR.com www.989.org 《数据结构 1800》 A. O(n) B. O(nlogn) C. O(n3) D. O(n2) 【南京理工大学 1998一、1(2分)】 13.以下哪个数据结构不是多型数据类型(D )【中山大学 1999 一、3(1分)】 A.栈 B.广义表 C.有向图 D.字符串 14.以下数据结构中,(A )是非线性数据结构【中山大学 1999 一、4】 A.树 B.字符串 C.队 D.栈 15. 下列数据中,(C )是非线性数据结构。【北京理工大学 2001 六、1(2分)】 A.栈 B. 队列 C. 完全二叉树 D. 堆 16.连续存储设计时,存储单元的地址(A )。【中山大学 1999 一、1(1分)】 A.一定连续 B.一定不连续 C.不一定连续 D.部分连续,部分不连续 17.以下属于逻辑结构的是(C )。【西安电子科技大学应用 2001一、1】 A.顺序表 B. 哈希表 C.有序表 D. 单链表 二、判断 1. 数据元素是数据的最小单位。( ) 【北京邮电大学 1998 一、1(2分)】【青岛大学 2000 一、1 (1分)】 【上海交通大学 1998 一、1】 【山东师范大学 2001 一、1 (2分)】 2. 记录是数据处理的最小单位。 ( ) 【上海海运学院 1998 一、5(1分)】 3. 数据的逻辑结构是指数据的各数据项之间
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页