严蔚敏视频 笔记30
为避免每次都要搜索入度为零的顶点,在算法中设置一个“栈”,以保存“入度为零”的顶点
CountInDegree(G,indegree);
// 对各顶点求入度
InitStack(S);
for(i=0;i<G.vexnum;++i)
if(!indegree[i]) Push(S,i);
// 入度为零的顶点入栈
count=0; // 对输出顶点计数
while(!EmptyStack(S)) {
Pop(S,v); ++count; printf(v);
for(w=FirstAdj(v));w;w=NextAdj(G,v,w))
--indegree(w);
if(!indegree[w]) Push(S,w);
// 新产生的入度为零的顶点
}
if(count<G.vexnum) printf("图中有回路");
1。熟悉图的各种存储结构及其构造算法
2。熟练掌握图的两种搜索路径的遍历,深度优先搜索和广度优先搜索,区别图和树之间的相似和差异
3。利用遍历算法求各种简单路径问题
4。理解图中各种图的基本算法
建议习题:
7.2 7.3 7.4 7.7
5.4 广义表的类型定义
ADT GList {
数据对象:
D={ei|i=1,2,…,n;n>=0;ei∈AtomSet或ei∈GList}
数据关系:
LR={<ei-1,ei>|ei-1,ei∈D,2<=i<=n}
基本操作:
// 结构的创建和销毁
InitGList(&L);
DestroyGList(&L);
GreateGList(&L,S);
CopyGList(&T,L);
// 状态函数
GListLength(L);
GListDepth(L);
GListEmpty(L);
GetHead(L);
GetTail(L);
// 插入和删除操作
InsertFirst_GL(&L,e);
DeleteFirst_GL(&L,&e);
// 遍历
Traverse_GL(L,Visit());
}
递归定义的线性结构
一般情况下广义表写成
LS=(α1,α2,…,αn) 其中αi或为原子或为广义表
多层次的线性结构
结构特点:
数据元素有相对次序
长度定义为最外层包含元素个数
深度定义为所含括弧的重数
原子的深度为0 空表的深度为1
可以共享
可以递归
任何一个非空广义表都可以分解为表头和表尾两项,表尾一定是广义表
5.5 广义表的表示方法
头尾指针的链表结构
表结点: tag=1 hp tp
原子结点:tag=0 data
构造存储结构的两种分析方法
空表 ls=NIL
非空表
ls-> 1 指向表头指针 指向表尾指针
若表头为原子 则 0 data
5.6 广义表操作的递归函数
递归函数:
一个含直接或间接调用本函数语句的函数被称为递归函数,必须满足一下两个条件:
每一次调用自己时,必须是更接近于解
必须有一个终止处理或计算的准则
例如hanoi塔
例如二叉树的遍历
借助分治法求解
基本思想:
对输入规模为n的函数或问题,用方法把输入分割成k个子集,从而产生了l个子问题,分别求解这l个子问题,得出l个问题的子解,用某种方法
把它们组合成原来问题的解,反复使用,直至可以直接求解为止
广义表常用分治法求解
广义表的头尾链表存储表示:
typedef enum {ATOM,LIST} ElemTag; // ATOM原子 LIST子表
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom;
struct {struct GLNode *hp,*tp;} ptr;
};
} *GList;
例一 求广义表的深度
广义表的深度=Max{子表的深度}+1
空表的深度=1 原子的深度=0
int GListDepth(GList L) {
if(!L) return 1;
if(L->tag==ATOM) return 0;
for(max=0,pp=L;pp;pp=pp->ptr.tp) {
dep=GListDepth(pp->ptr.hp);
if(dep>max) max=dep;
}
return max+1;
}