《数据结构(C语言版)第二版》第五章-树和二叉树(算法设计题)

用的二叉树例子

在这里插入图片描述

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行的值进行自减。*/    
		}
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值