自学考试-上海交通大学-数据结构实践课,自考,计算机科学与技术

0.2022年10月,A卷,;

题目一,

给定一个数组,array = {2,3,38,5,4}, 一个数字n,求数组中是否存在一个序列使得之和等于n,例如n=9,如果存在输出True, 否则输出False,用递归的方法。

//这个问题可以有多个变体:
//1.子集和问题,有回溯法,这个参考的算法比较简洁:https://blog.csdn.net/qq_62899367/article/details/122383351?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169893884816800180655506%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169893884816800180655506&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-122383351-null-null.142^v96^control&utm_term=%E5%AD%90%E9%9B%86%E5%92%8C%E9%97%AE%E9%A2%98&spm=1018.2226.3001.4187

//如果单纯只是判断,是否存在这样的素组,可以使用以下简洁的方法;
//对于有n个元素的数组,对于是否存在某子集使其和等于某数;
//这个问题可以简化,对每个元素来说,是否应该加入到结果子集中;

int sum(int n, int m)    //含有n个元素的集合,是否存在子集使其和为m;
{
    if (sum[n] == m)
        flag = true;
    else if(n == 1)
        return;
    else
    {
        //对于任意元素都是,是否要加入到子集中;
        sum(n - 1, m - sum[n]);    //取了元素n的情况;
        sum(n - 1, m);             //没有取元素n的情况;
    }

}

题目二,

要求在某个节点上建一个健身房,使所有节点到健身房的路程最小;约定相邻节点间的距离为1;

代码我直接复制其他人的,参考:【精选】dijkstra算法详解—简单易懂-CSDN博客

如果有其他更简洁的写法,欢迎提出来。

void dijkstra(){
	//源点为源点start。
	int minn;//记录每趟最短路径中最小的路径值。 
	int pos;//记录得到的minn所对应的下标。
	init();//调用初始化函数。
	visited[start]=true;
	for(int i=1;i<=n;i++){
		//将n个顶点依次加入判断。
		minn=inf;
		for(int j=1;j<=n;j++){
			if(!visited[j]&&dis[j]<minn){
				minn=dis[j];
				pos=j;
			}
		}
		//经过这趟for循环后我们找到的就是我们想要的点,可以确定这点到源点的最终最短距离了。
		visited[pos]=true;//我们将此点并入已知集合。
		//接下来就是更新dis数组了,也就是当前最短距离,这都是针对还没有并入已知集合的点。
		for(int j=1;j<=n;j++){
			if(!visited[j]&&dis[j]>dis[pos]+graph[pos][j])
				dis[j]=dis[pos]+graph[pos][j];
		}
	}
	//退出循环后,所有的点都已并入已知集合中,得到的dis数组也就是最终最短距离了。
	cout<<dis[goal]<<endl;//输出目标点到源点的最短路径长度。
}

dijkstra求最短路径

//上次考的是dijkstra;

这一次考的是

5个城市节点,8个边,每个边的权值为高速公路的造价;

example, 2, 3, 50;  //50为高速公路造价;

五个城市间,造4条高速公路,使总造价最低;

1.2022年10月,B卷,第一题;

1.1.题目:二叉树的先序和中序,求后序;

例如:二叉树的先序遍历为abdec, 中序遍历为dbcae; 求后序遍历;

1.2.解题思路:

考虑递归;先回顾下正常的后序遍历算法;

(自我总结:叶子节点,作为一个子树时,该叶子节点就是该子树的根节点,三种遍历算法就是递归的以一定的顺序遍历根节点;先序遍历是:根节点-左子树的先序遍历-右子树先序遍历;后序遍历是:左子树的后序遍历-右子树的后序遍历-根节点)

/* 此题作为后序遍历算法的变种,一定是这种思路 */
void post()
{
        post();    /* left tree */
        post();    /* right tree */
        printf("root");
}

1.3.其中一种解法(参考:

#include <stdio.h>

char *preorder = "abdec";
char *inorder  = "dbeac";

//very interesting, 每一遍理解都不一样,这里可以理解为,一直在寻找自由一个值的树,然后把它打印出来;
//这一个值可以理解为左子树=右子树=根;
//这个算法的关键是理解inorder中某个子树的根在preorder中的下标;
//i - start的含义:此次遍历,左子树中元素的数量。那么右子树的根在preorder中的下标必然为,root + 1 + (i - stat) = 根的下一个位置+左子树的偏移量;

/* 参数root是先序遍历序列中根的位置下标, start, end是树在中序遍历序列中的起始位置
 * 
 */
void post(int root, int start, int end)
{
        int i;
        for (i = start; i <= end; i++) {
                if (inorder[i] == preorder[root]) {
                        post(root + 1, start, i - 1);    /* 后序遍历左子树 */
                        post(root + (i - start) + 1, i + 1, end);    /* 后序遍历右子树 */
                        printf("%c", preorder[root]);
                }
        }
}

2.2022年10月,B卷,第二题(具体题目记不清了,类似下题);

一班有m个男生,n个女生(m!=n),举办舞会,男女生分别编号坐在舞池两旁,每曲开始时,依次从男生和女生中各出一人配对跳舞,没有配对成功的等待下一曲,设计程序模拟舞伴配对过程。

2.1解题思路,按照队列处理;

  1 #include <stdio.h>
  2
  3 #define MAN 13
  4 #define WOMAN 14
  5 char *man_string = "ABCDEFGHIJKLM";
  6 char *woman_string = "abcdefghijklmn";
  7 
  8 typedef struct {
  9         char *man;
 10         int front;
 11 } man_queue;
 12 
 13 typedef struct {
 14         char *woman;
 15         int front;
 16 } woman_queue;
 17 
 18 void test(void)
 19 {
 20         man_queue dance_man;
 21         woman_queue dance_woman;
 22         dance_man.man = man_string;
 23         dance_woman.woman = woman_string;
 24         dance_man.front = 0;
 25         dance_woman.front = 0;
 26 
 27         while (dance_man.front < MAN) {
 28                 printf("man %c, woman %c\n",
 29                         dance_man.man[dance_man.front],
 30                         dance_woman.woman[dance_woman.front]);
 31 
 32 
 33                 if (dance_man.front == MAN - 1) {
 34                         printf("dance is over!, wait next\n");
 35                         sleep(5);
 36                 }
 37 
 38                 dance_man.front = (dance_man.front + 1) % MAN;
 39                 dance_woman.front = (dance_woman.front + 1) % WOMAN;
 40         }
 41 }
                                                                                                                                        41,1          25%

2023年11月5日,数据结构试卷

第一题:有1,2, 3,.... n个人,依次报数,报数到m时出列,直到所有人都出列;

//这个考试队列的引用;

第二题,

5个城市节点,8个边,每个边的权值为高速公路的造价;

example, 2, 3, 50;  //50为高速公路造价;

五个城市间,造4条高速公路,使总造价最低;

//这次考试Floyd算法,求任意两点间的最短路径;参考:七、最短路径——弗洛伊德(Floyd)算法_floyd算法求最短路径问题_瘦弱的皮卡丘的博客-CSDN博客

void ShortestPath_Floyd(MGraph G, vector<vector<int>>& P, vector<vector<int>>& D)
{
	for (int i = 0; i < G.numVertexte; ++i)
	{
		for (int j = 0; j < G.numVertexte; ++j)
		{
			D[i][j] = G.arc[i][j];//用G的邻接矩阵初始化D
			P[i][j] = j;
		}
 
		for (int i = 0; i < G.numVertexte; ++i)
		{
			for (int j = 0; j < G.numVertexte; ++j)
			{
				for (int w = 0; w < G.numVertexte; ++w)
				{
					if (D[j][w] > D[j][i] + D[i][w])//如果经过下标为i的顶点路径比原两点间路径更短
					{
						D[j][w] = D[j][i] + D[i][w];//更新D的值
						P[j][w] = P[j][i];//更新P的值
					}
				}
			}
		}
	}
}

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值