更
- 給定一個二叉樹(雙親表示法)和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。
代碼:
/*
樹的表示-雙親表示法
*/
#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);
}
}
}