更
- 给定一个二叉树(双亲表示法)和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
代码:
/*
树的表示-双亲表示法
*/
#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");
}
}
}
}
运行结果:
++++++++++++++++++++++++++++++++++++分割线+++++++++++++++++++++++++++++++++++
更一个
- 祖父结点值为偶数的结点和
代码:
/*
树的表示-双亲表示法
*/
#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;
}
++++++++++++++++++++++++++++++++++++分割线+++++++++++++++++++++++++++++++++++
更一个
- 双亲结点树,求所给树的度以及各自的度跟树的树的度一样的结点,放入一个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;
}
- 计算树中第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个结点的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;
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
更一个
- 给定一个双亲表示法的树,求最低一层中结点的个数
代码:
/*
树的表示
*/
#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;
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
更一个
- 双亲表示法的树中,取出两个结点最近的公共祖先结点
代码:
/*
树的表示
*/
#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;// 结点个数
};
下面是一些练习:
- 计算叶子结点数目
代码:
/*
树的表示
*/
#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;
}
- 计算并输出树中每个叶子结点的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);
}
}
}