用的二叉树例子
AB#C#D###
EF###
GH#IJ#### (下图少一个J结点,J为I结点的左孩子)
AB#C#D##EF##GH#IJ#### (下图少一个J结点,J为I结点的左孩子)
以二叉链表作为二叉树的存储结构,编写以下算法:
习题1
统计二叉树的叶结点个数。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
int LeafNodeCount(BiTree T);
int main()
{
BiTree T = NULL;
InitBiTree(T);
CreateBiTree(T);
printf("先序序列为: ");
preOrderTraverse(T);
printf("\n中序序列为: ");
InOrderTraverse(T);
printf("\n后序序列为: ");
posOrderTraverse(T);
printf("\n叶子结点个数 : %d", LeafNodeCount(T));
return 0;
}
void InitBiTree(BiTree& T)
{
T = NULL;
}
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
int LeafNodeCount(BiTree T)
{
int num = 0;
if (!T)
{
return 0;
}
else
{
printf("\nT = %c\n", T->data);
if (T->lchild == NULL && T->rchild == NULL)
{
return 1;
}
else
{
if (T->lchild)
{
printf("T->lchild = %c\n", T->lchild->data);
}
else
{
printf("T->lchild = %c\n", '#');
}
if (T->rchild)
{
printf("T->rchild = %c\n", T->rchild->data);
}
else
{
printf("T->rchild = %c\n", '#');
}
int m = LeafNodeCount(T->lchild);
int n = LeafNodeCount(T->rchild);
return m + n;
}
}
}
习题2
判别两棵树是否相等。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
int JudgeEqual(BiTree T1, BiTree T2);
int main()
{
BiTree T1 = NULL;
BiTree T2 = NULL;
int c = 0;
char choice = '\0';
while (1)
{
InitBiTree(T1);
InitBiTree(T2);
CreateBiTree(T1);
printf("T1先序序列为: ");
preOrderTraverse(T1);
printf("\nT1中序序列为: ");
InOrderTraverse(T1);
printf("\nT1后序序列为: ");
posOrderTraverse(T1);
printf("\n\n");
getchar();
CreateBiTree(T2);
printf("T2先序序列为: ");
preOrderTraverse(T1);
printf("\nT2中序序列为: ");
InOrderTraverse(T1);
printf("\nT2后序序列为: ");
posOrderTraverse(T1);
printf("\nT1与T2是否相等 : %d\n", JudgeEqual(T1, T2));
printf("\n是否继续?(y/n): ");
scanf_s(" %c", &choice); //这里的"%c"前面必须要有空格,否则输入y也会退出主函数
getchar(); // 清除输入缓冲区中的换行符
if (choice != 'y' && choice != 'Y')
break;
printf("\n\n");
}
return 0;
}
void InitBiTree(BiTree& T)
{
T = NULL;
}
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
int JudgeEqual(BiTree T1, BiTree T2)
{
if (T1 != NULL && T2 == NULL || T1 == NULL && T2 != NULL)
{
return 0; //不相等
}
else if(T1 == NULL && T2 == NULL)
{
return 1; //相等
}
else //两个都不为空
{
if (T1->data == T2->data)
{
int m = JudgeEqual(T1->lchild, T2->lchild);
int n = JudgeEqual(T1->rchild, T2->rchild);
if (m == 1 && n == 1)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;//不相等
}
}
}
int JudgeEqual(BiTree T1, BiTree T2)
{
if (T1 != NULL && T2 == NULL || T1 == NULL && T2 != NULL)
{
return 0; //不相等
}
else if(T1 == NULL && T2 == NULL)
{
return 1; //相等
}
else //两个都不为空
{
if (T1)
{
printf("\nelse : T1 = %c\n", T1->data);
}
else
{
printf("\nelse : T1 = %c\n", '#');
}
if (T2)
{
printf("\nelse : T2 = %c\n", T2->data);
}
else
{
printf("\nelse : T2 = %c\n", '#');
}
if (T1->data == T2->data)
{
if (T1->lchild)
{
printf("T1->lchild = %c\n", T1->lchild->data);
}
else
{
printf("T1->lchild = %c\n", '#');
}
if (T2->lchild)
{
printf("T2->lchild = %c\n", T2->lchild->data);
}
else
{
printf("T2->lchild = %c\n", '#');
}
int m = JudgeEqual(T1->lchild, T2->lchild);
printf("\nm = %d\n", m);
if (T1->rchild)
{
printf("T1->rchild = %c\n", T1->rchild->data);
}
else
{
printf("T1->rchild = %c\n", '#');
}
if (T2->rchild)
{
printf("T2->rchild = %c\n", T2->rchild->data);
}
else
{
printf("T2->rchild = %c\n", '#');
}
int n = JudgeEqual(T1->rchild, T2->rchild);
printf("\nn = %d\n", n);
if (m == 1 && n == 1)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;//不相等
}
}
}
习题3
交换二叉树每个结点的左孩子和右孩子。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
void changeLRchild(BiTree& T);
int main()
{
BiTree T = NULL;
int c = 0;
char choice = '\0';
while (1)
{
InitBiTree(T);
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
printf("\n\n");
changeLRchild(T);
printf("交换每个结点的左右孩子之后,二叉树的先序序列为: ");
preOrderTraverse(T);
printf("\n交换每个结点的左右孩子之后,二叉树的中序序列为: ");
InOrderTraverse(T);
printf("\n交换每个结点的左右孩子之后,二叉树的后序序列为: ");
posOrderTraverse(T);
printf("\n是否继续?(y/n): ");
scanf_s(" %c", &choice); //这里的"%c"前面必须要有空格,否则输入y也会退出主函数
getchar(); // 清除输入缓冲区中的换行符
if (choice != 'y' && choice != 'Y')
break;
printf("\n\n");
}
return 0;
}
void InitBiTree(BiTree& T)
{
T = NULL;
}
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
//交换二叉树每个结点的左孩子和右孩子
void changeLRchild(BiTree& T)
{
BiTree temp = NULL;
if (T == NULL)
{
return;
}
else
{
temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
changeLRchild(T->lchild);
changeLRchild(T->rchild);
}
}
习题4
设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说, 先访问这个结点, 再按双序遍历它的左子树, 然后再一次访问这个结点, 接下来按双序遍历它的右子树)。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
void DoublepreOrderTraverse(BiTree& T);
int main()
{
BiTree T = NULL;
int c = 0;
char choice = '\0';
while (1)
{
InitBiTree(T);
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
printf("\n\n");
printf("二叉树的双序序列为: ");
DoublepreOrderTraverse(T);
printf("\n是否继续?(y/n): ");
scanf_s(" %c", &choice); //这里的"%c"前面必须要有空格,否则输入y也会退出主函数
getchar(); // 清除输入缓冲区中的换行符
if (choice != 'y' && choice != 'Y')
break;
printf("\n\n");
}
return 0;
}
void InitBiTree(BiTree& T)
{
T = NULL;
}
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
void DoublepreOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
DoublepreOrderTraverse(T->lchild);
printf("%c", T->data);
DoublepreOrderTraverse(T->rchild);
}
}
习题5
计算二叉树最大的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
int CountNode_KLevel(BiTree T, int k);
int Depth(BiTree T);
int* NumCount_KLevel(BiTree T);
int Max_array(int* s, int n);
/*
ABC##DE#G##F###
-*a##b##c##
ABD##E##C##
-+a##*b##-c##d##/e##f##
*/
int main()
{
BiTree T = NULL;
int h = 0;
int* s = NULL;
int c = 0;
char choice = '\0';
while (1)
{
InitBiTree(T);
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
printf("\n\n");
h = Depth(T);
s = NumCount_KLevel(T);
printf("二叉树的最大宽度为: %d", Max_array(s, h));
printf("\n是否继续?(y/n): ");
scanf_s(" %c", &choice); //这里的"%c"前面必须要有空格,否则输入y也会退出主函数
getchar(); // 清除输入缓冲区中的换行符
if (choice != 'y' && choice != 'Y')
break;
printf("\n\n");
}
return 0;
}
void InitBiTree(BiTree& T)
{
T = NULL;
}
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
//计算二叉树第k层的结点个数
int CountNode_KLevel(BiTree T,int k)
{
if (T == NULL)
{
return 0;
}
else
{
if (k == 1)
{
return 1;
}
else
{
int m = CountNode_KLevel(T->lchild, k - 1);
int n = CountNode_KLevel(T->rchild, k - 1);
return m + n;
}
}
}
//计算二叉树深度
int Depth(BiTree T)
{
if (T == NULL)
{
return 0;
}
else
{
int m = Depth(T->lchild);
int n = Depth(T->rchild);
if (m >= n)
{
return m+1;
}
else
{
return n+1;
}
}
}
//将二叉树每一层的结点个数写进一个数组中
int* NumCount_KLevel(BiTree T)
{
int* w = NULL;
int h = Depth(T);
int i = 0;
w = (int*)malloc(sizeof(int) * (h+1));
for (i = 1; i <= h; i++)
{
w[i] = CountNode_KLevel(T,i); //不使用w数组中0号单元
}
return w;
}
//计算一个包含n个数的一维整数型数组s中的最大值,并返回其最大值
int Max_array(int* s,int n)
{
int p = s[1]; //数组s中的0号单元不使用
int i = 1;
for (i = 2; i <= n; i++)
{
if (p < s[i])
{
p = s[i];
}
}
return p;
}
-+a##*b##-c##d##/e##f## 的二叉树
习题6
用按层次顺序遍历二叉树的方法, 统计树中度为 1 的结点数目。
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
typedef struct QNode
{
BiTree elem;
struct QNode* next;
}QNode,*QNodeptr;
typedef struct
{
QNodeptr front;
QNodeptr rear;
}LinkQueue;
void InitLinkQueue(LinkQueue& Q);
void EnQueue(LinkQueue& Q, BiTree e);
BiTree DeQueue(LinkQueue& Q);
BiTree Gettop(LinkQueue Q);
int EmptyQueue(LinkQueue Q);
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
int CountNode_1(BiTree& T);
/*
ABC##DE#G##F### //2
AB#C#D### //3
EF### //1
GH#IJ#### //3
AB#C#D##EF##GH#IJ#### //5
*/
int main()
{
BiTree T = NULL;
char choice = '\0';
while (1)
{
InitBiTree(T);
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
printf("\n\n");
printf("T层次遍历序列为: ");
printf("\n二叉树度为1的结点个数为: %d", CountNode_1(T));
printf("\n是否继续?(y/n): ");
scanf_s(" %c", &choice); //这里的"%c"前面必须要有空格,否则输入y也会退出主函数
getchar(); // 清除输入缓冲区中的换行符
if (choice != 'y' && choice != 'Y')
break;
printf("\n\n");
}
return 0;
}
//初始化队列
void InitLinkQueue(LinkQueue& Q)
{
Q.front = (QNodeptr)malloc(sizeof(QNode));
if (!Q.front)
{
printf("初始化队列时,内存分配失败.\n");
return;
}
Q.rear = Q.front;
Q.front->next = NULL;
}
//入队
void EnQueue(LinkQueue& Q, BiTree e)
{
QNodeptr p = NULL;
p = (QNodeptr)malloc(sizeof(QNode));
if (!p)
{
printf("元素入队时,内存分配失败。\n");
return;
}
p->elem = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
//出队
BiTree DeQueue(LinkQueue& Q)
{
if (Q.front == Q.rear)
{
printf("元素出队时,队列为空。\n");
return NULL;
}
QNodeptr p = Q.front->next;
BiTree e = p->elem;
Q.front->next = p->next;
if (p == Q.rear)
{
Q.rear = Q.front;
}
free(p);
return e;
}
//取队头
BiTree Gettop(LinkQueue Q)
{
if (Q.front == Q.rear)
{
printf("取队头元素时,链队为空。\n");
return NULL;
}
return Q.front->next->elem;
}
//判空
int EmptyQueue(LinkQueue Q)
{
if (Q.front == Q.rear)
{
return 1;
}
else
{
return 0;
}
}
//初始化二叉树
void InitBiTree(BiTree& T)
{
T = NULL;
}
//创建二叉树
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
//层次遍历求度为1的结点个数
int CountNode_1(BiTree& T)
{
BiTree p = T;
LinkQueue Q = { NULL,NULL };
InitLinkQueue(Q);
int num = 0;
if (p)
{
EnQueue(Q, p);
while (!EmptyQueue(Q))
{
p = DeQueue(Q);
printf("%c",p->data);
if (p->lchild != NULL && p->rchild == NULL || p->lchild == NULL && p->rchild != NULL)
{
//printf("\n该度为1的结点为:%c\n", p->data);
num++;
}
if (p->lchild != NULL)
{
EnQueue(Q, p->lchild);
}
if (p->rchild != NULL)
{
EnQueue(Q, p->rchild);
}
}
}
return num;
}
? ? ? 习题7(不完整)
求任意二叉树中第一条最长的路径长度, 并输出此路径上各结点的值。
只包括从根节点到各叶子结点的最长路径
不包括跨越根节点的情况(路径中可能包含根结点,也可能不包含),即从左子树的一个节点到右子树的一个节点。
【原因: 求二叉树最长路径长度和 ———— 苍白的咏叹调 】
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
#define MaxSize 1000
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode, * BiTree;
/*
ABC##DE#G##F### //GEDBA
AB#C#D### //DCBA
AB#C#D##EF##GH#IJ#### //JIHGEA
-*a##b##c## //a*-
ABD##E##C## //DBA
*/
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
void LongestPath(BiTree bt);
int main()
{
BiTree T = NULL;
char choice = '\0';
InitBiTree(T);
while (1)
{
printf("请输入要用二叉链表表示的字符先序序列: ");
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
printf("各叶子结点到根结点的最长路径为: ");
LongestPath(T);
printf("\n是否继续?(y/n):");
scanf_s(" %c", &choice);
getchar();
if (choice != 'y' && choice != 'Y')
{
break;
}
printf("\n\n");
}
return 0;
}
//初始化二叉树
void InitBiTree(BiTree& T)
{
T = NULL;
}
//创建二叉树
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
void LongestPath(BiTree bt)//求二叉树中的第一条最长路径长度,并输出最长路径上的节点
{
BiTree p = bt;
BiTree l[MaxSize];
BiTree s[MaxSize]; //l, s是栈,元素是二叉树结点指针,l中保留当前最长路径中的结点
int i = 0;
int j = 0;
int k = 0;
int top = 0;
int tag[MaxSize];
int longest = 0;
while (p || top > 0)
{
while (p)
{
s[++top] = p;
tag[top] = 0;
p = p->lchild;
} //沿左分枝向下
if (tag[top] == 1) //当前结点的右分枝已遍历
{
if (!s[top]->lchild && !s[top]->rchild) //只有到叶子结点时,才查看路径长度
{
if (top > longest)
{
for (i = 1; i <= top; i++)
{
l[i] = s[i];
}
longest = top;
top--;
}//保留当前最长路径到l栈,记住最高栈顶指针,退栈
}
}
//找到tag数组中最后一个0(最后一个还没有访问右子树)
for (j = top; tag[j] != 0; j--)
{
;
}
top = j;
if (top > 0)
{
tag[top] = 1;
p = s[top]->rchild; //沿右子分枝向下
}
}//while(p!=null||top>0)
for (k = longest; k >=1; k--)
{
printf("%c", l[k]->data);
}
}
习题8
输出二叉树中从每个叶子结点到根结点的路径
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
#define MaxSize 1000
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode, * BiTree;
/*
ABC##DE#G##F###
AB#C#D###
AB#C#D##EF##GH#IJ####
-*a##b##c##
ABD##E##C##
*/
void InitBiTree(BiTree& T);
void CreateBiTree(BiTree& T);
void preOrderTraverse(BiTree& T);
void InOrderTraverse(BiTree& T);
void posOrderTraverse(BiTree& T);
void AllPath(BiTree T, TElemType path[], int pathlen);
int main()
{
BiTree T = NULL;
TElemType path[MaxSize];
int pathlen = 0;
char choice = '\0';
InitBiTree(T);
while (1)
{
printf("请输入要用二叉链表表示的字符先序序列: ");
CreateBiTree(T);
printf("T先序序列为: ");
preOrderTraverse(T);
printf("\nT中序序列为: ");
InOrderTraverse(T);
printf("\nT后序序列为: ");
posOrderTraverse(T);
AllPath(T, path, pathlen);
printf("\n是否继续?(y/n):");
scanf_s(" %c", &choice);
getchar();
if (choice != 'y' && choice != 'Y')
{
break;
}
printf("\n\n");
}
return 0;
}
//初始化二叉树
void InitBiTree(BiTree& T)
{
T = NULL;
}
//创建二叉树
void CreateBiTree(BiTree& T)
{
TElemType ch = '\0';
ch = getchar();
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void preOrderTraverse(BiTree& T)
{
if (T)
{
printf("%c", T->data);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiTree& T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
}
void posOrderTraverse(BiTree& T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("%c", T->data);
}
}
/* pathlen是为数组path设定的下标初始值,系统默认从0开始。
在函数执行中pathlen值会发生改变。但由于针对同一个根结点T,其左子树和右子树分别都会使用一次该递归函数。
而左子树和右子树的pathlen是没有关系的,并不是说右子树的pathlen是在左子树的基础上改变,而是都根据其根结点T进行递归时的情况走。
因此不能给pathlen加引用符,使得左右子树在递归时都有自己的pathlen。
即每次执行AllPath函数时的参数pathlen都是相互独立的。 */
void AllPath(BiTree T, TElemType path[], int pathlen)
{
int i;
if (T != NULL)
{
if (T->lchild == NULL && T->rchild == NULL) //T为叶子结点
{
printf("\n叶子结点%c到根结点的路径为:", T->data);
path[pathlen] = T->data; //将当前叶结点放入路径中
pathlen++;
for (i = pathlen - 1; i >= 0; i--)
printf("%c", path[i]);
}
else
{
//printf("\nelse语句中结点为:%c", T->data);
path[pathlen] = T->data; //将当前结点放入路径中
pathlen++; //路径长度增1(系统默认pathlen从0开始)
/* if (T->lchild)
{
printf("\n进入%c的左子树%c前,path数组为:", T->data, T->lchild->data);
for (i = pathlen - 1; i >= 0; i--)
printf("%c", path[i]);
printf("\n进入%c的左子树%c前,pathlen = %d", T->data, T->lchild->data, pathlen);
} */
AllPath(T->lchild, path, pathlen); //递归扫描左子树
/* if (T->rchild)
{
printf("\n进入%c的右子树%c前,path数组为:", T->data, T->rchild->data);
for (i = pathlen - 1; i >= 0; i--)
printf("%c", path[i]);
printf("\n进入%c的右子树%c前,pathlen = %d", T->data, T->rchild->data, pathlen);
} */
AllPath(T->rchild, path, pathlen); //递归扫描右子树
/* //下面这部分,仅指示当前的根结点T的所在的层次,是否存在对函数结果没有影响
(递归函数本就是一层一层地执行完并返回结果,不需要使用额外的变量使其恢复到上一层。)
printf("\n进行%c左右子树递归后,pathlen = %d", T->data, pathlen);
pathlen--; //恢复环境
/*因为函数AllPath的参数pathlen没有加引用符& ,所以在进行左右函数递归时,引起的pathlen值的改变,
并不会影响到不在其函数体内的此处的pathlen,这里的pathlen还是针对第150行的值进行自减。*/
}
}
}