软件工程暑期周总结
作者:互联网
本周完成了数据结构课题第一阶段
一、任务说明
1.时间安排
2.任务描述
要求个人完成实现查找二叉排序树、jmu-ds-实现KMP、关键路径、修建道路、先序和中序构造二叉树。
二、概要设计
1.抽象数据类型
抽象数据类型包括有向图 无向图 和 二叉树 实例均来自于课本或手动设计输入。
2.主程序流程及各程序模块的层次关系
1) 查找二叉排序树
输入:模式串,主串
功能要求:在二叉排序树中查找指定的关键字,并在查找过程中输出查找过程中历经的节点。
基本设计思路:
二叉排序树是可以看作是一个有序表,所以其查找过程和折半查找类似。
首先将待查关键字key与根节点关键字t进行比较:
a.如果key = t, 则返回根节点指针。
b.如果key < t,则进一步查找左子书。
c.如果key > t,则进一步查找右子树。
2)jmu-ds-实现KMP
输入:第一行输入一个整数n,表示测试数据的个数
功能要求:给两个字符串A、B, 从A中找出第一次出现B的位置。
3)关键路径
输入:有向图(顶点序列,有向边序列)
功能要求:能判断是否是AOE网;输出各关键活动或输出关键路径(包括关键路径的长度)
基本设计思路:(1)要找出一个AOE网中的关键路径,就要先找出网里的关键活动,这些关键活动间的路径就是关键路径。
(2)判断一个活动是不是关键活动,方法是要先找到所有活动的最早开始时间和最晚开始时间,并且对它们进行比较,如果二者相等(意味着这个活动在该工程中没有时间松动),说明这个活动是关键活动。
(3)对于活动<Vi, Vj>,它最早的开始时间等于事件Vi最早的发生时间earlist[Vi](事件v的最早发生时间用earlist[v])。假设E[Vi]表示所有到达顶点Vi的弧的集合,len<Vi, Vj>表示活动<Vi, Vj>的持续时间,那么:
注意,这里假设顶点下标从0开始,所以Vi==0,则表示它是源点,因此最早的开始时间为0;当某个顶点不是源点,那么只有在它前面的事件都发生完后,才能轮到这个事件,所以用了max。
(4)对于活动<Vi, Vj>,它最晚的开始时间等于事件Vj最晚的发生时间减去这个活动的持续事件,即latest[Vj]-len<Vi, Vj>(事件v的最晚的发生时间用latest[v])。假设S[Vj]表示所有从顶点Vj出发的弧的集合,len<Vj, Vk>表示活动<Vj, Vk>的持续时间。
4)修建道路
输入格式: 第一行是一个整数N(3<=N<=100),代表村庄的数目。后面的N行,第i行包含N个整数,这N个整数中的第j个整数是第i个村庄和第j个村庄之间的距离,距离值在[1,1000]之间。
然后是一个整数Q(0<=Q<=N*(N+1)/2)。后面给出Q行,每行包含两个整数a和b(1<=a<b<=N),表示在村庄a和b之间已经兴建了路。
功能要求:输出一行仅有一个整数,表示为使所有的村庄连通需要新建公路的长度的最小值。
基本设计思路:鲁斯卡尔(Kruskal)算法从另一途径求网的最小生成树。其基本思想是:假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),概述图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止
5)先序和中序构建二叉树
输入格式:
在第一行中输入元素个数。
第二行中输入先序序列,用空格分隔。
第三行中输入中序序列,用空格分隔。
功能要求:用先序序列和中序序列构造一棵二叉树(树中结点个数不超过10个),并输出其后序序列。
- 设计思路:分别求得根节点的左子树和右子树的先序遍历序列与中序遍历序列
- 分别以左子树和右子树为新树进行第一步操作
- 直至没有子树为止
三、详细设计
- 查找二叉排序树
#include<iostream>
using namespace std;
typedef int KeyType; //定义关键字类型
typedef struct node //记录类型
{
KeyType key; //关键字项
struct node *lchild,*rchild; //左右孩子指针
} BSTNode;
int ReadData(int a[]); //键盘输入若干个整数,顺序保存在数组a中,并返回输入整数的数量。由裁判程序实现,细节不表。
BSTNode *CreatBST(KeyType A[],int n); //顺序读入数组A中的关键字, 依序建立一棵二叉排序树并返回根结点指针。由裁判程序实现,细节不表。
int SearchBST(BSTNode *bt,KeyType k) ; //在函数中输出从根节点出发进行查找的节点路径 ,如果找到k,返回1,否则返回0。
int main()
{
BSTNode *bt = NULL;
KeyType k;
int a[100],N;
N = ReadData( a ) ; //键盘输入若干个整数,存储在数组a[]
bt=CreatBST( a , N ); //根据数组a,创建一棵BST树
scanf( "%d", &k ); //输入待查找的关键字k
if ( SearchBST( bt , k ) ) //在SearchBST函数中输出从根节点出发进行查找的节点路径 ,如果找到k,返回1,否则返回0。
printf(":Found");
else
printf(":NOT Found\n");
return 0;
}
int SearchBST(BSTNode *bt,KeyType k){
printf("%d ",bt->key);
if(bt->key==k){
return 1;
}else{
if(k>bt->key&&bt->rchild!=NULL){
SearchBST(bt->rchild,k);
}else if(k<bt->key&&bt->lchild!=NULL){
SearchBST(bt->lchild,k);
}else if(bt->lchild==NULL&&bt->rchild==NULL){
return 0;
}
}
}
- .jmu-ds-实现KMP
#include <iostream>
using namespace std;
// 递推计算Next数组,模板串为str,模板串长度为len
void get_next(string str, int len, int next[])
{
int i = 0, j = 0;
next[0] = -1;
for (i = 1; i < len; i++) {
while (j > 0 && str[i] != str[j])
j = next[j-1];
if (str[i] == str[j]) j++;
next[i] = j;
}
}
// 在字符串s中匹配字符串t,s长度为len_s,t长度为len_t,t的Next数组为next[],返回t第一次出现的位置
int find_pattern(string s, int len_s, string t, int len_t, int next[])
{
int i = 0, j = 0;
while(i < len_s && j < len_t)
{
//匹配字符
if(j == -1 || s[i] == t[j])
{
j++;
i++;
}
else{
j = next[j];
}
}
if(j == len_t)
return i - j ;
else
return -1;
}
int main()
{
int cas;
string s,t;
int next[100];
cin>>cas;
while (cas --)
{
cin>>s>>t;
int len_s = s.length();
int len_t = t.length();
get_next(t, len_t, next);
int flag = find_pattern(s, len_s, t, len_t, next);
if(flag>0) cout<<flag<<endl;
else cout<<"not find!"<<endl;
}
}
- 关键路径
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N][N],n;
int in[N],dis[N];
int out[N],rdis[N];
int vec[N],cnt;
int main(){
int m;
while(cin>>n>>m){
cnt=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=0;
}
}
memset(in,0,sizeof in);
memset(out,0,sizeof out);
memset(dis,0,sizeof dis);
memset(rdis,0x3f,sizeof rdis);
for(int i=0;i<m;i++){
int u,v,d;
cin>>u>>v>>d;
in[v]++;
out[u]++;
a[u][v]=d;
}
int o=-1;
bool ji=0;
for(int i=1;i<=n;i++){
if(in[i]==0){
if(o==-1){
o=i;
}else{
ji=1;
}
}
}
if(o==-1||ji==1){
cout<<"unworkable project"<<endl;
continue;
}
vec[cnt++]=o;
while(cnt>0){
int p=vec[--cnt];
for(int i=1;i<=n;i++){
if(a[p][i]>0){
in[i]--;
if(dis[i]<dis[p]+a[p][i]){
dis[i]=dis[p]+a[p][i];
}
if(in[i]==0){
vec[cnt++]=i;
}
}
}
}
bool fl=1;
for(int i=1;i<=n;i++){
if(in[i]>0){
fl=0;
}
}
if(fl==0){
cout<<"unworkable project"<<endl;
continue;
}
int tmp=vec[0];
rdis[vec[0]]=dis[vec[0]];
cnt++;
while(cnt>0){
int p=vec[--cnt];
for(int i=1;i<=n;i++){
if(a[i][p]>0){
out[i]--;
if(rdis[i]>rdis[p]-a[i][p]){
rdis[i]=rdis[p]-a[i][p];
}
if(out[i]==0){
vec[cnt++]=i;
}
}
}
}
cout<<dis[tmp]<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]>0&&dis[i]==rdis[i]&&dis[j]==rdis[j]&&dis[i]+a[i][j]==dis[j] ){
cout<<i<<"->"<<j<<endl;
}
}
}
}
return 0;
}
- 修建道路
#include <bits/stdc++.h>
#define MAX_VEX_NUM 105
using namespace std;
typedef struct
{
int vexs[MAX_VEX_NUM];
int arcs[MAX_VEX_NUM][MAX_VEX_NUM];
int vexnum, arcnum;
} Graph;
int lowcost[MAX_VEX_NUM] = {0} ; //记录最短路径
int visited[MAX_VEX_NUM] = {0} ; //记录是否访问过
void Create_G(Graph &G)
{
cin >> G.vexnum ;
int i,j,preroad = 0;
for(i = 1; i <= G.vexnum; ++i)
for(j = 1; j <= G.vexnum ; ++j)
G.arcs[i][j] = INT_MAX;
for(i = 1; i <= G.vexnum; ++i)
{
for(j = 1; j <= G.vexnum ; ++j)
{
cin >> G.arcs[i][j];
}
}
int n;
cin >> n ;
for( i = 0 ; i < n ; ++i)
{
int a,b;
cin >> a >> b ;
G.arcs[a][b] = G.arcs[b][a] = 0; //有路的边全部清零
visited[a];
visited[b];
}
}
int minadj(int a[],int n)
{
int lowest = INT_MAX;
int k = 1;
for( int i = 1; i <= n; i++ )
{
if( a[i] < lowest && !visited[i] )
{
lowest = a[i];
k = i;
}
}
return k;
}
int Prim_Road(Graph G)
{
int i,j,k;
int cost = 0; //记录需要铺设的最短的路
int nums = G.vexnum;
for(i = 1 ; i <= nums; ++i)
{
lowcost[i] = G.arcs[1][i];
visited[i] = 0 ;
}
//从第一个顶点开始
lowcost[1] = 0 ;
visited[1] = true ;
for(i = 1; i <= nums; ++i)
{
k = minadj(lowcost,nums); //找到最小边的邻接点
cost += lowcost[k];
//因为已经连好的路是0,所以一定会经过已经连好的路,此时只记录整个图的最短路径就是所需要铺设的路的长度
visited[k] = true;
// lowcost[k] = 0;
for(j = 1 ; j <= nums; ++j)
{
if(G.arcs[k][j] < lowcost[j] && !visited[j])
{
lowcost[j] = G.arcs[k][j];
}
}
}
return cost;
}
int main()
{
Graph G;
Create_G(G);
cout << Prim_Road(G) << endl;
return 0;
}
- 先序和中序构造二叉树
#include<iostream>
#include<cmath>
using namespace std;
void getlast(int n,int *a,int *b){
if(n<=0){
return ;
}
int root=a[0],i;
for(i=0;i<n;i++){
if(root==b[i])
break;
}
getlast(i,a+1,b);
getlast(n-i-1,a+1+i,b+i+1);
cout<<root<<" ";
}
int main()
{
int n,i;
int a[11],b[11];
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
}
for(i=0;i<n;i++){
cin>>b[i];
}
getlast(n,a,b);
cout<<endl;
return 0;
}
四、调试分析
1、遇到的问题
4.1.1 7-1kmp算法中next数组如何求
4.1.2 7-2如何求关键路径,怎么求关键活动
4.1.3 7-3如何求最短路径,怎么用代码实现
2、解决的方法
翻书看书上的例题,同时看以前的题目熟悉一些定义和做法,上网找例题看别人的思路,再自己思考每一步的作用
五、系统测试
1. 查找二叉排序树
先输入节点的个数,再输入节点生成二叉树,最后输入要查找的数,输出经过的节点和查询结果
2. jmu-ds-实现KMP
输入要查询的个数,再输入主串和子串,输出子串在主串中第一次出现的位置,若没有则输出not find!
3.关键路径
输入AOE网的顶点数和边数,再输入每条边的端点和权值,输出完成工程的最短时间和关键活动
4. 修建道路
输入村庄的数目N,再输入的第i行包含N个整数,这N个整数中的第j个整数是第i个村庄和第j个村庄之间的距离,再输入一个整数Q,后面给出Q行,每行包含两个整数a和b(1<=a<b<=N),表示在村庄a和b之间已经兴建了路。输出使所有的村庄连通需要新建公路的长度的最小值。
5.先序和中序构建二叉树
输入二叉树元素个数,再输入先序序列和中序序列,输出后序序列
六、体会
转眼间,三天已过去第一阶段实验也随之结束了。在这期间我学到了很多。
数据结构旨在使读者学会分析研究数据对象的特性,学会数据的组织方法,以便选择合适的数据逻辑结构和存储结构,以及相应的运算(操作),把现实世界中的问题转化为计算机内部的表示和处理,这是一个良好的程序设计技能训练的过程。
经过这三天的课程设计,我把所学知识全部应用于课程设计当中,同时也将有关数据结构和C语言,C++的知识重新巩固了一遍。通过这次实验,我不仅在理论知识方面有了很大提高,而且思维方面也有很大的进步。这次任务提高了我们对实际问题的解决能力,即运用所学的知识对问题进行分析。
通过编写这几个算法,对这几个算法有了更深的理解、以前从课本上没有理解的东西,在这里得到了理解。
这次实验,让我对自己所学的知识进行了深入巩固和提高。
标签:总结,int,len,next,bt,软件工程,暑期,查找,输入 来源: https://www.cnblogs.com/z13516221762/p/16483879.html