东华复试上机备考踩坑记-17年第三题

(6)从数据结构中树的定义可知,除根结点外,树中的每个结点都有唯一的一个双亲结点。根据这一特性,可用一组连续的存储空间(一维数组)存储树中的各结点。树中的结点除保存结点本身的信息之外,还要保存其双亲结点在数组中的位置(即在数组中的下标。双亲的信息为-1则表示该结点为根结点),树的这种表示法称为双亲表示法。
树的每个结点的数据类型定义如下: struct PTNode { char data; //结点数据域 int
parent; //结点双亲在数组中的位置 }; 树的数据类型定义如下:
#define MAX_TREE_SIZE 100 struct PTree { struct PTNode nodes[MAX_TREE_SIZE]; //存储树中所有结点 int n; //树中共有n个结点,n不超过100 };
则下图1所示的树,按照双亲表示法存储结构,存储为图2所示形式(n为10)。
在这里插入图片描述

已知一棵树已存储为以上形式,请编写函数GetNearestCommonGrand,查找给定的两个(不相同的)结点最近的共同祖先。GetNearestCommonGrand的函数原型为:
char GetNearestCommonGrand(struct PTree T, char nodeData1, char
nodeData2) 函数形参: T:保存了树中结点数目及图2所示的结点数组
nodeData1,nodeData2:给定的两个结点的数据(输入时保证这两个结点存在)。 函数返回值: 两个结点最近的共同祖先。
比如,nodeData1为’G’,nodeData2为’H’,则函数返回’A’。
说明:输入保证nodeData1和nodeData2在树中能找到。

部分代码在prog3.c中,请仅在GetNearestCommonGrand函数中填入内容,完成程序。
要求:尽量优化算法的时间复杂度与空间复杂度,并在GetNearestCommonGrand函数前的注释部分简要介绍自己的算法,同时指出该算法具有什么样的时间复杂度与空间复杂度。
请勿改动主函数main和其它已有函数中的任何内容,可以在函数GetNearestCommonGrand的花括号中填入你编写的若干语句,允许增加自定义函数。

prog3.c中,struct PTree
CreateTree()函数用于从键盘输入树的双亲表示法的信息,创建一棵树。输入的第一个数n表示树中结点数,此后有n行输入,每行表示一个结点的信息,其中第一个信息为结点的数据,第二个信息为结点的双亲结点在数组中的位置。
在main函数中还需要输入两个结点的字符数据,查询这两个结点的最近共同祖先。

如输入(第一行为n,表示共有10个结点,后面10行,为10个结点的信息,最后一行为g和h,表示查询结点g和结点h的最近共同祖先): 10 a
-1 b 0 c 0 d 0 e 1 f 1 g 1 h 2 i 3 j 3 g h 则将创建图b所对应的树。 输出结果为’a’

如输入: 8 a -1 b 0 e 1 h 6 c 0 d 0 f 5 g 5 g h 输出结果为’d’

我的想法是:先找出两结点的所有祖先结点,存储在两个不同的数组中。然后比对两个数组,找出第一个公共祖先结点即可
初始代码如下:

#include <stdio.h>
#define MAX_TREE_SIZE 100
void NONO();
struct PTNode /*树的一个结点*/
{
    char data;
    int parent; /* 双亲位置域 */
};
struct PTree
{    
    struct PTNode nodes[MAX_TREE_SIZE];
    int n; /* 结点数 */
};
/*
请在此介绍自己的算法,并解释算法的时间复杂度与空间复杂度
	往上找结点的祖先,将祖先分别存在两个数组中。
	比对这两个数组,找出最先重合的祖先即可。
*/
char GetNearestCommonGrand(struct PTree T, char nodeData1, char nodeData2)
{
	char ances1[MAX_TREE_SIZE], ances2[MAX_TREE_SIZE];// 存放两结点的祖先结点
	struct PTNode p, q;// 工作指针
	int i = 0, j = 0, m = 0, n = 0;

	for (i = 0; i < T.n; i++) {// 根据两结点数据确定两结点
		if (T.nodes[i].data == nodeData1) {
			p = T.nodes[i];
		}
		if (T.nodes[i].data == nodeData2) {
			q = T.nodes[i];
		}
	}

	i = 0, j = 0;
	p = T.nodes[p.parent];
	while (1) {// 得到第一个结点的所有祖先
		ances1[i++] = p.data;
		p = T.nodes[p.parent];
		if (p.parent == -1) {
			break;
		}
		
	}
	q = T.nodes[q.parent];
	while (1) {// 得到第二个结点的所有祖先
		ances2[j++] = q.data;
		q = T.nodes[q.parent];
		if (q.parent == -1) {
			break;
		}
		
	}

	for (m = 0; m < i; m++) {// 比对两结点的祖先,找出最近的共同祖先
		for (n = 0; n < j; n++) {
			if (ances1[m] == ances2[n]) {
				return ances1[m];
			}
		}
	}

	return (char) 0;

}
struct PTree CreateTree()
{
    int i,n;
    int parentId;
    char ch;
    struct PTree newTree;
    scanf("%d", &n);
    newTree.n=n;
    for (i = 0; i < n; i++)
    {
        scanf(" %c%d", &ch, &parentId);
        newTree.nodes[i].data=ch;
        newTree.nodes[i].parent=parentId;
    }
    return newTree;
}
int main()
{
    struct PTree aTree;
    char node1, node2, nodeGrand;
    aTree = CreateTree();
    scanf(" %c %c", &node1, &node2);
    nodeGrand= GetNearestCommonGrand (aTree, node1, node2);
    printf("%c\n", nodeGrand);
    //NONO();
    return 0;
}
void NONO()
{//本函数用于辅助教师判卷,不需要阅读其中代码,也请不要改动其中代码。
    FILE *fp, *wf ;
	int i,j,n;
	char ch;
	int parentId;
    char node1, node2, nodeGrand;
	struct PTree newTree;
    fp = fopen("p3.in","r");
    wf = fopen("p3.out","w");
    for(i = 0 ; i < 6 ; i++)
	{
		fscanf(fp, "%d", &n);
		newTree.n=n;
		for (j = 0; j < n; j++)
		{
			fscanf(fp," %c%d", &ch, &parentId);
			newTree.nodes[j].data=ch;
			newTree.nodes[j].parent=parentId;
		}
    fscanf(fp," %c %c", &node1, &node2);
    nodeGrand= GetNearestCommonGrand (newTree, node1, node2);
		fprintf(wf, "%c\n", nodeGrand);
	}
    fclose(fp);
    fclose(wf);
}

结果如下:
在这里插入图片描述
看到这里我就有点奇怪了,怎么会输出空格呢?调试后发现问题出在这里:
在这里插入图片描述
这里1和2的顺序反了,这就导致根结点没有被保存下来,所以会输出空格。改过来就好啦
在这里插入图片描述
下次写while循环一定要注意语句的书写顺序呀

发布了34 篇原创文章 · 获赞 6 · 访问量 6121

猜你喜欢

转载自blog.csdn.net/qq_41409120/article/details/103985203
今日推荐