复习树的表示-双亲表示法

  1. 给定一个二叉树(双亲表示法)和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

代码:

/*
	树的表示-双亲表示法 
*/
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

void findSpecPath(struct PTree tree, int tar);

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	char nodes[MAX_SIZE] = "";
	
	scanf("%d", &tree.n);
	
	tree.node[0].data = '6', tree.node[0].parent = -1;
	tree.node[1].data = '3', tree.node[1].parent = 0;
	tree.node[2].data = '1', tree.node[2].parent = 1;
	tree.node[3].data = '3', tree.node[3].parent = 2;
	tree.node[4].data = '7', tree.node[4].parent = 0;
	tree.node[5].data = '2', tree.node[5].parent = 0;
	tree.node[6].data = '5', tree.node[6].parent = 5;
	tree.node[7].data = '7', tree.node[7].parent = 5;
	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");

	printf("所有根结点到叶子结点值之和为13的路径为:\n");
	findSpecPath(tree, 13); 
	
	return 0;
} 



// 给定一个二叉树和一个目标和,找到所有从根节点到叶子
// 节点路径总和等于给定目标和的路径。
// 算法概述:统计每个叶子结点到根节点的结点值之和,等于
// 目标和的时候逆序输出这些结点值 
void findSpecPath(struct PTree tree, int tar) {
	int sum = 0;
	int flag = 0;
	int i = 0, j = 0, k = 0;
	struct PTNode p;// 工作结点
	char node[MAX_SIZE] = {0};
	
	for (i = 0; i < tree.n; i++) {
		j = 0, flag = 1;
		while (j < tree.n) {
			if (tree.node[j++].parent == i)
				flag = 0;// 标记为非叶子结点 
		}
		if (flag) {
			j = 0;
			p = tree.node[i];
			sum = p.data - '0';
			node[j++] = p.data;
			while (p.parent != -1) {// 统计结点值之和 
				p = tree.node[p.parent];
				sum += (p.data - '0');
				node[j++] = p.data;
			}
			node[j] = '\0';
			if (sum == tar) {
				for (k = j - 1; k >= 0; k--)
					printf("%c ", node[k]);
				printf("\n");
			}
		} 
	} 
}

运行结果:
在这里插入图片描述

++++++++++++++++++++++++++++++++++++分割线+++++++++++++++++++++++++++++++++++

更一个

  1. 祖父结点值为偶数的结点和

代码:

/*
	树的表示-双亲表示法 
*/
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2); 
int getLowestLeavesCount(struct PTree tree); 
int getDegreeAndSpeNodes(struct PTree tree, char nodes[]); 
int getOneChiNodeAmt(struct PTree tree);
int graFaEvNoSum(struct PTree tree);

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	char nodes[MAX_SIZE] = "";
	
	scanf("%d", &tree.n);
	tree.node[0].data = '6', tree.node[0].parent = -1;
	tree.node[1].data = '8', tree.node[1].parent = 0;
	tree.node[2].data = '9', tree.node[2].parent = 1;
	tree.node[3].data = '3', tree.node[3].parent = 2;
	tree.node[4].data = '1', tree.node[4].parent = 0;
	tree.node[5].data = '2', tree.node[5].parent = 0;
	tree.node[6].data = '5', tree.node[6].parent = 5;
	tree.node[7].data = '7', tree.node[7].parent = 5;
	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
	
	printf("所有的祖父结点为偶数的结点的和为%d\n", graFaEvNoSum(tree));
	
	return 0;
} 

// 祖父结点值为偶数的结点和
// 算法概述:遍历树中的各个结点,若当前结点的祖父结点为偶数
// 则累加当前结点 
int graFaEvNoSum(struct PTree tree) {
	int i = 0;
	int sum = 0;
	int faIndex = 0;// 父结点下标 
	
	for (i = 0; i < tree.n; i++) {
		faIndex = tree.node[i].parent;
		if (faIndex == -1)// 当前结点没有父结点 
			continue;
		faIndex = tree.node[faIndex].parent;
		if (faIndex == -1)// 当前结点没有祖父结点 
			continue;
		 
		if ((tree.node[faIndex].data - '0') % 2 == 0)
			sum += (tree.node[i].data- '0');
	}
	
	return sum;
}

++++++++++++++++++++++++++++++++++++分割线+++++++++++++++++++++++++++++++++++

更一个

  1. 双亲结点树,求所给树的度以及各自的度跟树的树的度一样的结点,放入一个char型数组中

代码:

/*
	树的表示 
*/
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2); 
int getLowestLeavesCount(struct PTree tree); 
int getDegreeAndSpeNodes(struct PTree tree, char nodes[]); 

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	char nodes[MAX_SIZE] = "";
	
	scanf("%d", &tree.n);
	tree.node[0].data = 'A', tree.node[0].parent = -1;
	tree.node[1].data = 'B', tree.node[1].parent = 0;
	tree.node[2].data = 'E', tree.node[2].parent = 1;
	tree.node[3].data = 'H', tree.node[3].parent = 2;
	tree.node[4].data = 'C', tree.node[4].parent = 0;
	tree.node[5].data = 'D', tree.node[5].parent = 0;
	tree.node[6].data = 'F', tree.node[6].parent = 5;
	tree.node[7].data = 'G', tree.node[7].parent = 5;
//	tree.node[8].data = 'I', tree.node[8].parent = 3;
//	tree.node[9].data = 'J', tree.node[9].parent = 3;
//	getchar();
//	for (i = 0; i < tree.n; i++) {
//		scanf("%c%d", &tree.node[i].data, &tree.node[i].parent);
//		getchar();
//	}
//	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
//	
//	p = tree.node[tree.n - 1];
//	while (p.parent != -1) {
//		printf("%c->", p.data);
//		p = tree.node[p.parent];
//	} 
//	printf("%c\n", p.data);

	//printf("%d\n", getLeavesCount(tree));
	//getDataAndLayer(tree);
	//getNearestPaNode(tree, 3, 1);
	//printf("%d\n", getLowestLeavesCount(tree));
	
	int treeDegree = getDegreeAndSpeNodes(tree, nodes);
	printf("树的度为:%d, 结点的度与树的度一样的结点有:%s\n", treeDegree, nodes);
	
	return 0;
} 

// 双亲结点树,求所给树的度以及各自的度跟树的树的度一样的结点,放入一个char型数组中 
// 树的度:树内所有结点度的最大值 
int getDegreeAndSpeNodes(struct PTree tree, char nodes[]) {
	int max = 0; 
	int degree = 0;// 某个几点的度 
	int degrees[MAX_SIZE] = {0};// degrees[i]表示下标为i的结点的度 
	int i = 0, j = 0;
	
	for (i = 0; i < tree.n; i++) {// 计算各个结点的度,同时得出树的度 
		j = 0, degree = 0;
		while (j < tree.n) {
			if (tree.node[j++].parent == i)
				degree++;
		}
		degrees[i] = degree;
		if (degree > max)
			max = degree;
	} 
	
	j = 0;// 记录跟树的度一样的结点的个数 
	for (i = 0; i < tree.n; i++) {
		if (degrees[i] == max) {
			nodes[j++] = tree.node[i].data;
		}
	}
	nodes[j] = '\0';
	

	return max;
}

  1. 计算树中第i层结点的个数

代码:

// 计算树中第i层结点的个数
int getILayerNodesAmt(struct PTree tree, int i) {
	int iAmt = 0;// 第i层结点的个数 
	int layer = 0;
	int j = 0;
	struct PTNode p;// 工作结点 

	for (j = 0; j < tree.n; j++) {// 计算所有结点的层数 
		layer = 1;
		p = tree.node[j];
		while (p.parent != -1) {
			p = tree.node[p.parent];
			layer++;
		}
		if (layer == i) 
			iAmt++;
	}
	
	return iAmt;
} 
  1. 计算树中度为1的结点个数

代码:

// 计算树中度为1的结点个数 
// 所谓度为1,实际就是树的结点中有且仅有1个结点的parent域是
// 当前结点下标,那么当前结点的度为1 
int getOneChiNodeAmt(struct PTree tree) {
	int i = 0, j = 0; 
	int count = 0;// 度为1的结点个数
	int degree = 0;// 某个结点的度
	 
	for (i = 0; i < tree.n; i++) {
		j = 0, degree = 0;
		while (j < tree.n) {
			if (tree.node[j++].parent == i)
				degree++;
		} 
		if (degree == 1)
			count++;
	} 
	
	return count;
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

更一个

  1. 给定一个双亲表示法的树,求最低一层中结点的个数

代码:

/*
	树的表示 
*/
#include<stdio.h>
#include<string.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2); 
int getLowestLeavesCount(struct PTree tree); 

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	
	scanf("%d", &tree.n);
	tree.node[0].data = 'A', tree.node[0].parent = -1;
	tree.node[1].data = 'B', tree.node[1].parent = 0;
	tree.node[2].data = 'E', tree.node[2].parent = 1;
	tree.node[3].data = 'H', tree.node[3].parent = 2;
	tree.node[4].data = 'C', tree.node[4].parent = 0;
	tree.node[5].data = 'D', tree.node[5].parent = 0;
	tree.node[6].data = 'F', tree.node[6].parent = 5;
	tree.node[7].data = 'G', tree.node[7].parent = 5;
//	tree.node[8].data = 'I', tree.node[8].parent = 3;
//	tree.node[9].data = 'J', tree.node[9].parent = 3;
//	getchar();
//	for (i = 0; i < tree.n; i++) {
//		scanf("%c%d", &tree.node[i].data, &tree.node[i].parent);
//		getchar();
//	}
//	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
//	
//	p = tree.node[tree.n - 1];
//	while (p.parent != -1) {
//		printf("%c->", p.data);
//		p = tree.node[p.parent];
//	} 
//	printf("%c\n", p.data);

	//printf("%d\n", getLeavesCount(tree));
	//getDataAndLayer(tree);
	//getNearestPaNode(tree, 3, 1);
	printf("%d\n", getLowestLeavesCount(tree));
	
	return 0;
} 

// 给定一个双亲表示法的树,求最低一层中结点的个数 
// 算法概述:记录每个叶子结点所在层数,然后求出最大值的个数即可
int getLowestLeavesCount(struct PTree tree) {
	int i = 0, j = 0;
	int max = 0;// 最大层数 
	int flag = 0;// 标记当前结点是否为叶子结点 
	int layer = 0;// 所在层数 
	int count = 0;// 叶子结点数量
	int lowestLeavesCount = 0;
	int leafLayers[MAX_SIZE]; 
	struct PTNode p;// 工作结点
	 
	for (i = 0; i < tree.n; i++) {// 记录每个叶子结点所在层数
		j = 0, flag = 0;
		while (j < tree.n) {
			if (tree.node[j++].parent == i) {
				flag = 1;
				break; 
			}
		}
		if (!flag) {// 是叶子结点 
			layer = 1;
			p = tree.node[i];
			while (p.parent != -1) {// 计算叶子结点所在层数 
				p = tree.node[p.parent];
				layer++;
			}
			leafLayers[count] = layer;
			if (layer > max)
				max = layer;// 更新最大层数 
			
			count++; 
		}
	}	 
	
	for (i = 0; i < count; i++) {// 找最大层数的结点个数 
		printf("%d ", leafLayers[i]);
		if (leafLayers[i] == max) {
			lowestLeavesCount++;
		}
	}
	printf("\n");
	
	return lowestLeavesCount;
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

更一个

  1. 双亲表示法的树中,取出两个结点最近的公共祖先结点

代码:

/*
	树的表示 
*/
#include<stdio.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2); 

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	
	scanf("%d", &tree.n);
	tree.node[0].data = 'A', tree.node[0].parent = -1;
	tree.node[1].data = 'B', tree.node[1].parent = 0;
	tree.node[2].data = 'E', tree.node[2].parent = 1;
	tree.node[3].data = 'H', tree.node[3].parent = 2;
	tree.node[4].data = 'C', tree.node[4].parent = 0;
	tree.node[5].data = 'D', tree.node[5].parent = 0;
	tree.node[6].data = 'F', tree.node[6].parent = 5;
	tree.node[7].data = 'G', tree.node[7].parent = 5;
//	tree.node[8].data = 'I', tree.node[8].parent = 3;
//	tree.node[9].data = 'J', tree.node[9].parent = 3;
//	getchar();
//	for (i = 0; i < tree.n; i++) {
//		scanf("%c%d", &tree.node[i].data, &tree.node[i].parent);
//		getchar();
//	}
//	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
//	
//	p = tree.node[tree.n - 1];
//	while (p.parent != -1) {
//		printf("%c->", p.data);
//		p = tree.node[p.parent];
//	} 
//	printf("%c\n", p.data);

	//printf("%d\n", getLeavesCount(tree));
	//getDataAndLayer(tree);
	getNearestPaNode(tree, 6, 7);
	
	return 0;
} 

// 双亲表示法的树中,取出两个结点最近的公共祖先结点
// 算法概述:往上分别找两个结点的双亲结点并用两个数组将它们
// 存起来,然后找两个数组中第一个相同元素即为答案 
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2) {
	int i = 0;
	int count1 = 0, count2 = 0;// 每个结点的父结点个数 
	int parentIndexes1[MAX_SIZE] = {0};// 分别存放两个结点的父结点 
	int parentIndexes2[MAX_SIZE] = {0};
	struct PTNode p1 = tree.node[nodeIndex1];// 初始化两个工作结点 
	struct PTNode p2 = tree.node[nodeIndex2];
	
	parentIndexes1[count1++] = nodeIndex1;// 保存自身下标 
	while (p1.parent != -1) {
		parentIndexes1[count1++] = p1.parent;// 保存父结点下标 
		p1 = tree.node[p1.parent];
	}
	
	parentIndexes2[count2++] = nodeIndex2;// 保存自身下标 
	while (p2.parent != -1) {
		parentIndexes2[count2++] = p2.parent;// 保存父结点下标 
		p2 = tree.node[p2.parent];
	}
	
	for (i = 0; i < (count1 < count2 ? count1 : count2); i++) {
		if (parentIndexes1[i] == parentIndexes2[i]) {
			printf("最近父结点为:下标%d,数据%c\n", parentIndexes1[i], tree.node[parentIndexes1[i]].data);
			break;
		}
	}
}

改进版代码:

// 双亲表示法的树中,取出两个结点最近的公共祖先结点
// 算法概述:定义一个标记数组isPaIndex,isPaIndex[i]表示i为当前结点某一祖先结点的下标
// 找第一个结点祖先结点,并标记其下标,然后找第二个结点的祖先结点,若此下标已被标记,
// 则即为最近祖先结点 
void getNearestPaNode(struct PTree tree, int nodeIndex1, int nodeIndex2) {
	int i = 0;
	int count = 0;// 第一个结点的祖先结点个数 
	int isPaIndex[MAX_SIZE] = {0};
	struct PTNode p = tree.node[nodeIndex1];// 初始化第工作结点 
	
	memset(isPaIndex, 0, sizeof(isPaIndex));
	isPaIndex[nodeIndex1] = 1;// 标记自身下标 
	while (p.parent != -1) {
		isPaIndex[p.parent] = 1;// 标记祖先结点下标 
		p = tree.node[p.parent];
	}
	
	if (isPaIndex[nodeIndex2]) {// 自身即为最近公共祖先结点 
		printf("最近祖先结点为:下标%d,数据%c\n", nodeIndex2, tree.node[nodeIndex2].data);
		return ;
	}
	
	p = tree.node[nodeIndex2];
	while (p.parent != -1) {
		if (isPaIndex[p.parent]) {
			printf("最近祖先结点为:下标%d,数据%c\n", p.parent, tree.node[p.parent].data);
			break;
		}
		p = tree.node[p.parent];
	}
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

树的双亲表示法结构如下:

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

下面是一些练习:

  1. 计算叶子结点数目

代码:

/*
	树的表示 
*/
#include<stdio.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	
	scanf("%d", &tree.n);
	tree.node[0].data = 'A', tree.node[0].parent = -1;
	tree.node[1].data = 'B', tree.node[1].parent = 0;
	tree.node[2].data = 'E', tree.node[2].parent = 1;
	tree.node[3].data = 'H', tree.node[3].parent = 2;
	tree.node[4].data = 'C', tree.node[4].parent = 0;
	tree.node[5].data = 'D', tree.node[5].parent = 0;
	tree.node[6].data = 'F', tree.node[6].parent = 5;
	tree.node[7].data = 'G', tree.node[7].parent = 5;
//	tree.node[8].data = 'I', tree.node[8].parent = 3;
//	tree.node[9].data = 'J', tree.node[9].parent = 3;
//	getchar();
//	for (i = 0; i < tree.n; i++) {
//		scanf("%c%d", &tree.node[i].data, &tree.node[i].parent);
//		getchar();
//	}
//	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
//	
//	p = tree.node[tree.n - 1];
//	while (p.parent != -1) {
//		printf("%c->", p.data);
//		p = tree.node[p.parent];
//	} 
//	printf("%c\n", p.data);

	printf("%d\n", getLeavesCount(tree));
	//getDataAndLayer(tree);
	
	return 0;
} 

// 计算叶子结点数目 
// 叶子结点:没有结点的父结点下标是当前结点的下标,那么当前结点为父结点 
int getLeavesCount(struct PTree tree) {
	int count = 0;
	int flag = 0;// 标记某结点是否存在孩子结点 
	int i = 0, j = 0;
	
	for (i = 0; i < tree.n; i++) {
		j = 0, flag = 0;
		while (j < tree.n) {
			if (tree.node[j++].parent == i)
				flag = 1;
		}
		if (!flag)
			count++; 
	} 
	return count;
} 
 
  1. 计算并输出树中每个叶子结点的data域值与所在的层数

代码:

/*
	树的表示 
*/
#include<stdio.h>
#define MAX_SIZE 105

// 树的结点 
struct PTNode {
	char data;
	int parent;
};

// 树 
struct PTree {
	struct PTNode node[MAX_SIZE];
	int n;// 结点个数 
};

int getLeavesCount(struct PTree tree);
void getDataAndLayer(struct PTree tree);

int main() {
	struct PTree tree;
	struct PTNode p;// 工作指针 
	int i = 0;
	
	scanf("%d", &tree.n);
	tree.node[0].data = 'A', tree.node[0].parent = -1;
	tree.node[1].data = 'B', tree.node[1].parent = 0;
	tree.node[2].data = 'E', tree.node[2].parent = 1;
	tree.node[3].data = 'H', tree.node[3].parent = 2;
	tree.node[4].data = 'C', tree.node[4].parent = 0;
	tree.node[5].data = 'D', tree.node[5].parent = 0;
	tree.node[6].data = 'F', tree.node[6].parent = 5;
	tree.node[7].data = 'G', tree.node[7].parent = 5;
//	tree.node[8].data = 'I', tree.node[8].parent = 3;
//	tree.node[9].data = 'J', tree.node[9].parent = 3;
//	getchar();
//	for (i = 0; i < tree.n; i++) {
//		scanf("%c%d", &tree.node[i].data, &tree.node[i].parent);
//		getchar();
//	}
//	
	printf("树中所有结点为:\n");
	for (i = 0; i < tree.n; i++) {
		printf("%c ", tree.node[i].data);
	}
	printf("\n");
//	
//	p = tree.node[tree.n - 1];
//	while (p.parent != -1) {
//		printf("%c->", p.data);
//		p = tree.node[p.parent];
//	} 
//	printf("%c\n", p.data);

	//printf("%d\n", getLeavesCount(tree));
	getDataAndLayer(tree);
	
	return 0;
} 

// 计算并输出树中每个叶子结点的data域值与所在的层数
// 叶子结点:树的结点中没有以当前结点的下标为它的parent域,那么当前结点为叶子结点 
void getDataAndLayer(struct PTree tree) {
	int i = 0, j = 0;
	int flag = 0;
	int layer = 0;// 结点的层数 
	struct PTNode p;// 工作结点 
	
	for (i = 0; i < tree.n; i++) {
		j = 0, flag = 0;
		while (j < tree.n) {
			if (tree.node[j++].parent == i) {
				flag = 1;
				break;
			}
		}
			
		if (!flag) {// 当前结点为叶子结点 
			printf("叶子结点:%c,", tree.node[i].data);
			layer = 1; 
			p = tree.node[i];
			while (p.parent != -1) {
				p = tree.node[p.parent];// 指向父结点
				layer++; 
			}
			printf("所在层数为:%d\n", layer);
		}
	}
	
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章