数据结构第8章-图

数据结构第8章-图
数据结构第8章-图

第8章图

一、复习要点

图是一种重要的非线性结构。它的特点是每一个顶点都可以与其它顶点相关联,与树不同,图中各个顶点的地位都是平等的,对顶点的编号都是人为的。通常,定义图由两个集合构成:一个是顶点的非空有穷集合,一个是顶点与顶点之间关系(边)的有穷集合。对图的处理要区分有向图与无向图。它的存储表示可以使用邻接矩阵,可以使用邻接表,前者属顺序表示,后者属链接表示。在本章着重讨论了图的深度优先搜索和广度优先搜索算法,附带引入了生成树与生成森林的概念。对于带权图,给出了最小生成树的两种方法:Prim算法和Kruskal算法,后者使用了最小堆和并查集作为它的辅助求解手段。在解决最短路径问题时,采用了逐步求解的策略。最后讨论了作工程计划时常用的活动网络。涉及的主要概念是拓扑排序和关键路径,在解决应用问题时它们十分有用。

本章复习的要点是:

1、基本知识点

主要要求理解图的基本概念,包括图的定义、图的连通性、图的路径和路径长度、图中各顶点的度及度的度量、无向连通图的最大边数和最小边数,有向强连通图的最大边数与最小边数等。掌握图的存储表示,包括邻接矩阵和邻接表,以及这些存储表示上的典型操作,如构造、求根、找第一个邻接顶点、找下一个邻接顶点等操作的实现算法。并要求掌握图的两种遍历算法:深度优先搜索和广度优先搜索算法,以及求解连通性问题的方法。理解求解关节点及构造重连通图的方法。此外,要求掌握构造最小生成树的Prim算法和Kruskal方法,掌握活动网络的拓扑排序算法,掌握求解关键路径的方法。需要注意的是,让某个关键活动提前完成,是否能让整个工程提前完成。

2、算法设计

建立无向带权图的邻接表的算法,要求输入边的数目随机而定。

图的深度优先搜索的递归算法。

利用图的深度优先搜索的递归算法建立图的深度优先生成森林(用左子女右兄弟表示)的算法。

图的广度优先搜索算法。

利用图的广度优先搜索算法建立图的广度优先生成森林(用左子女右兄弟表示)的算法。

求解最小生成树的Prim算法,注意nearvex和lowcost辅助数组的变化。

求解最小生成树的Kruskal算法,注意minheap和UFset的变化。

求解最短路径的dijkstra算法,注意dist辅助数组的变化。

有向图中求解拓扑排序的算法,要求用邻接表作为图的存储表示。注意算法执行过程中入度为零的顶点栈的变化。

有向图中求解拓扑排序的算法,要求用邻接矩阵作为图的存储表示。

二、难点和重点

1、图:图的定义与图的存储表示

邻接矩阵表示(通常是稀疏矩阵)

邻接表与逆邻接表表示,要求建立算法

邻接多重表(十字链表)表示

2、深度优先遍历与广度优先遍历 生成树与生成树林的定义

深度优先搜索算法和广度优先搜索算法

深度优先搜索是个递归的过程,而广度优先搜索是个非递归的过程 为防止重复访问已经访问过的顶点,需要设置一个访问标志数组visited 3、图的连通性

深度优先搜索可以遍历一个连通分量上的所有顶点 对非连通图进行遍历,可以建立一个生成森林 对非强连通图进行遍历,可能建立一个生成森林

关节点的求解方法和以最少的边构成重连通图的方法 4、最小生成树

对于连通网络、可用不会构成环路的权值最小的n-1条边构成最小生成树

会画出用Kruskal 算法及Prim 算法构造最小生成树的过程 5、单源最短路径

采用逐步求解的方式求某一顶点到其他顶点的最短路径的方法

要求每条边的权值必须大于零 6、活动网络

拓扑排序、关键路径、关键活动、AOE 网 拓扑排序将一个偏序图转化为一个全序图。

为实现拓扑排序,要建立一个栈,将所有入度为零的顶点进栈 关键路径的计算

三、教材中习题的解析

8-1 画出1个顶点、2个顶点、3个顶点、4个顶点和5个顶点的无向完全图。试证明在n 个顶点的无向完全图中,边的条数为n(n -1)/2。 【解答】

【证明】

在有n 个顶点的无向完全图中,每一个顶点都有一条边与其它某一顶点相连,所以每一个顶点有n -1条边与其他n -1个顶点相连,总计n 个顶点有n(n -1)条边。但在无向图中,顶点i 到顶点j 与顶点j 到顶点i 是同一条边,所以总共有n(n -1)/2条边。

8-2 右边的有向图是强连通的吗?请列出所有的简单路径。 【解答】 判断一个有向图是否强连通,要看从任一顶点出发是否能够回到该顶点。右面的有向图做不到这一点,它不是强连通的有向

图。各个顶点自成强连通分量。

所谓简单路径是指该路径上没有重复的顶点。

从顶点A 出发,到其他的各个顶点的简单路径有A →B ,A →D →B ,A →B →C ,A →D →B →C ,A →D ,A →B →E ,A →D →E ,A →D →B →E ,A →B →C →F →E ,A →D →B →C →F →E ,A →B →C →F ,A →D →B →C →F 。

1个顶点的 无向完全图 2个顶点的

无向完全图

3个顶点的 无向完全图 4个顶点的 无向完全图 5个顶点的 无向完全图

???

?

??

?

?

?

???????????=010000000000010010100000010100001010Edge 从顶点B 出发,到其他各个顶点的简单路径有B →C ,B →C →F ,B →E ,B →C →F →E 。 从顶点C 出发,到其他各个顶点的简单路径有C →F ,C →F →E 。 从顶点D 出发,到其他各个顶点的简单路径有D →B ,D →B →C ,D →B →C →F ,D →E ,D →B →E ,D →B →C →F →E 。

从顶点E 出发,到其他各个顶点的简单路径无。

从顶点F 出发,到其他各个顶点的简单路径有F →E 。

8-3 给出右图的邻接矩阵、邻接表和邻接多重表表示。 【解答】

(1) 邻接矩阵

(2) 邻接表

(3) 邻接多重表(十字链表)

0 1 2 3 4 5 (出边表) (入边表)

0 1 2 3 4 5 012345 (A, D)

(D, B)

(A, B) (B, C)

(B, E)

(F, E)

(D, E) (C, F)

8-4 用邻接矩阵表示图时,若图中有1000个顶点,1000条边,则形成的邻接矩阵有多少矩阵元素?有多少非零元素?是否稀疏矩阵? 【解答】

一个图中有1000个顶点,其邻接矩阵中的矩阵元素有10002 = 1000000个。它有1000个非零元素(对于有向图)或2000个非零元素(对于无向图),因此是稀疏矩阵。

8-5 用邻接矩阵表示图时,矩阵元素的个数与顶点个数是否相关?与边的条数是否相关? 【解答】

用邻接矩阵表示图,矩阵元素的个数是顶点个数的平方,与边的条数无关。矩阵中非零元素的个数与边的条数有关。

8-6 有n 个顶点的无向连通图至少有多少条边?有n 个顶点的有向强连通图至少有多少条边?试举例说明。 【解答】

n 个顶点的无向连通图至少有n -1条边,n 个顶点的有向强连通图至少有n 条边。例如:

特例情况是当n = 1时,此时至少有0条边。

8-7对于有n 个顶点的无向图,采用邻接矩阵表示,如何判断以下问题: 图中有多少条边?任意两个顶点i 和j 之间是否有边相连?任意一个顶点的度是多少? 【解答】

用邻接矩阵表示无向图时,因为是对称矩阵,对矩阵的上三角部分或下三角部分检测一遍,统计其中的非零元素个数,就是图中的边数。如果邻接矩阵中A[i][j] 不为零,说明顶点i 与顶点j 之间有边相连。此外统计矩阵第i 行或第i 列的非零元素个数,就可得到顶点i 的度数。

8-8对于如右图所示的有向图,试写出: (1) 从顶点①出发进行深度优先搜索所得到的深度优

先生成树;

(2) 从顶点②出发进行广度优先搜索所得到的广度优

先生成树;

【解答】

(1) 以顶点①为根的深度优先生成树(不唯一):② ③ ④ ⑤ ⑥

(2) 以顶点②为根的广度优先生成树:

① ② ③ ④ ⑤ ①

② ③ ④ ⑤

① ② ③

④ ⑤

① ② ③ ④ ⑤

8-9 试扩充深度优先搜索算法,在遍历图的过程中建立生成森林的左子女-右兄弟链表。算法的首部为void Graph::DFS ( const int v, int visited [ ], TreeNode * t ) 其中,指针t 指向生成森林上具有图顶点v信息的根结点。(提示:在继续按深度方向从根v的某一未访问过的邻接顶点w向下遍历之前,建立子女结点。但需要判断是作为根的第一个子女还是作为其子女的右兄弟链入生成树。)

【解答】

为建立生成森林,需要先给出建立生成树的算法,然后再在遍历图的过程中,通过一次次地调用这个算法,以建立生成森林。

te mplate void Graph :: DFS_Tree ( const int v, int visited [ ], TreeNode *t ) { //从图的顶点v出发, 深度优先遍历图, 建立以t (已在上层算法中建立)为根的生成树。

Visited[v] = 1; int first = 1; TreeNode * p, * q;

int w = GetFirstNeighbor ( v );//取第一个邻接顶点

while ( w != -1 ) {//若邻接顶点存在

if ( vosited[w] == 0 ) { //且该邻接结点未访问过

p = new TreeNode ( GetValue (w) );//建立新的生成树结点

if ( first == 1 ) //若根*t还未链入任一子女

{ t->setFirstChild ( p );first = 0; }//新结点*p成为根*t的第一个子女else q->setNextSibling ( p );//否则新结点*p成为*q的下一个兄弟

q = p;//指针q总指示兄弟链最后一个结点

DFS_Tree ( w, visited, q );//从*q向下建立子树

}

w = GetNextNeighbor ( v, w );//取顶点v排在邻接顶点w的下一个邻接顶点}

}

下一个算法用于建立以左子女-右兄弟链表为存储表示的生成森林。

template void Graph :: DFS_Forest ( Tree& T ) {

//从图的顶点v出发, 深度优先遍历图, 建立以左子女-右兄弟链表表示的生成森林T。

T.root = NULL; int n =NumberOfVertices ( ); //顶点个数

TreeNode * p, * q;

int * visited = new int [ n ];//建立访问标记数组

for ( int v = 0; v < n; v++ ) visited[v] = 0;

for ( v = 0; v < n; v++ ) //逐个顶点检测

if ( visited[v] == 0 ) {//若尚未访问过

p = new TreeNode ( GetValue ( v ) );//建立新结点*p

if ( T.root == NULL ) T.root = p;//原来是空的生成森林, 新结点成为根

else q-> setNextSibling ( p );//否则新结点*p成为*q的下一个兄弟

q = p;

DFS_Tree ( v, visited, p );//建立以*p为根的生成树

}

}

8-10 用邻接表表示图时,顶点个数设为n,边的条数设为e,在邻接表上执行有关图的遍历操作时,时间代价是O(n*e)?还是O(n+e)?或者是O(max(n,e))?

【解答】

在邻接表上执行图的遍历操作时,需要对邻接表中所有的边链表中的结点访问一次,还

需要对所有的顶点访问一次,所以时间代价是O(n+e)。

8-11 右图是一个连通图,请画出 (1) 以顶点①为根的深度优先生成树; (2) 如果有关节点,请找出所有的关节点。

(3) 如果想把该连通图变成重连通图,至少在图中

加几条边?如何加?

【解答】 (1) 以顶点①为根的深度优先生成树:

(2) 关节点为 ①,②,③,⑦,⑧ (3) 至少加四条边 (1, 10), (3, 4), (4, 5), (5, 6)。从③的子孙结点⑩到③的祖先结点①引一条边,从②的子孙结点④到根①的另一分支③引一条边,

并将⑦的子孙结点⑤、⑥与结点④连结起来,可使其变为重连通图。

8-12试证明在一个有n 个顶点的完全图中,生成树的数目至少有2n-1-1。 【证明】略

8-

13 编写一个完整的程序,首先定义堆和并查集的结构类

和相关操作,再定义 Kruskal 求连通网络

的最小生成树算法的 实现。并以右图为 例,写出求解过程中

堆、并查集和最小生成树的变化。 【解答】 求解过程的第一步是对所有的边,按其权值大小建堆:

5

② ③ ④ ⑤

11 7 6

8 10 9

7

⑩ ① ②

③ ④

⑥ ⑦

⑩ ① ②

③ ④ ⑤ ⑥ ⑦ ⑧

加(1, 2), (1, 3),

(2,3)

加(2, 4) 加(3, 4)

⑩ ① ② ③ ④ ⑤ ⑥ ⑦

求解过程中并查集与堆的变化:

最后得到的生成树如下

完整的程序如下:

#include

template class MinHeap { public: enum { MaxHeapSize = 50 };

MinHeap ( int Maxsize = MaxHeapSize ); MinHeap ( Type Array[ ], int n ); void Insert ( const Type &ele ); void RemoveMin ( Type &Min ); void Output ();

② ③

④ ⑤

6

7

5

7

9

加(3, 5) 加(3, 6)

加(5, 6)

选(3,4,5)

选(1,2,7)

③ ④ ⑤ ⑥

① ② 1 3 11 3 5 7

2 4 9

2 3 10

3 6 8 选(3,5,7) ③ ⑤

① 1 3 11

2 4 9 2

3 10

3 6 8

选(3,6,8), 在同一连通分量上, 不加 ③ ④ ⑤

⑥ ① ② 1 3 11

2 3 10 2 4 9

选(2,4,9), 结束

1 3 11

2 3 10

③ ④ ⑤

3 1 -6 3 3 5 0 1 2 3

4

5 6

并查集的存储表示

private:

void FilterDown ( int start, int end );

void FilterUp ( int end );

Type *pHeap;

int HMaxSize;

int CurrentSize;

};

class UFSets {

public:

enum { MaxUnionSize = 50 };

UFSets ( int MaxSize = MaxUnionSize );

~UFSets () { delete [ ] m_pParent; }

void Union ( int Root1, int Root2 );

int Find ( int x );

private:

int m_iSize;

int *m_pParent;

};

class Graph {

public:

enum { MaxVerticesNum = 50 };

Graph( int Vertices = 0) { CurrentVertices = Vertices; InitGraph(); } void InitGraph ();

void Kruskal ();

int GetVerticesNum () { return CurrentVertices; }

private:

int Edge[MaxVerticesNum][MaxVerticesNum];

int CurrentVertices;

};

class GraphEdge {

public:

int head, tail;

int cost;

int operator <= ( GraphEdge &ed );

};

GraphEdge :: operator <= ( GraphEdge &ed ) {

return this->cost <= ed.cost;

}

UFSets :: UFSets ( int MaxSize ) {

m_iSize = MaxSize;

m_pParent = new int[m_iSize];

for ( int i = 0; i < m_iSize; i++ ) m_pParent[i] = -1;

}

void UFSets :: Union ( int Root1, int Root2 ) {

m_pParent[Root2] = Root1;

}

int UFSets :: Find ( int x ) {

while ( m_pParent[x] >= 0 ) x = m_pParent[x];

return x;

}

template MinHeap :: MinHeap ( int Maxsize ) { HMaxSize = Maxsize;

pHeap = new Type[HMaxSize];

CurrentSize = -1;

}

template MinHeap :: MinHeap ( Type Array[], int n ) { HMaxSize = ( n < MaxHeapSize ) ? MaxHeapSize : n;

pHeap = new Type[HMaxSize];

for ( int i = 0; i < n; i++ ) pHeap[i] = Array[i];

CurrentSize = n-1;

int iPos = ( CurrentSize - 1 ) / 2;

while ( iPos >= 0 ) {

FilterDown ( iPos, CurrentSize );

iPos--;

}

}

template void MinHeap :: FilterDown ( int start, int end ) { int i = start, j = 2 * start + 1;

Type Temp = pHeap[i];

while ( j <= end ) {

if ( j < end && pHeap[j+1] <= pHeap[j] ) j++;

if ( Temp <= pHeap[j] ) break;

pHeap[i] = pHeap[j];

i = j; j = 2 * j + 1;

}

pHeap[i] = Temp;

}

template void MinHeap :: FilterUp ( int end ) { int i = end, j = ( end - 1 ) / 2;

Type Temp = pHeap[i];

while ( i > 0 ) {

if ( pHeap[j] <= Temp ) break;

pHeap[i] = pHeap[j];

i = j; j = ( j - 1 ) / 2;

}

pHeap[i] = Temp;

}

template void MinHeap :: Insert ( const Type &ele ) { CurrentSize++;

if ( CurrentSize == HMaxSize ) return;

pHeap[CurrentSize] = ele;

FilterUp ( CurrentSize );

}

template void MinHeap :: RemoveMin ( Type &Min ) { if ( CurrentSize < 0 )return;

Min = pHeap[0];

pHeap[0] = pHeap[CurrentSize--];

FilterDown ( 0, CurrentSize );

}

template void MinHeap :: Output ( ) {

for ( int i = 0; i <= CurrentSize; i++ ) cout << pHeap[i] << " ";

cout << endl;

}

void Graph :: InitGraph( ) {

Edge[0][0] = -1;Edge[0][1] = 28;Edge[0][2] = -1;Edge[0][3] = -1;Edge[0][4] = -1;

Edge[0][5] = 10; Edge[0][6] = -1;

Edge[1][1] = -1;Edge[1][2] = 16;Edge[1][3] = -1;Edge[1][4] = -1;Edge[1][5] = -1;

Edge[1][6] = 14;

Edge[2][2] = -1; Edge[2][3] = 12;Edge[2][4] = -1; Edge[2][5] = -1;Edge[2][6] = -1;

Edge[3][3] = -1;Edge[3][4] = 22;Edge[3][5] = -1;Edge[3][6] = 18;

Edge[4][4] = -1;Edge[4][5] = 25; Edge[4][6] = 24;

Edge[5][5] = -1;Edge[5][6] = -1;

Edge[6][6] = -1;

for ( int i = 1; i < 6; i++ )

for ( int j = 0; j < i; j ++ ) Edge[i][j] = Edge[j][i];

}

void Graph :: Kruskal( ) {

GraphEdge e;

int VerticesNum = GetVerticesNum ( );

int i, j, count;

MinHeap heap ( VerticesNum *VerticesNum );

UFSets set ( VerticesNum );

for ( i = 0; i < VerticesNum ; i++ ) for ( j = i + 1; j < VerticesNum ; j++ ) if ( Edge[i][j] > 0 ) { e.head = i ; e.tail = j ; e.cost = Edge[i][j]; heap.Insert ( e );

}

count = 1;

while ( count < VerticesNum ) { heap.RemoveMin ( e ); i = set.Find ( e.head ); j = set.Find ( e.tail ); if ( i != j ) { set.Union ( i, j ); count++;

cout << "( " << e.head << ", " << e.tail << ", " <<

e.cost << " )" << endl;

}

} }

8-14 利用Dijkstra 算法的思想,设计一个求最小生成树的算法。 【解答】 计算连通网络的最小生成树的Dijkstra 算法可描述如下:将连通网络中所有的边以方便的次序逐步加入到初始为空的生成树的边集合T 中。每次选择并加入一条边时,需要判断它是否会与先前加入T 的边构成回路。如果构成了回路,则从这个回路中将权值最大的边退选。 下面以邻接矩阵作为连通网络的存储表示,并以并查集作为判断是否出现回路的工具,分析算法的执行过程。

26 21

11 ① ② ⑤ ④

⑥ 18 14 16

19 9 5 6 ?????????? ??------------∞∞--∞-∞∞=02601118060199502114160Edge ① ② ③ ④ ⑤ ⑥ ① ②③④⑤⑥ ③ ① ②

⑥ 14

16

21

① ② ⑤ ⑥ 并查集, 表明4

个结点在同一连通分量上 16

14

21

19

9

5

? ①

② ⑤

② ⑤ ③ 19 9 ① ②

④ ③

⑥ 14 16 5 6

?

14

16

5

6

19

11

? ①

③ ④

最终得到的最小生成树为

算法的思路如下:

① 并查集初始化:将所有顶点置为只有一个顶点的连通分量; ② 检查所有的边: ⅰ)若边的两个端点i 与j 不在同一连通分量上(i 与j 在并查集中不同根),则连通之(合并);

ⅱ) 若边的两个端点i 与j 在同一连通分量上(i 与j 在并查集中同根),则

— 在并查集中寻找离i 与j 最近的共同祖先结点 — 分别从i 与j 向上检测具有最大权值的边

— 在并查集上删除具有最大权值的边,加入新的边。

下面给出实现算法:

const int MaxNum = 10000; void Graph :: Dijkstra ( ) { GraphEdge e ;

int VerticesNum = GetVerticesNum ( ); int i , j , p, q, k ;

int disJoint[VerticesNum];

//并查集 for ( i = 0; i < VerticesNum ; i++ ) disJoint[i] = -1; //并查集初始化 for ( i = 0; i < VerticesNum -1; i++ ) //检查所有的边 for ( j = i + 1; j < VerticesNum ; j++ ) if ( Edge[i][j] < MaxNum ) {

//边存在

p = i ; q = j ;

//判结点i 与j 是否在同一连通分量上

while ( disJoint[p] >= 0 ) p = disJoint[p]; while ( disJoint[q] >= 0 ) p = disJoint[q]; if ( p != q ) disJoint[j] = i ; // i 与j 不在同一连通分量上, 连通之 } else {

// i 与j 在同一连通分量上

p = i ;

//寻找离结点i 与j 最近的祖先结点

while ( disJoint[p] >= 0 ) {

//每变动一个p, 就对q 到根的路径检测一遍

q = j ;

while ( disJoint[q] >= 0 && disJoint[q] == disJoint[p] )

q = disJoint[q];

if ( disJoint[q] == disJoint[p] ) break;

else p = disJoint[p];

}

k = disJoint[p];

//结点k 是i 和j 的最近的共同祖先 p = i ; q = disJoint[p]; max = -MaxNum ;

//从i 到k 找权值最大的边(s1, s2)

while ( q <= k ) { if ( Edge[q][p] > max ) { max = Edge[q][p]; s1 = p ; s2 = q ; }

p =q ; q = disJoint[p];

}

p = j ; q = disJoint[p]; max = -MaxNum ;

//从j 到k 找权值最大的边(t1, t2)

14

16

5

6

11

while ( q <= k ) {

if ( Edge[q][p] > max ) { max = Edge[q][p]; t1 = p; t2 = q; }

p =q;q = disJoint[p];

}

max = Edge[i][j];k1 = i;k2 = j;

if ( max < Edge[s1][s2] ) { max = Edge[s1][s2]; k1 = s1; k2 = s2; }

if ( max < Edge[t1][t2] ) { max = Edge[t1][t2]; k1 = t1; k2 = t2; }

if ( max != Edge[i][j] ) { //当Edge[i][j] == max时边不改

if ( disJoint[k1] == k2 ) disJoint[k1] = -1;

else disJoint[k2] = -1; //删除权值最大的边

disJoint[j] = i; //加入新的边

Edge[j][i] = - Edge[j][i];

}

}

}

8-15以右图为例,按Dijkstra算法计算得到的从顶点①(A)到其它各个顶点的最短路径和最

短路径长度。

C

8-16 在以下假设下,重写Dijkstra算法:

(1) 用邻接表表示带权有向图G,其中每个边结点有3个域:邻接顶点vertex,边上的

权值length和边链表的链接指针link。

(2) 用集合T = V(G) - S代替S (已找到最短路径的顶点集合),利用链表来表示集合T。

试比较新算法与原来的算法,计算时间是快了还是慢了,给出定量的比较。

【解答】

(1)用邻接表表示的带权有向图的类定义:

const int DefaultSize = 10; //缺省顶点个数

class Graph; //图的前视类定义

struct Edge { //边的定义

friend class Graph;

int vertex; //边的另一顶点位置

float length; //边上的权值

Edge *link; //下一条边链指针

Edge ( ) { }//构造函数

Edge ( int num, float wh ) : vertex (num), length (wh), link (NULL) { }//构造函数

int operator < ( const Edge & E ) const { return length != E.length;}//判边上权值小否

}

struct Vertex { //顶点的定义

friend class Graph;

char data; //顶点的名字

Edge *adj; //边链表的头指针

}

class Graph { //图的类定义

private:

Vertex *NodeTable; //顶点表(各边链表的头结点)

int NumVertices; //当前顶点个数

int NumEdges; //当前边数

int GetVertexPos ( const Type vertex ); //给出顶点vertex在图中的位置

public:

Graph ( int sz ); //构造函数

~Graph ( ); //析构函数

int NumberOfVertices ( ) { return NumVertices;} //返回图的顶点数

int NumberOfEdges ( ) { return NumEdges;} //返回图的边数

char GetValue ( int i ) //取位置为i的顶点中的值

{ return i >= 0 && i < NumVertices ? NodeTable[i].data : … ?;}

float GetWeight ( int v1, int v2 );//返回边(v1, v2)上的权值

int GetFirstNeighbor ( int v ); //取顶点v的第一个邻接顶点

int GetNextNeighbor ( int v, int w ); //取顶点v的邻接顶点w的下一个邻接顶点

}

(2) 用集合T = V(G) - S代替S (已找到最短路径的顶点集合),利用链表来表示集合T。

集合T用有序链表表示,数据域为顶点序号,链表T中的顶点都是未找到最短路径的顶点。另外设置一个数组S,其作用是记录已找到的顶点0到其他各顶点的最短路径path 及最短路径长度len。

算法的主要思路是:

①对数组S及链表T初始化,记录顶点0到各个顶点的初始最短路径及其长度;

②扫描链表T,寻找链表T中各个顶点到顶点0的当前最短路径中长度最小者,记为

u;

③在邻接表中扫描第u个顶点的出边表,确定每一边的邻接顶点号k。

若顶点k的最短路径没有选中过,比较绕过顶点u到顶点k的路径长度和原来顶点0到顶点k的最短路径长度,取其小者作为从顶点0到顶点k的新的最短路径。

④重复执行②、③步,直到图中所有顶点的最短路径长度都已选定为止。

算法的实现如下:

const float MaxNum = 10000000;

typedef struct info {//辅助数组元素: 各顶点最短路径信息

int pre;//在最短路径上前一顶点的顶点序号

float len;//当前最短路径长度

}

info S [NumVertices];//辅助数组: 最短路径数组

List T;//未选定最短路径顶点链表

int i, k, u;ListNode * p;

T. MakeEmpty ();

for ( i = 1; i < NumVertices; i++) {

S[i].pre = 0;S[i].len = MaxNum;//辅助数组初始化

T.Locate ( i );T.Insert( i );//形成有序链表T

}

p = NodeTable[0].adj;

while ( p != NULL )

{ S[p->vertex].len = p->length;p = p->link; }

while (1) {

T.First (); //循环检测链表T

if ( ! T.NextNotNull( ) ) break;//链表仅剩一个顶点, 跳出循环, 算法结束

float min = MaxNum;u = 0;

while ( T.NotNull( ) ) {//链表不空, 还有剩余顶点未确定最短路径

i = T.GetData( ); //取剩余顶点号

if ( S[i].len < min ) { min = S[i].len;u = i; }//比较, 寻找最短路径长度结点u

T.next ( );

}

p = NodeTable[u].adj;

while ( p != NULL ) {//比较绕过顶点u 到其他顶点k的路径长度k = p->vertex;//顶点k在链表T中表示该顶点未最终选定最短路径

if ( T.Find(k) != NULL && S[u].len + p->length < S[k].len )

{ s[k].len = S[u].len + p->length;S[k].pre = u; }//修改

p = p->link;

}

T.Find(u);T.Remove(); //在链表T中删除顶点u

}

8-17 试证明:对于一个无向图G = (V, E),若G中各顶点的度均大于或等于2,则G中必有回路。

【解答】

反证法:对于一个无向图G=(V,E),若G中各顶点的度均大于或等于2,则G中没有回路。此时从某一个顶点出发,应能按拓扑有序的顺序遍历图中所有顶点。但当遍历到该顶点的另一邻接顶点时,又可能回到该顶点,没有回路的假设不成立。

8-18 设有一个有向图存储在邻接表中。试设计一个算法,按深度优先搜索策略对其进行拓扑排序。并以右图为例检验你的算法的正确性。

【解答】

(1) 利用题8-16定义的邻接表结构。

增加两个辅助数组和一个工作变量:

?记录各顶点入度int indegree[NumVertices]。

?记录各顶点访问顺序int visited[NumVertices],初始

时让visited[i] = 0, i = 1, 2, , NumVertices。

?访问计数int count,初始时为0。

(2) 拓扑排序算法

void Graph :: dfs ( int visited[ ], int indegree[ ], int v, int& count ) { count++; visited[v] = count;

cout << NodeTable[v].data << endl;

Edge *p = NodeTable[v].adj;

while ( p != NULL ) {

int w = p->vertex; ①

②③

④⑤

indegree[w]--;

if ( visited[w] == 0 && indegree[w] == 0 ) dfs ( visited, indegree, w, count );

p = p->link;

}

}

主程序

int i, j; Edge *p; float w;

cin >> NumVertices;

int * visited = new int[NumVertices+1];

int * indegree = new int[NumVertices+1];

for ( i = 1; i <= NumVertices; i++ ) {

NodeTable[i].adj = NULL; cin >> NodeTable[i].data; cout << endl;

visited[i] = 0; indegree[i] = 0;

}

int count = 0;

cin >> i >> j >> w; cout << endl;

while ( i != 0 && j != 0 ) {

p = new Edge ( j, w );

if ( p == NULL ) { cout << “存储分配失败!” << endl; exit(1); }

indegree[j]++;

p->link = NodeTable[i].adj;NodeTable[i].adj = p;

NumEdges++;

cin >> i >> j >> w; cout << endl;

}

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

if ( visited[i] == 0 && indegree[i] == 0 )dfs ( visited, indegree, i, count );

if (count < NumVertices ) cout<< “排序失败!” << endl;

else cout<< “排序成功!” << endl;

delete [ ] visited; delete [ ] indegree;

8-19试对下图所示的AOE网络,解答下列问题。

(1) 这个工程最早可能在什么时间结束。

(2) 求每个事件的最早开始时间Ve[i]和最迟开始时间Vl[i]。

(3) 求每个活动的最早开始时间e( )和最迟开始时间l( )。

(4) 确定哪些活动是关键活动。画出由所有关键活动构成的图,指出哪些活动加速可使整个工程提前完成。

【解答】

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

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

8-20 若AOE网络的每一项活动都是关键活动。令G是将该网络的边去掉方向和权后得到的无向图。

(1) 如果图中有一条边处于从开始顶点到完成顶点的每一条路径上,则仅加速该边表示的活动就能减少整个工程的工期。这样的边称为桥(bridge)。证明若从连通图中删去桥,将把图分割成两个连通分量。

(2) 编写一个时间复杂度为O(n+e)的使用邻接表表示的算法,判断连通图G中是否有桥,若有。输出这样的桥。

【解答】

(1) 反证法(略)

(2)借助于求重连通分量的算法。如果一条边的两个端点满足下列条件之一,即为桥:

①两个端点都是关节点;

②一个端点是关节点,另一端点是整个图的开始点;

③一个端点是关节点,另一端点是整个图的完成点。

四、其他练习题

8-21 判断题

(1) 用邻接矩阵存储一个图时,在不考虑压缩存储的情况下,所占用的存储空间大小只与图中的顶点个数有关,而与图的边数无关。

(2) 邻接表只能用于有向图的存储,邻接矩阵对于有向图和无向图的存储都适用。

(3) 邻接矩阵只适用于稠密图(边数接近于顶点数的平方),邻接表适用于稀疏图(边数远小于顶点数的平方)。

(4) 有n (n≥1) 个顶点的无向连通图最少有n-1条边。

(5) 有n (n≥1) 个顶点的有向强连通图最少有n条边。

(6) 存储无向图的邻接矩阵是对称的,因此只要存储邻接矩阵的下(上)三角部分就可以了。

(7) 连通分量是无向图中的极小连通子图。

(8) 强连通分量是有向图中的极大强连通子图。

(9) 对任何用顶点表示活动的网络(AOV网)进行拓扑排序的结果都是唯一的。

(10) 有回路的有向图不能完成拓扑排序。

(11) 在AOE网络中一定只有一条关键路径。

(12)关键活动不按期完成就会影响整个工程的完成时间。

(13) 任何一个关键活动提前完成, 那么整个工程将会提前完成。

(14)所有的关键活动都提前完成, 那么整个工程将会提前完成。

(15) 任何一个关键活动延迟,那么整个工程将会延迟。

【解答】

(1) √(2) ?(3) √(4) √(5) √(6) √(7) ?(8) √

(9) ?(10) √(11) ?(12) √(13) ?(14) √(15) √

8-22 填空题

(1) 在一个无向图中,所有顶点的度数之和等于所有边数的________倍。

(2) 在一个具有n个顶点的无向完全图中,包含有________条边,在一个具有n个顶点的有向完全图中,包含有________条边。

(3) 在一个具有n个顶点的无向图中,要连通所有顶点则至少需要________条边。

(4) 表示图的三种存储结构为________、________和________。

(5) 对于一个具有n个顶点的图,若采用邻接矩阵表示,则矩阵大小为________。

(6) 对于一个具有n个顶点和e条边的有向图和无向图,在其对应的邻接表中,所含边结点分别为________和________条。

(7) 在有向图的邻接表和逆邻接表表示中,每个顶点的边链表中分别链接着该顶点的所有________和________结点。

(8) 对于一个具有n个顶点和e条边的有向图和无向图,若采用邻接多重表表示,则存于顶点表中的边链表指针分别有________和________个,所有边结点有________个。

(9) 对于一个具有n个顶点和e条边的无向图,当分别采用邻接矩阵、邻接表和邻接多重表表示时,求任一顶点度数的时间复杂度依次为________、________和________。

(10) 假定一个图具有n个顶点和e条边,则采用邻接矩阵、邻接表和邻接多重表表示时,其相应的空间复杂度分别为________、________和________。

(11) 对用邻接矩阵表示的图进行任一种遍历时,其时间复杂度为________,对用邻接表表示的图进行任一种遍历时,其时间复杂度为________。

(12) 对于一个具有n个顶点和e条边的连通图,其生成树中的顶点数和边数分别为________和________。

【解答】

(1) 2 (2) n(n-1)/2, n(n-1)

(3) n-1 (4) 邻接矩阵, 邻接表, 邻接多重表

(5) n2(6) e, 2e

(7) 出边, 入边(8) 2n, n, e

(9) O(n), O(e/n), O(e) (10) O(n2), O(n+e), O(n+e)

(11) O(n2), O(e) (12) n, n-1

8-23 从供选择的答案中选择与下面有关图的叙述中各括号相匹配的词句,将其编号填入相应的括号内。

(1) 采用邻接表存储的图的深度优先遍历算法类似于二叉树的( A )。

(2) 采用邻接表存储的图的广度优先遍历算法类似于二叉树的( B )。

(3) 对于含有n个顶点和e条边的无向连通图,利用prim算法产生最小生成树,其时间复杂性为( C ),利用Kruskal算法产生最小生成树,其时间复杂性为( D )。

(4) 设图中有n个顶点和e条边,进行深度优先搜索的时间复杂度至多为( E ),进行广度优先搜索的时间复杂性至多为( F )。

(5) 对于一个具有n个顶点和e条边的无向图,进行拓扑排序时,总的时间为(G )。

(4) 判断有向图是否存在回路,除了可以利用拓扑排序方法外,还可以利用(H )。供选择的答案

A, B:①中序遍历②前序遍历③后序遍历④按层次遍历

C, D:①O(n2) ②O(n*e) ③O(nlog2n) ④O(elog2e)

E, F:①O(n+e) ②O(n*e) ③O(nlog2n) ④O(elog2e)

G:①n ②n+1 ③n-1 ④n+e

H:①求关键路径的方法②求最短路径的Dijkstra方法

③深度优先遍历算法④广度优先遍历算法

【解答】

A.②B.④C.①D.④E.①F.①G.①H.③

8-24 若设一个图采用邻接矩阵表示,试编写进行深度优先搜索的非递归算法。

【解答】

邻接矩阵采用教材中的定义。在相应的深度优先搜索的非递归算法中,同样使用了一个辅助数组int visited[ ],在visited[i]中记忆第i个顶点是否访问过。另外,算法中使用了一个栈S,记忆回退的路径。具体算法实现如下:

#include

#include “stack.h”

template void Graph : : dfss ( int v ) {

//从顶点v开始进行深度优先搜索,一次遍历一个连通分量的所有顶点

int i, j, k; Stack S; S.Push ( v );

int vosited[MaxNumVertices];

for (i = 0; i < MaxNumVertices; i++ ) visited[i] = 0;

while ( !S.IsEmpty ( ) ) {

k = S.GetTop( );S.Pop ( ); //栈中退出一个顶点

if ( !visited[k] ) { //若未访问过

cout << k << ' ';visited[k] = 1;//访问,并作访问标记

for ( j = MaxNumVertices-1; j >= 0; j-- ) //检查k的所有邻接顶点

if ( k != j && Edge[k][j] != MaxValue ) //所有邻接顶点进栈

S.Push ( j );

}

}

}

}

8-25 应用Prim算法求解连通网络的最小生成树问题。

(1) 针对右图所示的连通网络,试按如下格式给出在构造最小生成树过程中顺序选出的各条边。

( , , )

( , , )

( , , )

( , , )

( , , )

(2) 下面是Prim算法的实现,中间有5个地方缺失,请阅读程序后将它们补上。

const int MaxInt = INT_MAX;//INT_MAX的值在

const int n = 6;//图的顶点数, 应由用户定义

typedef int AdjMatrix[n][n];//用二维数组作为邻接矩阵表示

typedef struct {//生成树的边结点int fromVex, toVex;//边的起点与终点

int weight;//边上的权值

} TreeEdgeNode;

typedef TreeEdgeNode MST[n-1]; //最小生成树定义

void PrimMST ( AdjMatrix G, MST T, int rt ) {

//从顶点rt出发构造图G的最小生成树T,rt成为树的根结点TreeEdgeNode e; int i, k = 0, min, minpos, v;

for ( i = 0; i < n; i++ ) //初始化最小生成树T if ( i != rt ) {

T[k].fromVex = rt;

;

T[k++].weight = G[rt][i];

}

for ( k = 0; k < n-1; k++ ) { //依次求MST的候选边

;

for ( i = k; i < n-1; i++ ) //遍历当前候选边集合

if//选具有最小权值的候选边

{ min = T[i].weight;; }

if ( min == MaxInt ) , 出错处理

{ cerr << “Graph is disconnected!” << endl; ; }

e = T[minpos]; T[minpos] = T[k] ; T[k] = e;

v = T[k].toVex;

for ( i = k+1; i < n-1; i++ ) //修改候选边集合

if ( G[v][T[i].toVex] < T[i].weight ) {

T[i].weight = G[v][T[i].toVex];

;

}

}

}

【解答】

(1) 选出的边顺序为: 【括号中的内容为:(始顶点号,终顶点号,权值)】

(0, 3, 1),(3, 5, 4),(5, 2, 2),(3, 4, 5) 或(3, 1, 5),(4, 1, 3),(1, 4, 3 )

(2) 应填入的语句是:①T[k].toVex = i;②min = MaxInt; ③minpos = i;

④exit (1);⑤T[i].fromVex = v;

8-26 给定n个小区之间的交通图。若小区i与小区j之间有路可通,则将顶点i与顶点j之间用边连接,边上的权值wij表示这条道路的长度。现在打算在这n个小区中选定一个小区建一所医院,试问这家医院应建在哪个小区,才能使距离医院最远的小区到医院的路程最短?试设计一个算法解决上述问题。

【解答】

将n个小区的交通图视为带权无向图,并利用邻接矩阵来存放带权无向图。算法的思想是:

(1) 应用Floyed算法计算每对顶点之间的最短路径;

数据结构课后习题与解析第六章

第六章习题 1.试分别画出具有3个结点的树和3个结点的二叉树的所有不同形态。2.对题1所得各种形态的二叉树,分别写出前序、中序和后序遍历的序列。 3.已知一棵度为k的树中有n 1个度为1的结点,n 2 个度为2的结点,……,n k 个度为k的结点, 则该树中有多少个叶子结点并证明之。 4.假设一棵二叉树的先序序列为EBADCFHGIKJ,中序序列为ABCDEFGHIJK,请画出该二叉树。 5.已知二叉树有50个叶子结点,则该二叉树的总结点数至少应有多少个? 6.给出满足下列条件的所有二叉树: ①前序和后序相同 ②中序和后序相同 ③前序和后序相同 7. n个结点的K叉树,若用具有k个child域的等长链结点存储树的一个结点,则空的Child 域有多少个? 8.画出与下列已知序列对应的树T: 树的先根次序访问序列为GFKDAIEBCHJ; 树的后根次序访问序列为DIAEKFCJHBG。 9.假设用于通讯的电文仅由8个字母组成,字母在电文中出现的频率分别为: 0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10 请为这8个字母设计哈夫曼编码。 10.已知二叉树采用二叉链表存放,要求返回二叉树T的后序序列中的第一个结点指针,是否可不用递归且不用栈来完成?请简述原因. 11. 画出和下列树对应的二叉树:

12.已知二叉树按照二叉链表方式存储,编写算法,计算二叉树中叶子结点的数目。 13.编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间。 14.分别写函数完成:在先序线索二叉树T中,查找给定结点*p在先序序列中的后继。在后序线索二叉树T中,查找给定结点*p在后序序列中的前驱。 15.分别写出算法,实现在中序线索二叉树中查找给定结点*p在中序序列中的前驱与后继。 16.编写算法,对一棵以孩子-兄弟链表表示的树统计其叶子的个数。 17.对以孩子-兄弟链表表示的树编写计算树的深度的算法。 18.已知二叉树按照二叉链表方式存储,利用栈的基本操作写出后序遍历非递归的算法。 19.设二叉树按二叉链表存放,写算法判别一棵二叉树是否是一棵正则二叉树。正则二叉树是指:在二叉树中不存在子树个数为1的结点。 20.计算二叉树最大宽度的算法。二叉树的最大宽度是指:二叉树所有层中结点个数的最大值。 21.已知二叉树按照二叉链表方式存储,利用栈的基本操作写出先序遍历非递归形式的算法。 22. 证明:给定一棵二叉树的前序序列与中序序列,可唯一确定这棵二叉树; 给定一棵二叉树的后序序列与中序序列,可唯一确定这棵二叉树; 23. 二叉树按照二叉链表方式存储,编写算法,计算二叉树中叶子结点的数目。 24. 二叉树按照二叉链表方式存储,编写算法,将二叉树左右子树进行交换。 实习题 1.[问题描述] 建立一棵用二叉链表方式存储的二叉树,并对其进行遍历(先序、中序和后序), 打印输出遍历结果。

《数据结构》习题汇编07 第七章 图 试题

第七章图试题 一、单项选择题 1.在无向图中定义顶点的度为与它相关联的()的数目。 A. 顶点 B. 边 C. 权 D. 权值 2.在无向图中定义顶点 v i与v j之间的路径为从v i到达v j的一个()。 A. 顶点序列 B. 边序列 C. 权值总和 D. 边的条数 3.图的简单路径是指()不重复的路径。 A. 权值 B. 顶点 C. 边 D. 边与顶点均 4.设无向图的顶点个数为n,则该图最多有()条边。 A. n-1 B. n(n-1)/2 C. n(n+1)/2 D. n(n-1) 5.n个顶点的连通图至少有()条边。 A. n-1 B. n C. n+1 D. 0 6.在一个无向图中,所有顶点的度数之和等于所有边数的 ( ) 倍。 A. 3 B. 2 C. 1 D. 1/2 7.若采用邻接矩阵法存储一个n个顶点的无向图,则该邻接矩阵是一个 ( )。 A. 上三角矩阵 B. 稀疏矩阵 C. 对角矩阵 D. 对称矩阵 8.图的深度优先搜索类似于树的()次序遍历。 A. 先根 B. 中根 C. 后根 D. 层次 9.图的广度优先搜索类似于树的()次序遍历。 A. 先根 B. 中根 C. 后根 D. 层次 10.在用Kruskal算法求解带权连通图的最小(代价)生成树时,通常采用一个()辅助结构, 判断一条边的两个端点是否在同一个连通分量上。 A. 位向量 B. 堆 C. 并查集 D. 生成树顶点集合 11.在用Kruskal算法求解带权连通图的最小(代价)生成树时,选择权值最小的边的原则是该边不能 在图中构成()。 A. 重边 B. 有向环 C. 回路 D. 权值重复的边 12.在用Dijkstra算法求解带权有向图的最短路径问题时,要求图中每条边所带的权值必须是 ()。 A. 非零 B. 非整 C. 非负 D. 非正 13.在一个连通图中进行深度优先搜索得到一棵深度优先生成树,树根结点是关节点的充要条件是它至少 有()子女。

(完整word版)数据结构 第八章排序

第八章排序:习题 习题 一、选择题 1.在所有排序方法中,关键字比较的次数与记录的初始排列次序无关的是( )。 A.希尔排序 B.冒泡排序 C.插入排序 D.选择排序 2.设有1000个无序的记录,希望用最快的速度挑选出其中前10个最大的记录,最好选用( )排序法。 A.冒泡排序 B.快速排序 C.堆排序 D.基数排序 3.在待排序的记录序列基本有序的前提下,效率最高的排序方法是( )。 A.插入排序 B.选择排序 C.快速排序 D.归并排序’ 4.不稳定的排序方法是指在排序中,关键字值相等的不同记录的前后相对位置( )。 A.保持不变 B.保持相反 C.不定 D.无关 5.内部排序是指在排序的整个过程中,全部数据都在计算机的( )中完成的排序。 A. 内存储器 B.外存储器 C.内存储器和外存储器 D.寄存器 6.用冒泡排序的方法对n个数据进行排序,第一趟共比较( )对记录。 A.1 B.2 C.n-l D.n 7.直接插入排序的方法是从第( )个记录开始,插入前边适当位置的排序方法。 A.1 B.2 C.3 D.n 8.用堆排序的方法对n个数据进行排序,首先将n个记录分成( )组。 A.1 B.2 C.n-l D.n 9.归并排序的方法对n个数据进行排序,首先将n个记录分成( )组,两两归并。 A.1 B.2 C.n-l D.n 10.直接插入排序的方法要求被排序的数据( )存储。 A.必须是顺序 B.必须是链表 C.顺序或链表 D.二叉树 11.冒泡排序的方法要求被排序的数据( )存储。 A.必须是顺序 B.必须是链表 C.顺序或链表 D.二叉树 12.快速排序的方法要求被排序的数据( )存储。 A.必须是顺序 B.必须是链表 C.顺序或链表 D.二叉树 13.排序方法中,从未排序序列中依次取出记录与已排序序列(初始时为空)中的记录进行比较,将其放入已排序序列的正确位置上的方法,称为( )。 A.希尔排序 B.冒泡排序 C.插入排序 D.选择排序 14.每次把待排序的记录划分为左、右两个子序列,其中左序列中记录的关键字均小于等于基准记录的关键字,右序列中记录的关键字均大于基准记录的关键字,则此排序方法叫做( )。 A.堆排序 B.快速排序 C.冒泡排序 D. Shell排序 15.排序方法中,从未排序序列中挑选记录,并将其依次放入已排序序列(初始时为空)的一端的方法,称为( )。 A.希尔排序 B.归并排序 C.插入排序 D.选择排序 16.用某种排序方法对线性表(25,84,21,47,15,27,68,35,20)进行排序时,记录序列的变化情况如下: (1) (25,84,21,47,15,27,68,35,40) (2) (20,15,21,25,47,27,68,35,84)

数据结构第7章图习题

、单项选择题 1.在一个无向图 G 中,所有顶点的度数之和等于所有边数之和的 _________ 倍 A .l/2 B .1 D .4 2.在一个有向图中, 所有顶点的入度之和等于所有顶点的出度之和的 ________倍 A .l/2 C .2 D .4 3.一个具有 n 个顶点的无向图最多包含 _____ 条边。 A .n B .n +1 C .n-1 D .n(n-1)/2 4.一个具有 n 个顶点的无向完全图包含 _____ 条边。 A .n(n-l) B .n(n+l) C .n(n-l)/2 D .n(n-l)/2 5.一个具有 n 个顶点的有向完全图包含 _____ 条边。 A .n(n-1) B .n(n+l) C .n(n-l)/2 D .n(n+l)/2 6.对于具有 n 个顶点的图,若采用邻接矩阵表示,则该矩阵的大小为 A. n B. n>

点邻接表中的结点总数为_________ 。

B. e C. 2n D. 2e 10.在有向图的邻接表中,每个顶点邻接表链接着该顶点所有邻接点。 A .入边B.出边 C.入边和出边 D .不是入边也不是出边 11.在有向图的逆邻接表中,每个顶点邻接表链接着该顶点所有邻接点。 A .入边B.出边 C.入边和出边 D .不是人边也不是出边 12.如果从无向图的任一顶点出发进行一次深度优先搜索即可访问所有顶点,则 该图一定是 A .完全图B.连通图 C.有回路 D .一棵树 13.采用邻接表存储的图的深度优先遍历算法类似于二叉树的算法。 A .先序遍历B.中序遍历 C.后序遍历 D .按层遍历 14.采用邻接表存储的图的广度优先遍历算法类似于二叉树的算法。 A .先序遍历B.中序遍历 C.后序遍历 D .按层遍历 15.如果无向图G必须进行二次广度优先搜索才能访问其所有顶点,则下列说 法中不正确的是 A. G肯疋不是元全图 B. G 一定不是连通图 C. G中一定有回路 D . G有二个连通分量 16. 下列有关图遍历的说法不正确的是 A .连通图的深度优先搜索是一个递归过程 B. 图的广度优先搜索中邻接点的寻找具有先进先出”的特征 C.非连通图不能用深度优先搜索法 D. 图的遍历要求每一顶点仅被访问一次 17. 下列说法中不正确的是

数据结构第六章习题课

1、下图所示的4棵二叉树中,不是完全二叉树的是() 2、二叉树的前序遍历序列中,任意一个结点均处在其子女结点的前面,这种说法()。 A 、正确 B 、错误 C 、不一定 3、已知某二叉树的后序遍历序列是dabec ,中序遍历序列是debac ,它的前序遍历序列是()。 A 、acbed B 、decab C 、deabc D 、cedba 4、如果T2是由有序树T 转换而来的二叉树,那么T 中结点的后序就是T2中结点的()。 A 、前序 B 、中序 C 、后序 D 、层次序 5、深度为5的二叉树至多有()个结点。 A 、16 B 、32 C 、31 D 、10 6、在一个非空二叉树的中序遍历序列中,根结点的右边()。 A 、只有右子树上的所有结点 B 、只有右子树上的部分结点 C 、只有左子树上的部分结点 D 、只有左子树上的所有结点 7、树最适合用来表示()。 A 、有序数据元素 B 、无序数据元素 C 、元素之间具有分支层次关系的数据 D 、元素之间无联系的数据。 8、任何一棵二叉树的叶结点在先序、中序和后序遍历序列中的相对次序()。 A 、不发生改变 B 、发生改变 C 、不能确定 D 、以上都不对 9、实现任意二叉树的后序遍历的非递归算法而不使用栈结构,最佳方案是二叉树采用()存储结构。 A 、二叉链表 B 、广义表存储结构 C 、三叉链表 D 、顺序存储结构 10、对一个满二叉树,m 个树叶,n 个结点,深度为h ,则()。 A 、n=m+h B 、h+m=2n C 、m=h-1 D 、n=2h -1 11、设n ,m 为二叉树上的两个结点,在中序遍历时,n 在m 前的条件是()。 A 、n 在m 右方 B 、n 是m 祖先 C 、n 在m 左方 D 、n 是m 子孙 12.已知一算术表达式的中缀形式为 A+B*C-D/E ,后缀形式为ABC*+DE/- , A B C D

数据结构第7章

数据结构第7章-图习题

第7章图 一、单项选择题 1.在一个无向图G中,所有顶点的度数之和等于所有边数之和的______倍。 A.l/2 B.1 C.2 D.4 2.在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的______倍。 A.l/2 B.1 C.2 D.4 3.一个具有n个顶点的无向图最多包含______条边。 A.n B.n+1 C.n-1 D.n(n-1)/2 4.一个具有n个顶点的无向完全图包含______条边。 A.n(n-l) B.n(n+l) C.n(n-l)/2 D.n(n-l)/2 5.一个具有n个顶点的有向完全图包含______条边。 A.n(n-1) B.n(n+l) C.n(n-l)/2 D.n(n+l)/2 6.对于具有n个顶点的图,若采用邻接矩阵表示,则该矩阵的大小为______。 A.n B.n×n C.n-1 D.(n-l) ×(n-l) 7.无向图的邻接矩阵是一个______。 A.对称矩阵B.零矩阵

C.上三角矩阵D.对角矩阵 8.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则表头向量的大小为______。 A.n B.e C.2n D.2e 9.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则所有顶点邻接表中的结点总数为______。 A.n B.e C.2n D.2e 10.在有向图的邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。 A.入边B.出边 C.入边和出边D.不是入边也不是出边 11.在有向图的逆邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。 A.入边B.出边 C.入边和出边D.不是人边也不是出边 12.如果从无向图的任一顶点出发进行一次深度优先搜索即可访问所有顶点,则该图一定是______。 A.完全图B.连通图 C.有回路D.一棵树 13.采用邻接表存储的图的深度优先遍历算法类似于二叉树的______算法。 A.先序遍历B.中序遍历 C.后序遍历 D.按层遍历

数据结构-第六章-图-练习题及答案详细解析(精华版)

图 1. 填空题 ⑴ 设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。 【解答】0,n(n-1)/2,0,n(n-1) 【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。 ⑵ 任何连通图的连通分量只有一个,即是()。 【解答】其自身 ⑶ 图的存储结构主要有两种,分别是()和()。 【解答】邻接矩阵,邻接表 【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。 ⑷ 已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。 【解答】O(n+e) 【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。 ⑸ 已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。 【解答】求第j列的所有元素之和 ⑹ 有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。 【解答】出度

⑺ 图的深度优先遍历类似于树的()遍历,它所用到的数据结构是();图的广度优先遍历类似于树的()遍历,它所用到的数据结构是()。 【解答】前序,栈,层序,队列 ⑻ 对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为(),利用Kruskal 算法求最小生成树的时间复杂度为()。 【解答】O(n2),O(elog2e) 【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Kruskal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。 ⑼ 如果一个有向图不存在(),则该图的全部顶点可以排列成一个拓扑序列。 【解答】回路 ⑽ 在一个有向图中,若存在弧、、,则在其拓扑序列中,顶点vi, vj, vk的相对次序为()。 【解答】vi, vj, vk 【分析】对由顶点vi, vj, vk组成的图进行拓扑排序。 2. 选择题 ⑴ 在一个无向图中,所有顶点的度数之和等于所有边数的()倍。 A 1/2 B 1 C 2 D 4 【解答】C 【分析】设无向图中含有n个顶点e条边,则。

数据结构第七章图

数据结构习题(图) 一、选择题 1.设完全无向图的顶点个数为n,则该图有( B )条边。 A. n-l B. n(n-l)/2 C.n(n+l)/2 D. n(n-l) 2.在一个无向图中,所有顶点的度数之和等于所有边数的( )倍。 A.3 B.2 C.1 D.1/2 3.有向图的一个顶点的度为该顶点的( )。 A.入度 B. 出度 C.入度与出度之和 D.(入度+出度)/2 4.在无向图G (V,E)中,如果图中任意两个顶点vi、vj (vi、vj∈V,vi≠vj)都的,则称该图是( )。 A.强连通图 B.连通图 C.非连通图 D.非强连通图 5.若采用邻接矩阵存储具有n个顶点的一个无向图,则该邻接矩阵是一个( )。 A.上三角矩阵 B.稀疏矩阵 C.对角矩阵 D.对称矩阵 6.若采用邻接矩阵存储具有n个顶点的一个有向图,顶点vi的出度等于邻接矩阵 A.第i列元素之和 B.第i行元素之和减去第i列元素之和 C.第i行元素之和 D.第i行元素之和加上第i列元素之和 7.对于具有e条边的无向图,它的邻接表中有( )个边结点。 A.e-l B.e C.2(e-l) D. 2e 8.对于含有n个顶点和e条边的无向连通图,利用普里姆Prim算法产生最小生成时间复杂性为( ),利用克鲁斯卡尔Kruskal算法产生最小生成树(假设边已经按权的次序排序),其时间复杂性为( )。 A. O(n2) B. O(n*e) C. O(n*logn) D.O(e) 9.对于一个具有n个顶点和e条边的有向图,拓扑排序总的时间花费为O( ) A.n B.n+l C.n-l D.n+e 10.在一个带权连通图G中,权值最小的边一定包含在G的( )生成树中。 A.最小 B.任何 C.广度优先 D.深度优先 二、填空题 1.在一个具有n个顶点的无向完全图中,包含有____条边;在一个具有n个有向完全图中,包含有____条边。 2.对于无向图,顶点vi的度等于其邻接矩阵____ 的元素之和。 3.对于一个具有n个顶点和e条边的无向图,在其邻接表中,含有____个边对于一个具有n个顶点和e条边的有向图,在其邻接表中,含有_______个弧结点。 4.十字链表是有向图的另一种链式存储结构,实际上是将_______和_______结合起来的一种链表。 5.在构造最小生成树时,克鲁斯卡尔算法是一种按_______的次序选择合适的边来构造最小生成树的方法;普里姆算法是按逐个将_______的方式来构造最小生成树的另一种方法。 6.对用邻接表表示的图进行深度优先遍历时,其时间复杂度为一;对用邻接表表示的图进行广度优先遍历时,其时间复杂度为_______。 7.对于一个具有n个顶点和e条边的连通图,其生成树中的顶点数为_______ ,边数为_______。 8.在执行拓扑排序的过程中,当某个顶点的入度为零时,就将此顶点输出,同时将该顶点的所有后继顶点的入度减1。为了避免重复检测顶点的入度是否为零,需要设立一个____来存放入度为零的顶点。 三、简答题 l.回答以下问题:

数据结构第八章习题及答案

习题八查找 一、单项选择题 1.顺序查找法适合于存储结构为()的线性表。 A.散列存储 B. 顺序存储或链式存储 C. 压缩存储 D. 索引存储 2.若查找每个记录的概率均等,则在具有n个记录的连续顺序文件中采用顺序查找法查找一个记录,其平均查找长度ASL为( )。 A. (n-1)/2 B. n/2 C. (n+1)/2 D. n 3.适用于折半查找的表的存储方式及元素排列要求为( ) A.链接方式存储,元素无序 B.链接方式存储,元素有序 C.顺序方式存储,元素无序 D.顺序方式存储,元素有序 4.当在一个有序的顺序存储表上查找一个数据时,即可用折半查找,也可用顺序查找,但前者比后者的查找速度( ) A.必定快 B.不一定 C. 在大部分情况下要快 D. 取决于表递增还是递减5.当采用分块查找时,数据的组织方式为 ( ) A.数据分成若干块,每块内数据有序 B.数据分成若干块,每块内数据不必有序,但块间必须有序,每块内最大(或最小)的数据组成索引块 C. 数据分成若干块,每块内数据有序,每块内最大(或最小)的数据组成索引块 D. 数据分成若干块,每块(除最后一块外)中数据个数需相同 6.二叉树为二叉排序树的充分必要条件是其任一结点的值均大于其左孩子的值、小于其右孩子的值。这种说法()。 A.正确 B. 错误 7. 二叉查找树的查找效率与二叉树的((1) )有关, 在 ((2) )时其查找效率最低。 (1): A. 高度 B. 结点的多少 C. 树型 D. 结点的位置 (2): A. 结点太多 B. 完全二叉树 C. 呈单枝树 D. 结点太复杂。 8.如果要求一个线性表既能较快的查找,又能适应动态变化的要求,则可采用( )查找法。 A. 分快查找 B. 顺序查找 C. 折半查找 D. 基于属性 9.分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是( )。 A.(100,80, 90, 60, 120,110,130) B.(100,120,110,130,80, 60, 90) C.(100,60, 80, 90, 120,110,130) D. (100,80, 60, 90, 120,130,110) 10.下图所示的4棵二叉树,( )是平衡二叉树。 (A)(B)(C)(D) 11.散列表的平均查找长度()。 A.与处理冲突方法有关而与表的长度无关 B.与处理冲突方法无关而与表的长度有关 C.与处理冲突方法有关且与表的长度有关 D.与处理冲突方法无关且与表的长度无关 12. 设有一组记录的关键字为{19,14,23,1,68,20,84,27,55,11,10,79},用链地址法构造散列表,散列函数为H(key)=key MOD 13,散列地址为1的链中有()个

数据结构第7章-答案

一、单选题 C01、在一个图中,所有顶点的度数之和等于图的边数的倍。 A)1/2 B)1 C)2 D)4 B02、在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的倍。 A)1/2 B)1 C)2 D)4 B03、有8个结点的无向图最多有条边。 A)14 B)28 C)56 D)112 C04、有8个结点的无向连通图最少有条边。 A)5 B)6 C)7 D)8 C05、有8个结点的有向完全图有条边。 A)14 B)28 C)56 D)112 B06、用邻接表表示图进行广度优先遍历时,通常是采用来实现算法的。 A)栈 B)队列 C)树 D)图 A07、用邻接表表示图进行深度优先遍历时,通常是采用来实现算法的。 A)栈 B)队列 C)树 D)图 A08、一个含n个顶点和e条弧的有向图以邻接矩阵表示法为存储结构,则计算该有向图中某个顶点出度的时间复杂度为。 A)O(n) B)O(e) C)O(n+e) D)O(n2) C09、已知图的邻接矩阵,根据算法思想,则从顶点0出发按深度优先遍历的结点序列是。 A)0 2 4 3 1 5 6 B)0 1 3 6 5 4 2 C)0 1 3 4 2 5 6 D)0 3 6 1 5 4 2 B10、已知图的邻接矩阵同上题,根据算法,则从顶点0出发,按广度优先遍历的结点序列是。 A)0 2 4 3 6 5 1 B)0 1 2 3 4 6 5 C)0 4 2 3 1 5 6 D)0 1 3 4 2 5 6 D11、已知图的邻接表如下所示,根据算法,则从顶点0出发按深度优先遍历的结点序列是。 A)0 1 3 2 B)0 2 3 1 C)0 3 2 1 D)0 1 2 3 A12、已知图的邻接表如下所示,根据算法,则从顶点0出发按广度优先遍历的结点序列是。

数据结构第六章树和二叉树习题及答案

习题六树和二叉树 一、单项选择题 1.以下说法错误的是() A. 树形结构的特点是一个结点可以有多个直接前趋 B. 线性结构中的一个结点至多只有一个直接后继 C. 树形结构可以表达(组织)更复杂的数据 D. 树(及一切树形结构)是一种”分支层次”结构 E. 任何只含一个结点的集合是一棵树 2. 下列说法中正确的是() A. 任何一棵二叉树中至少有一个结点的度为2 B. 任何一棵二叉树中每个结点的度都为2 C. 任何一棵二叉树中的度肯定等于2 D. 任何一棵二叉树中的度可以小于2 3. 讨论树、森林和二叉树的关系,目的是为了() A. 借助二叉树上的运算方法去实现对树的一些运算 B. 将树、森林按二叉树的存储方式进行存储 C. 将树、森林转换成二叉树 D. 体现一种技巧,没有什么实际意义4.树最适合用来表示() A. 有序数据元素 B .无序数据元素 C.元素之间具有分支层次关系的数据 D .元素之间无联系的数据 5.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是()A.9 B .11 C .15 D .不确定 6. 设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1, M2和M3与森林F 对应的二叉树根结点的右子树上的结点个数是()。 A.M1 B .M1+M2 C .M3 D .M2+M3 7.一棵完全二叉树上有1001个结点,其中叶子结点的个数是() A.250 B .500 C .254 D .505 E .以上答案都不对 8. 设给定权值总数有n 个,其哈夫曼树的结点总数为() A. 不确定 B . 2n C . 2n+1 D . 2n-1 9.二叉树的第I 层上最多含有结点数为() I I-1 I-1 I A.2I B .2 I-1 -1 C .2 I-1 D .2 I -1 10.一棵二叉树高度为h, 所有结点的度或为0,或为2,则这棵二叉树最少有()结点A.2h B .2h-1 C .2h+1 D .h+1 11. 利用二叉链表存储树,则根结点的右指针是()。 A.指向最左孩子 B .指向最右孩子 C .空D .非空 12.已知一棵二叉树的前序遍历结果为为()。 A.CBEFDA B .FEDCBA 13.已知某二叉树的后序遍历序列是()。 ABCDEF中序遍历结果 为 C .CBEDFA D dabec, 中序遍历序列是 CBAEDF则后序遍历的结 果 .不定 debac , 它的前序遍历是

数据结构第7章 图习题

第7章图 一、单项选择题 1.在一个无向图G中,所有顶点的度数之和等于所有边数之和的______倍。 A.l/2 B.1 C.2 D.4 2.在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的______倍。 A.l/2 B.1 C.2 D.4 3.一个具有n个顶点的无向图最多包含______条边。 A.n B.n+1 C.n-1 D.n(n-1)/2 4.一个具有n个顶点的无向完全图包含______条边。 A.n(n-l) B.n(n+l) C.n(n-l)/2 D.n(n-l)/2 5.一个具有n个顶点的有向完全图包含______条边。 A.n(n-1) B.n(n+l) C.n(n-l)/2 D.n(n+l)/2 6.对于具有n个顶点的图,若采用邻接矩阵表示,则该矩阵的大小为______。 A.n B.n×n C.n-1 D.(n-l) ×(n-l) 7.无向图的邻接矩阵是一个______。 A.对称矩阵B.零矩阵 C.上三角矩阵D.对角矩阵 8.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则表头向量的大小为______。 A.n B.e C.2n D.2e 9.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则所有顶点邻接表中的结点总数为______。

A.n B.e C.2n D.2e 10.在有向图的邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。 A.入边B.出边 C.入边和出边D.不是入边也不是出边 11.在有向图的逆邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。 A.入边B.出边 C.入边和出边D.不是人边也不是出边 12.如果从无向图的任一顶点出发进行一次深度优先搜索即可访问所有顶点,则该图一定是______。 A.完全图B.连通图 C.有回路D.一棵树 13.采用邻接表存储的图的深度优先遍历算法类似于二叉树的______算法。 A.先序遍历B.中序遍历 C.后序遍历 D.按层遍历 14.采用邻接表存储的图的广度优先遍历算法类似于二叉树的______算法。 A.先序遍历B.中序遍历 C.后序遍历 D.按层遍历 15.如果无向图G必须进行二次广度优先搜索才能访问其所有顶点,则下列说法中不正确的是______。 A.G肯定不是完全图B.G一定不是连通图 C.G中一定有回路D.G有二个连通分量 16.下列有关图遍历的说法不正确的是______。 A.连通图的深度优先搜索是一个递归过程 B.图的广度优先搜索中邻接点的寻找具有“先进先出”的特征 C.非连通图不能用深度优先搜索法 D.图的遍历要求每一顶点仅被访问一次 17.下列说法中不正确的是______。 A.无向图中的极大连通子图称为连通分量

数据结构习题集第章图

第7章图 一、选择题 1.一个有n 个顶点的无向图最多有()条边。 A、n B、n(n-1) C、n(n-1)/2 D、2n 2.具有6 个顶点的无向图至少有()条边才能保证是一个连通图。 A、5 B、6 C、7 D、8 3.具有n 个顶点且每一对不同的顶点之间都有一条边的图被称为()。 A、线性图 B、无向完全图 C、无向图 D、简单图 4.具有4个顶点的无向完全图有()条边。 A、6 B、12 C、16 D、20 5.G是一个非连通无向图,共有28 条边,则该图至少有()个顶点。 A、6 B、7 C、8 D、9 6.存储稀疏图的数据结构常用的是()。 A、邻接矩阵 B、三元组 C、邻接表 D、十字链表 7.对一个具有n个顶点的图,采用邻接矩阵表示则该矩阵的大小为()。 A、n B、(n-1)2 C、(n+1)2 D、n2 8.设连通图G的顶点数为n,则G 的生成树的边数为()。 A、n-1 B、n C、2n D、2n-1 9.对于一个具有N个顶点和E条边的无向图,若采用邻接表表示,则表头向量的大小为((1));所有邻接表 中的结点总数是((2))。 (1)A、N B、N+1 C、N-1 D、N+E (2)A、E/2 B、E C、2E D、N+E 10.对于一个具有n个顶点和e条边的无向图,若采用邻接表表示,则表向量的大小为(),所有顶点邻接表 的结点总数为()。 A、n B、n+1 C、n-1 D、2n E、e/2 F、e G、2e H、n+e 11.在有向图的邻接表存储结构中,顶点v在表结点中出现的次数是()。 A、顶点v 的度 B、顶点v 的出度 C、顶点v 的入度 D、依附于顶点v 的边数 12.已知一个图,若从顶点a出发进行深度和广度优先搜索遍历,则可能得到的顶点序列分别为()和() (1) A、abecdf B、acfebd C、acebfd D、acfdeb (2) A、abcedf B、abcefd C、abedfc D、acfdeb 13.采用邻接表存储的图的深度和广度优先搜索遍历算法类似于二叉树的()和()。 A、中序遍历 B、先序遍历 C、后序遍历 D、层次遍历 14.已知一有向图的邻接表存储结构如下图所示,分别根据图的深度和广度优先搜索遍历算法,从顶点v1出发,

数据结构 第六章 图 练习题及答案详细解析

图 1. 填空题 ⑴设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。 【解答】0,n(n-1)/2,0,n(n-1) 【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。 ⑵任何连通图的连通分量只有一个,即是()。 【解答】其自身 ⑶图的存储结构主要有两种,分别是()和()。 【解答】邻接矩阵,邻接表 【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。 ⑷已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。 【解答】O(n+e) 【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。 ⑸已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。 【解答】求第j列的所有元素之和 ⑹有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。 【解答】出度 ⑺图的深度优先遍历类似于树的()遍历,它所用到的数据结构是();图的广度优先遍历类似于树的()遍历,它所用到的数据结构是()。 【解答】前序,栈,层序,队列 ⑻对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为(),利用Kruskal 算法求最小生成树的时间复杂度为()。 【解答】O(n2),O(elog2e) 【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Kruskal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。 ⑼如果一个有向图不存在(),则该图的全部顶点可以排列成一个拓扑序列。 【解答】回路 ⑽在一个有向图中,若存在弧、、,则在其拓扑序列中,顶点vi, vj, vk的相对次序为()。 【解答】vi, vj, vk

数据结构第七章图练习及答案

1.拓扑排序的结果不是唯一的,试写出下图任意2个不同的拓扑序列。 2.写出求以下AOE网的关键路径的过程。要求:给出每一个事件和每一个活动的最早开 始时间和最晚开始时间。 【解析】解题关键是弄清拓扑排序的步骤 (1)在AOV网中,选一个没有前驱的结点且输出;(2)删除该顶点和以它为尾的弧;(3)重复上述步骤直至全部顶点均输出或不再有无前驱的顶点。 【答案】(1)0132465 (2)0123465 【解析】求关键路径首先求关键活动,关键活动ai的求解过程如下 (1)求事件的最早发生时间ve(j), 最晚发生时间vl(j); (2)最早发生时间从ve(0)开始按拓扑排序向前递推到ve(6), 最晚发生时间从vl(6)按逆拓扑排序向后递推到vl(0); (3)计算e(i),l(i):设ai由弧表示,持续时间记为dut,则有下式成立 e(i)=ve(j) l(i)=vl(k)-dut() (4)找出e(i)-l(i)=0的活动既是关键活动。 【答案】

关键路径为:a0->a4->a6->a9 7.1选择题 1.对于一个具有n个顶点和e条边的有向图,在用邻接表表示图时,拓扑排序算法时间复杂度为(B) A)O(n) B)O(n+e) C)O(n*n) D)O(n*n*n) 2.设无向图的顶点个数为n,则该图最多有(B)条边。 A)n-1 B)n(n-1)/2 C)n(n+1)/2 D)n2 3.连通分量指的是(B) A)无向图中的极小连通子图 B)无向图中的极大连通子图 C)有向图中的极小连通子图 D)有向图中的极大连通子图 4.n个结点的完全有向图含有边的数目(D) A)n*n B)n(n+1) C)n/2 D)n*(n-1) 5.关键路径是(A) A)AOE网中从源点到汇点的最长路径 B)AOE网中从源点到汇点的最短路径 C)AOV网中从源点到汇点的最长路径 D)AOV网中从源点到汇点的最短路径 6.有向图中一个顶点的度是该顶点的(C) A)入度B)出度C)入度与出度之和D)(入度+出度)/2 7.有e条边的无向图,若用邻接表存储,表中有(B)边结点。 A) e B)2e C)e-1 D)2(e-1) 8.实现图的广度优先搜索算法需使用的辅助数据结构为(B)

数据结构第八章习题及答案教学提纲

数据结构第八章习题 及答案

习题八查找 一、单项选择题 1.顺序查找法适合于存储结构为()的线性表。 A.散列存储 B. 顺序存储或链式存储 C. 压缩存储 D. 索引存储 2.若查找每个记录的概率均等,则在具有n个记录的连续顺序文件中采用顺序查找法查找一个记录,其平均查找长度ASL为( )。 A. (n-1)/2 B. n/2 C. (n+1)/2 D. n 3.适用于折半查找的表的存储方式及元素排列要求为( ) A.链接方式存储,元素无序 B.链接方式存储,元素有序C.顺序方式存储,元素无序 D.顺序方式存储,元素有序 4.当在一个有序的顺序存储表上查找一个数据时,即可用折半查找,也可用顺序查找,但前者比后者的查找速度( ) A.必定快 B.不一定 C. 在大部分情况下要快 D. 取决于表递增还是递减 5.当采用分块查找时,数据的组织方式为 ( ) A.数据分成若干块,每块内数据有序 B.数据分成若干块,每块内数据不必有序,但块间必须有序,每块内最大(或最小)的数据组成索引块 C. 数据分成若干块,每块内数据有序,每块内最大(或最小)的数据组成 索引块 D. 数据分成若干块,每块(除最后一块外)中数据个数需相同 6.二叉树为二叉排序树的充分必要条件是其任一结点的值均大于其左孩子的值、小于其右孩子的值。这种说法()。 A.正确 B. 错误 7. 二叉查找树的查找效率与二叉树的((1) )有关, 在 ((2) )时其查找效率最低。 (1): A. 高度 B. 结点的多少 C. 树型 D. 结点的位置 (2): A. 结点太多 B. 完全二叉树 C. 呈单枝树 D. 结点太复 杂。 8.如果要求一个线性表既能较快的查找,又能适应动态变化的要求,则可采用( )查找法。 A. 分快查找 B. 顺序查找 C. 折半查找 D. 基于属性9.分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是( )。 A.(100,80, 90, 60, 120,110,130) B.(100,120,110,130,80, 60, 90) C.(100,60, 80, 90, 120,110,130) D. (100,80, 60, 90,120,130,110)

数据结构第7章作业 图答案

第7章 图 一、单选题 ( C )1. 在一个图中,所有顶点的度数之和等于图的边数的 倍。 A .1/2 B. 1 C. 2 D. 4 ( B )2. 在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的 倍。 A .1/2 B. 1 C. 2 D. 4 ( B )3. 有8个结点的无向图最多有 条边。 A .14 B. 28 C. 56 D. 112 ( C )4. 有8个结点的无向连通图最少有 条边。 A .5 B. 6 C. 7 D. 8 ( C )5. 有8个结点的有向完全图有 条边。 A .14 B. 28 C. 56 D. 112 ( B )6. 用邻接表表示图进行广度优先遍历时,通常是采用 来实现算法的。 A .栈 B. 队列 C. 树 D. 图 ( A )7. 用邻接表表示图进行深度优先遍历时,通常是采用 来实现算法的。 A .栈 B. 队列 C. 树 D. 图 ( )8. 已知图的邻接矩阵,根据算法思想,则从顶点0出发按深度优先遍历的结点序列是 ( D )9. 已知图的邻接矩阵同上题8,根据算法,则从顶点0出发,按深度优先遍历的结点序列是 A . 0 2 4 3 1 5 6 B. 0 1 3 5 6 4 2 C. 0 4 2 3 1 6 5 D. 0 1 3 4 2 5 6 ( C )11. 已知图的邻接矩阵同上题8,根据算法,则从顶点0出发,按广度优先遍历的结点序列是 A . 0 2 4 3 1 6 5 B. 0 1 3 5 6 4 2 C. 0 1 2 3 4 6 5 D. 0 1 2 3 4 5 6 ( D )12. 已知图的邻接表如下所示,根据算法,则从顶点0出发按深度优先遍历的结点序列是 ( A )13. 已知图的邻接表如下所示,根据算法,则从顶点0出发按广度优先遍历的结点序列是 ??? ? ?? ? ? ? ? ? ???????????0100011101100001011010110011001000110010011011110A .0 1 3 2 B. 0 2 3 1 C. 0 3 2 1 D. 0 1 2 3

数据结构第七章图练习及答案

数据结构第七章图练习及答案 1( 拓扑排序的结果不是唯一的,试写出下图任意2个不同的拓扑序列。 2(写出求以下AOE网的关键路径的过程。要求:给出每一个事件和每一个活动的最早开始时间和最晚开始时间。 【解析】解题关键是弄清拓扑排序的步骤 (1)在AOV网中,选一个没有前驱的结点且输出;(2)删除该顶点和以它为尾的弧;(3)重复上述步骤直至全部顶点均输出或不再有无前驱的顶点。 【答案】(1)0132465 (2)0123465 【解析】求关键路径首先求关键活动,关键活动ai的求解过程如下 (1)求事件的最早发生时间ve(j), 最晚发生时间vl(j); (2)最早发生时间从ve(0)开始按拓扑排序向前递推到ve(6), 最晚发生时间从vl(6)按逆拓扑排序向后递推到 vl(0); (3)计算e(i),l(i):设ai由弧表示,持续时间记为dut,则有下式成立 e(i)=ve(j) l(i)=vl(k)-dut()

(4)找出e(i)-l(i)=0的活动既是关键活动。 【答案】 关键路径为:a0->a4->a6->a9 7.1 选择题 1(对于一个具有n个顶点和e条边的有向图,在用邻接表表示图时,拓扑排序算法时间复 杂度为( B ) A) O(n) B) O(n+e) C) O(n*n) D) O(n*n*n) 2(设无向图的顶点个数为n,则该图最多有( B )条边。 A)n-1 B)n(n-1)/2 C) n(n+1)/2 D)n2 3(连通分量指的是( B ) A) 无向图中的极小连通子图 B) 无向图中的极大连通子图 C) 有向图中的极小连通子图 D) 有向图中的极大连通子图 4(n个结点的完全有向图含有边的数目( D ) A)n*n B)n(n+1) C)n/2 D)n*(n-1) 5(关键路径是( A ) A) AOE网中从源点到汇点的最长路径

《数据结构》第八章习题参考答案 (1)

《数据结构》第八章习题参考答案 一、判断题(在正确说法的题后括号中打“√”,错误说法的题后括号中打“×”) 1、用邻接矩阵法存储一个图所需的存储单元数目与图的边数有关。( ×) 2、有e条边的无向图,在邻接表中有e个结点。(×) 3、强连通图的各顶点间均可达。(√) 4、无向图的邻接矩阵一定是对称矩阵,有向图的邻接矩阵一定是非对称矩阵。(×) 5、一个网(带权图)都有唯一的最小生成树。( ×) 6、最小生成树问题是构造连通网的最小代价生成树。( √) 7、关键路径是AOE网中从源点到终点的最长路径。(√) 8、在AOE图中,关键路径上活动的时间延长多少,整个工程的时间也就随之延长多少。(√) 9、n个顶点的完全有向图的边数为n(n-1)。(√) 10、稀疏图的存储结构采用邻接表比较合适。(√) 11、在图G的最小生成树T中,可能会有某条边的权值超过未选边的权值。(√) 二、单项选择题 1.具有4个顶点的无向完全(边数为n*(n-1)/2)图有(A)条边。 A.6 B.12 C.16 D.20 2.下列哪一种图的邻接矩阵是对称矩阵?(B) A.有向图B.无向图C.AOV网D.AOE网 3、在图采用邻接矩阵存储时,求最小生成树的Prim算法的时间复杂度为( C)。 A. O(n) B. O(n+e) C. O(n2) D. O(n3) 4、(1). 求从指定源点到其余各顶点的迪杰斯特拉(Dijkstra)最短路径算法中弧上权不能为负的原因是在实际应用中无意义; (2). 利用Dijkstra求每一对不同顶点之间的最短路径的算法时间是O(n3) ;(图用邻接矩阵表示) (3). Floyd求每对不同顶点对的算法中允许弧上的权为负,但不能有权和为负的回路。 上面不正确的是(A)。 A.(1),(2),(3) B.(1) C.(1),(3) D.(2),(3) 5、下列说法不正确的是( C )。 A.图的遍历是从给定的源点出发每一个顶点仅被访问一次 B.遍历的基本算法有两种:深度遍历和广度遍历 C.图的深度遍历不适用于有向图 D.图的深度遍历是一个递归过程 三、填空题

相关文档
最新文档