数据结构课程教学汇报-李春葆
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法设计思路:
p a1 A 尾插法 B 头插法 p b1 ...... bn ∧
例、假定采用带头节点的单链表保存单词,当两个单词 有相同的后缀时,则可共享相同的后缀存储空间,例如, “loading”和“being”,如下图所示。
str1
l
str2
o
a
d
p
i b e
n
g ∧
设str1和str2分别指向两个单词所在单链表的头节点, 链表节点结构为:
void PathAll(ALGraph *G,int u,int v,int path[],int d) //d是到当前为止已走过的路径长度,调用时初值为-1 { int w,i; ArcNode *p; visited[u]=1; d++; //路径长度增1 path[d]=u; //将当前顶点添加到路径中 if (u==v && d>1) //输出一条路径 { printf(" "); for (i=0;i<=d;i++) printf("%d ",path[i]); printf("\n"); } p=G->adjlist[u].firstarc; //p指向u的第一个邻接点 while (p!=NULL) { w=p->adjvex; //w为u的邻接顶点 if (visited[w]==0) //若顶点未标记访问,则递归访问之 PathAll(G,w,v,path,d); p=p->nextarc //找u的下一个邻接顶点 } visited[u]=0; //恢复环境 }
承上 启下
计算机导论 C语言 离散数学
算法设计与分析 操作系统 编译原理 数据库原理 软件工程
数据结构
„
数据结构课程的要求
掌握基本编 程方法 掌握数据组 织和数据处 理的方法 掌握大型软 件开发方法
基本 要求
课程 关系
C语言
学习识字
数据结构
学习写作文
软件工程
学习写小说 与语文 学习过 程类比
动手能力(上机实验)
例、 假设二叉树采用二叉链存储结构存储,试设计一个算 法,计算一棵给定二叉树的所有单分支节点个数。 解:计算一棵二叉树b中所有单分支节点个数的递归模型f(b) 如下: f(b)=0 若b=NULL f(b)=f(b->lchild)+f(b->rchild)+1
f(b)=f(b->lchild)+f(b->rchild)
其他情况
int count(Node *L) { if (L==NULL) return 0; else return count(L->next)+1; }
(2)正向显示以L为首节点指针的单链表的所有节点值 递归模型如下: f(L)不做任何事件 当L=NULL
f(L)输出L->data;f(L->next)
例、假设图G采用邻接表存储,设计一个算法,输出图G 中从顶点u到v的所有简单路径。 解:所谓简单路径是指路径上的顶点不重复。利用回溯的 深度优先搜索方法。 从顶点u开始进行深度优先搜索,在搜索过程中,需要把 当前的搜索线路记录下来。为此设立一个数组path保存走过的 路径,用d记录走过的路径长度。若当前扫描到的顶点u等于v 时,表示找到了一条路径,则输出路径path。
1、单链表算法设计
基于建表的算法:这类算法直接或间接地转换成建
表过程,如果新建表的次序与原来的次序相同,则
采用尾插法;如果新建表的次序与原来的次序相反, 则采用头插法。 基于查找、插入或删除的算法:这类算法以单链表 的基本运算为基础,包含有节点的查找、插入或删
除操作。
例、设C={a1,b1,a2,b2,…,an,bn}为一线性表,采用带头 节点的hc单链表存放,设计一个就地算法,将其拆分为 两个线性表(它们都用单链表存放),使得: A={a1,a2,…,an},B={b1,b2,…,bn} C a1 A a1 B b1 b2 ...... bn ∧ a2 ...... an ∧ b1 ...... bn ∧
data next
请设计一个时间上尽可能高效的算法,找出由str1和 str2所指向两个链表共同后缀的起始位置(如图中字符i所 在节点的位置p)。要求: (1)给出算法的基本设计思想。 (2)根据设计思想,采用C或C++或JAVA语言描述算 法,关键为之处给出注释。 (3)说明你所设计算法的时间复杂度。 本题为2012年全国考研题。
int visited[MAXV]={0}; //全局变量 void isPath(ALGraph *G,int u,int v,bool &flag) //flag表示uv是否有路径,初始时flag=false { int w; ArcNode *p; visited[u]=1; p=G->adjlist[u].firstarc; //p指向u的第一条边 while (p!=NULL) { w=p->adjvex; //w为u的邻接顶点 if (w==v) { flag=true; return; } else if (visited[w]==0) //若顶点未标记访问,则递归访问之 isPath(G,w,v); //从顶点w出发继续查找 p=p->nextarc //找u的下一个邻接顶点 } }
2、递归算法设计
求递归模型的步骤:
(1)对原问题 f(s)进行分析,称为“大问题”,假设 出合理的“小问题”f(s‘)(与数学归纳法中假设n=k-1时 等式成立相似); (2)假设f(s‘)是可解的,在此基础上确定f(s)的解, 即给出f(s)与f(s’)之间的关系(与数学归纳法中求证 n=k 时等式成立的过程相似); (3)确定一个特定情况(如f(1)或f(0))的解,由此作 为递归出口(与数学归纳法中求证n=1时等式成立相似)。
递归模型 递归算法
例如,设计不带头结点的单链表的相关递归算法 f(L):大问题 L a1 a2 ... an
f(L->next):小问题
为什么在设计单链表的递归算法时不带头节点?
(1)求单链表中数据结点个数
递归模型如下: f(L)=0 当L=NULL
f(L)=f(L->next)+1
递归算法如下:
算法设计思路:
p a1 A 尾插法 B 尾插法 p b1 ...... bn ∧
例、设C={a1,b1,a2,b2,…,an,bn}为一线性表,采用带头 节点的hc单链表存放,设计一个就地算法,将其拆分为 两个线性表(它们都用单链表存放),使得: A={a1,a2,…,an},B={bn,bn-1,…,b1} C a1 A a1 B bn bn-1 ...... b1 ∧ a2 ...... an ∧ b1 ...... bn ∧
else return l;
} }
4、图算法设计
基于深度优先或广度优先遍历算法。
基于深度优先遍历算法的应用
例、假设图G采用邻接表存储,设计一个算法,判断顶 点u到v是否有简单路径。
解:从顶点u开始进行深度优先搜索,当搜索到顶点v时表 明从顶点u到顶点v有路径,即:
u u1 u2
…
v
用形参has(调用时其初值置为false)表示顶点uv是否 有路径。
递归模型: f(b,x,h)=0 f(b,x,h)=h f(b,x,h)=l 当b=NULL 当b->data=x 当l=f(b->lchild,x,h+1)≠0
f(b,x,h)=f(b->rchild,x,h+1) 其他
递归算法如下:
int Level(BTNode *b,ElemType x,int h) //找到值为x节点后h为其层次,否则为0 { if (b==NULL) return 0; else { l=Level(b->lchild,x,h+1); //在左子树中查找 if (l==0) //左子树中未找到时在右子树中查找 return Level(b->rchild,x,h+1); //空树时返回0 else if (b->data==x) return h; //找到节点时
递归算法如下: void traverse(Node *L) { if (L==NULL) return; printf("%d ",L->data); traverse(L->next); }
其他情况
(3)反向显示以L为首节点指针的单链表的所有节点值 递归模型如下:
f(L)不做任何事件
f(L)f(L->next);输出L->data; 递归算法如下: void traverseR(Node *L) { if (L==NULL) return; traverseR(L->next); printf("%d ",L->data); }
算法设计思路:
str1 p
l
str2
o
a
d i
n
g ∧
b
q
e 比较p==q
算法实现:
typedef struct Node { char data; struct Node *next; } SNODE; SNODE * Findlist(SNODE *str1,SNODE *str2) { int m,n; SNODE *p,*q; m=Listlen(str1); //求单链表str1的长度m n=Listlen(str2); //求单链表str2的长度n for (p=str1;m>n;m--) //若m大,则str1后移m-n+1个节点 p=p->next; for (q=str2;m<n;n--) //若n大,则str1后移n-m+1个节点 q=q->next; while (p->next!=NULL && p->next!=q->next) { p=p->next; //p、q两步后移找第一个指针值相等的节点 q=q->next; } return p->next; }
例、假设二叉树采用二叉链存储结构,设计一个算法Level() 求二叉树中值为x的节点的层次(假设节点值唯一)。
解:设 Level(b,x,h)返回二叉链b中data值为x的节点的层数, 其中h表示b所指节点的层数。 b
调用Level(b,x,1)返回x节 点的层数。
b
调用Level(b,x,1)返回x节 点的层数。
二
提炼数据结构解决问题的思路
数据结构解决问题的思路:
ADT = 逻辑结构+抽象运算(功能描述) 映射 运 算 实 现 ①问题描述
存储结构1
…
存储结构n
… 算法nm
②设计存储 结构
算法11
… 源自文库法1m
算法n1
③算法设计 ④算法分析
算法分析
最佳算法
三
归纳数据结构算法设计的通用性方法
1、单链表算法设计 2、递归算法设计 3、二叉树的算法设计 4、图算法设计
2012年全国高等学校计算机程序设 计类课程教学论坛 清华大学出版社
2012年3月●武汉
数据结构课程教学汇报
武汉大学计算机学院 李春葆
2012年3月25日
使用教材:
1
数据结构教程(第3版) 普通高等教育“十一五”国家级规划教材
2
成套教材:
数据结构教程(第3版) 数据结构教程(第3版)学习指导 数据结构教程(第3版)上机实验指导
当L=NULL
其他情况
和上例相比,仅 交换了两个语句
3、二叉树算法设计
b
根
b->lchild
f(b) 大问题
b->rchild
左子树
右子树
当f(b->lchild)和f(b->rchild) 可解时,f(b)就很容易求解 了。
f(b->lchild) 小问题1
f(b->rchild)
小问题2
例、 假设二叉树采用二叉链存储结构存储,试设计一个 算法,计算一棵给定二叉树的所有叶子节点个数。 解:计算一棵二叉树b中所有叶子节点个数的递归模型f(b) 如下: f(b)=0 若b=NULL f(b)=1 若*b为叶子节点
f(b)=f(b->lchild)+f(b->rchild)
其他情况
递归算法如下: int LeafNodes(BTNode *b) { int num1,num2; if (b==NULL) return 0; else if (b->lchild==NULL && b->rchild==NULL) return 1; else { num1=LeafNodes(b->lchild); num2=LeafNodes(b->rchild); return (num1+num2); } }
若*b为单分支节点
其他情况
递归算法如下:
int SSonNodes(BTNode *b) { if (b==NULL) return 0; else if (b->lchild!=NULL && b->rchild==NULL || b->lchild==NULL && b->rchild!=NULL) //为单分支节点 return SSonNodes(b->lchild)+ SSonNodes(b->rchild)+1; else //为双分支节点或叶子节点时 return SSonNodes(b->lchild)+ SSonNodes(b->rchild); }
3
作为成套教材已申报 “十二五”国家级规 划教材,目前被武汉大学审核通过。
数据结构课程教学汇报
清晰地讲授本课程的目的、地位和要求 提炼数据结构解决问题的思路 归纳数据结构算法设计的通用性方法 注重教学的多维性 强化实践教学环节
一
清晰地讲授本课程的目的、地位和要求
计算机科学课程体系(偏软)
后期课程 前期课程