其他分享
首页 > 其他分享> > 软件工程暑期周总结

软件工程暑期周总结

作者:互联网

本周完成了数据结构课题第一阶段

一、任务说明

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个),并输出其后序序列。

  1. 设计思路:分别求得根节点的左子树和右子树的先序遍历序列与中序遍历序列
  2. 分别以左子树和右子树为新树进行第一步操作
  3. 直至没有子树为止

三、详细设计

  1. 查找二叉排序树

#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;

        }

    }

}

 

  1. .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;

    }

}

 

  1. 关键路径

#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;

}

 

  1. 修建道路

#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;

}

  1. 先序和中序构造二叉树

#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