数据结构第6章课后习题答案(下)

简介: 数据结构第6章课后习题答案(下)

(5)试对图6.36所示的AOE-网:

① 求这个工程最早可能在什么时间结束;    

② 求每个活动的最早开始时间和最迟开始时间;

③ 确定哪些活动是关键活动

图6.36  AOE-网

答案:按拓扑有序的顺序计算各个顶点的最早可能开始时间Ve和最迟允许开始时间Vl。然后再计算各个活动的最早可能开始时间e和最迟允许开始时间l,根据l - e = 0? 来确定关键活动,从而确定关键路径。

¸

·

 4 ¹

º

»

Ve

0

19

15

29

38

43

Vl

0

19

15

37

38

43

<1, 2>

<1, 3>

<3, 2>

<2, 4>

<2, 5>

<3, 5>

<4, 6>

<5, 6>

e

0

0

15

19

19

15

29

38

l

17

0

15

27

19

27

37

38

-e

17

0

0

8

0

12

8

0

此工程最早完成时间为43。关键路径为<1, 3><3, 2><2, 5><5, 6>

3.算法设计

1)分别以邻接矩阵和邻接表作为存储结构,实现以下图的基本操作:

① 增加一个新顶点v,InsertVex(G, v);

② 删除顶点v及其相关的边,DeleteVex(G, v);

③ 增加一条边<v,w>,InsertArc(G, v, w);

④ 删除一条边<v,w>,DeleteArc(G, v, w)。

[算法描述]

假设图G为有向无权图,以邻接矩阵作为存储结构四个算法分别如下:

① 增加一个新顶点v

Status Insert_Vex(MGraph &G, char v)//在邻接矩阵表示的图G上插入顶点v

{

if(G.vexnum+1)>MAX_VERTEX_NUM return INFEASIBLE;

G.vexs[++G.vexnum]=v;

return OK;

}//Insert_Vex

② 删除顶点v及其相关的边,

Status Delete_Vex(MGraph &G,char v)//在邻接矩阵表示的图G上删除顶点v

{

n=G.vexnum;

if((m=LocateVex(G,v))<0) return ERROR;

G.vexs[m]<->G.vexs[n]; //将待删除顶点交换到最后一个顶点

for(i=0;i<n;i++)

{

G.arcs[m]=G.arcs[n];

G.arcs[m]=G.arcs[n]; //将边的关系随之交换

}

G.arcs[m][m].adj=0;

G.vexnum--;

return OK;

}//Delete_Vex

分析:如果不把待删除顶点交换到最后一个顶点的话,算法将会比较复杂,而伴随着大量元素的移动,时间复杂度也会大大增加。

③ 增加一条边<v,w>

Status Insert_Arc(MGraph &G,char v,char w)//在邻接矩阵表示的图G上插入边(v,w)

{

if((i=LocateVex(G,v))<0) return ERROR;

if((j=LocateVex(G,w))<0) return ERROR;

if(i==j) return ERROR;

if(!G.arcs[j].adj)

{

G.arcs[j].adj=1;

G.arcnum++;

}

return OK;

}//Insert_Arc

④ 删除一条边<v,w>

Status Delete_Arc(MGraph &G,char v,char w)//在邻接矩阵表示的图G上删除边(v,w)

{

if((i=LocateVex(G,v))<0) return ERROR;

if((j=LocateVex(G,w))<0) return ERROR;

if(G.arcs[j].adj)

{

G.arcs[j].adj=0;

G.arcnum--;

}

return OK;

}//Delete_Arc

以邻接表作为存储结构,本题只给出Insert_Arc算法.其余算法类似。

Status Insert_Arc(ALGraph &G,char v,char w)//在邻接表表示的图G上插入边(v,w)

{

if((i=LocateVex(G,v))<0) return ERROR;

if((j=LocateVex(G,w))<0) return ERROR;

p=new ArcNode;

p->adjvex=j;p->nextarc=NULL;

if(!G.vertices.firstarc) G.vertices.firstarc=p;

else

{

for(q=G.vertices.firstarc;q->q->nextarc;q=q->nextarc)

if(q->adjvex==j) return ERROR; //边已经存在

q->nextarc=p;

}

G.arcnum++;

return OK;

}//Insert_Arc

2一个连通图采用邻接表作为存储结构,设计一个算法,实现从顶点v出发的深度优先遍历的非递归过程。

[算法描述]

Void DFSn(Graph G,int v)

{  //从第v个顶点出发非递归实现深度优先遍历图G

Stack s;

SetEmpty(s);

Push(s,v);

While(!StackEmpty(s))

{       //栈空时第v个顶点所在的连通分量已遍历完

Pop(s,k);

If(!visited[k])

{        visited[k]=TRUE;

VisitFunc(k);          //访问第k个顶点

//将第k个顶点的所有邻接点进栈

for(w=FirstAdjVex(G,k);w;w=NextAdjVex(G,k,w))

{      

if(!visited[w]&&w!=GetTop(s)) Push(s,w);    //图中有环时w==GetTop(s)

}

             }

    }

3设计一个算法,求图G中距离顶点v的最短路径长度最大的一个顶点,设v可达其余各个顶点。

[题目分析]

利用Dijkstra算法求v0到其它所有顶点的最短路径,分别保存在数组D[i]中,然后求出D[i]中值最大的数组下标m即可。

[算法描述]

int ShortestPath_MAX(AMGraph G, int v0){

   //Dijkstra算法求距离顶点v0的最短路径长度最大的一个顶点m

   n=G.vexnum;                                   //nG中顶点的个数

   for(v = 0; v<n; ++v){                     //n个顶点依次初始化

      S[v] = false;                                 //S初始为空集

      D[v] = G.arcs[v0][v];                 //v0到各个终点的最短路径长度初始化

      if(D[v]< MaxInt)  Path [v]=v0;          //如果v0v之间有弧,则将v的前驱置为v0

      else Path [v]=-1;                      //如果v0v之间无弧,则将v的前驱置为-1

     }//for

     S[v0]=true;                                   //v0加入S

     D[v0]=0;                                    //源点到源点的距离为0

     /*开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S*/

     for(i=1;i<n; ++i){                    //对其余n−1个顶点,依次进行计算

       min= MaxInt;

       for(w=0;w<n; ++w)

         if(!S[w]&&D[w]<min)  

             {v=w; min=D[w];}                 //选择一条当前的最短路径,终点为v

       S[v]=true;                                  //v加入S

       for(w=0;w<n; ++w)                       //更新从v0V−S上所有顶点的最短路径长度

       if(!S[w]&&(D[v]+G.arcs[v][w]<D[w])){

            D[w]=D[v]+G.arcs[v][w];     //更新D[w]

            Path [w]=v;                          //更改w的前驱为v

       }//if

   }//for

/*最短路径求解完毕,设距离顶点v0的最短路径长度最大的一个顶点为m */      

Max=D[0];

m=0;

for(i=1;i<n;i++)

if(Max<D[i]) m=i;          

return m;

}

4试基于图的深度优先搜索策略写一算法,判别以邻接表方式存储的有向图中是否存在由顶点vi到顶点vj的路径(i≠j)。

[题目分析]

引入一变量level来控制递归进行的层数

[算法描述]

int visited[MAXSIZE]; //指示顶点是否在当前路径上

int level1;//递归进行的层数

int exist_path_DFS(ALGraph G,int i,int j)//深度优先判断有向图G中顶点i到顶点j

是否有路径,是则返回1,否则返回0

{

 if(i==j) return 1; //i就是j

 else

 {

   visited[i]=1;

   for(p=G.vertices[i].firstarc;p;p=p->nextarclevel--)

   { level++;

     k=p->adjvex;

     if(!visited[k]&&exist_path(k,j)) return 1;//i下游的顶点到j有路径

}//for

 }//else

if (level==1)  return 0;

}//exist_path_DFS

5采用邻接表存储结构,编写一个算法,判别无向图中任意给定的两个顶点之间是否存在一条长度为为k的简单路径。

[算法描述]

int visited[MAXSIZE];

int exist_path_len(ALGraph G,int i,int j,int k)

//判断邻接表方式存储的有向图G的顶点ij是否存在长度为k的简单路径

{if(i==j&&k==0) return 1; //找到了一条路径,且长度符合要求

else if(k>0)

 {visited[i]=1;

  for(p=G.vertices[i].firstarc;p;p=p->nextarc)

   {l=p->adjvex;

    if(!visited[l])

       if(exist_path_len(G,l,j,k-1)) return 1; //剩余路径长度减一

   }//for

  visited[i]=0; //本题允许曾经被访问过的结点出现在另一条路径中

 }//else

return 0; //没找到

}//exist_path_len

目录
相关文章
|
10月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
466 77
|
10月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
324 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
10月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
389 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
10月前
|
算法 C++
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】 目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现二叉排序树的基本算法。 相关知识 为了完成本关任务,你需要掌握:二叉树的创建、查找和删除算法。具体如下: (1)由关键字序列(4,9,0,1,8,6,3,5,2,7)创建一棵二叉排序树bt并以括号表示法输出。 (2)判断bt是否为一棵二叉排序树。 (3)采用递归方法查找关键字为6的结点,并输出其查找路径。 (4)分别删除bt中关键
264 11
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
|
10月前
|
存储 人工智能 算法
【C++数据结构——图】最短路径(头歌教学实验平台习题) 【合集】
任务描述 本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。 相关知识 为了完成本关任务,你需要掌握:Dijkst本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。为了完成本关任务,你需要掌握:Dijkstra算法。带权有向图:该图对应的二维数组如下所示:Dijkstra算法:Dijkstra算法是指给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径。Dijkstra算法的具体步骤如下:(1)初始时,S只包含源点,即S={v},v的距离为0。
149 15
|
10月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
273 12
|
10月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
188 10
|
10月前
|
算法 C++
【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】
【数据结构——图】最小生成树(头歌实践教学平台习题)目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:【合集】任务描述 本关任务:编写一个程序求图的最小生成树。相关知识 为了完成本关任务,你需要掌握:1.建立邻接矩阵,2.Prim算法。建立邻接矩阵 上述带权无向图对应的二维数组,根据它建立邻接矩阵,如图1建立下列邻接矩阵。注意:INF表示无穷大,表示整数:32767 intA[MAXV][MAXV];Prim算法 普里姆(Prim)算法是一种构造性算法,从候选边中挑
135 10
|
10月前
|
存储 算法 C++
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
本任务要求编写程序实现图的邻接矩阵和邻接表的存储。需掌握带权有向图、图的邻接矩阵及邻接表的概念。邻接矩阵用于表示顶点间的连接关系,邻接表则通过链表结构存储图信息。测试输入为图的顶点数、边数及邻接矩阵,预期输出为Prim算法求解结果。通关代码提供了完整的C++实现,包括输入、构建和打印邻接矩阵与邻接表的功能。
372 10
|
10月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
230 7