看数据结构写代码(25) 二叉链表 求 宽度,交换左右子树,判断完全二叉树,求节点祖先

这篇博客主要探讨了二叉链表的相关操作,包括如何计算二叉树的宽度,交换左右子树的方法,判断是否为完全二叉树的策略,以及如何找到任意节点的祖先。通过层序遍历,可以有效地解决这些问题。
摘要由CSDN通过智能技术生成

二叉树的宽度是:每一层 节点数的最大值。

思路:根据层序遍历,求出 每一层的节点数,

//纠正 求 二叉树的 宽度问题,
//二叉树的宽度 为 各层次 节点数的 最大值
//算法思路,层序 遍历,

int treeWidth(Tree tree){
	if (tree != NULL)
	{
		int curWidth = 1;//当前层的 节点数
		int nextWidth = 0;//下一层的节点数
		int maxWidth = 1;//最大节点数
		LinkQueue queue;
		queueInit(&queue);
		enqueue(&queue,tree);
		while (!queueEmpty(queue))
		{
			while (curWidth != 0)
			{
				curWidth --;
				dequeue(&queue,&tree);
				if (tree->leftChild != NULL)
				{
					enqueue(&queue,tree->leftChild);
					nextWidth++;
				}
				if (tree->rightChild != NULL)
				{
					enqueue(&queue,tree->rightChild);
					nextWidth++;
				}
			}
			if(nextWidth > maxWidth){
				maxWidth = nextWidth;
			}
			curWidth = nextWidth;
			nextWidth = 0;
		}
		return maxWidth;
	}
	return 0;//空表宽度为0
}


查找任意节点的祖先:

祖先指的是:从根 到 节点 所经过的 所有节点。

//查找祖先
bool treeGetAllParent(Tree tree,ElementType data){
	if (tree != NULL)
	{
		if (tree->data == data)
		{
			return true;
		}
		if (treeGetAllParent(tree->leftChild,data) || treeGetAllParent(tree->rightChild,data))
		{
			printf("%d\t",tree->data);
			return true;
		}

	}
	return false;
}


判断是否是完全二叉树:

思路:层序遍历,在遍历中,遇到空节点 以后,如果 再遇到 一个 非空节点,就不是完全二叉树。

//判断是不是完全二叉树
//利用层序 遍历
//在层序遍历时,出现了 空子树以后,又出现了非空子树,不是完全二叉树
bool treeIsFull(Tree tree){
	bool isFindNull = false;//是不是发现空子树了
	LinkQueue queue;
	queueInit(&queue);
	enqueue(&queue,tree);
	while (!queueEmpty(queue))
	{
		dequeue(&queue,&tree);
		if (tree == NULL)
		{
			isFindNull = true;
		}
		else {
			if(isFindNull)//在 出现了空子树后,出现了 非空节点
			{
				return false;
			}
			else
			{
				//在还没发现空时,所有节点 都得 入队
				//在发现了空了,非空节点不需要入队
				//(算法优化)以前 无判断
				//enqueue(&queue,tree->leftChild);
				if (tree->leftChild != NULL || isFindNull == false)
				{
					enqueue(&queue,tree->leftChild);
				}
				if (tree->rightChild != NULL || isFindNull == false)
				{
					enqueue(&queue,tree->rightChild);
				}
			}
		}
	}
	//销毁队列
	queueDestory(&queue);
	return true;//空树 是完全二叉树
}

交互左右子树:

//交换左右子树
void treeExchangeChild(Tree t){
	if (t != NULL)
	{
		if (t->leftChild != NULL || t->rightChild != NULL)
		{
			Tree temp = t->leftChild;
			t->leftChild = t->rightChild;
			t->rightChild = temp;
		}
		treeExchangeChild(t->leftChild);
		treeExchangeChild(t->rightChild);
	}
}

完整代码:

// binaryTree.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <cstdlib>
#include "stack.h"
#include "queue.h"
#include <math.h>

typedef int ElementType;

typedef  struct TreeNode
{
	ElementType data;
	TreeNode * leftChild;
	TreeNode * rightChild;
} * Tree;

void treeInit(Tree * tree){
	*tree = NULL;
}
//其实 自己 不懂 这个 函数 初始化...
E_State treeCreate(Tree *tree){
	ElementType data;
	scanf("%d",&data);
	if (data == 0)
	{
		*tree = NULL;
	}else
	{
		*tree = (Tree)malloc(sizeof(TreeNode));
		(*tree)->data = data;
		treeCreate(&(*tree)->leftChild);
		treeCreate(&(*tree)->rightChild);
	}
	return E_State_Ok;
}


//后序遍历
void treeClear(Tree * tree){
	if (tree != NULL)
	{
		if ((*tree)->leftChild != NULL)
		{
			treeClear(&(*tree)->leftChild);
		}
		else if((*tree)->rightChild != NULL)
		{
			treeClear(&(*tree)->rightChild);
		}
		free(*tree);
		*tree = NULL;
	}
}

void treeDestory(Tree * tree){
	treeClear(tree);
}

//纠正 求 二叉树的 宽度问题,
//二叉树的宽度 为 各层次 节点数的 最大值
//算法思路,层序 遍历,

int treeWidth(Tree tree){
	if (tree != NULL)
	{
		int curWidth = 1;//当前层的 节点数
		int nextWidth = 0;//下一层的节点数
		int maxWidth = 1;//最大节点数
		LinkQueue queue;
		queueInit(&queue);
		enqueue(&queue,tree);
		while (!queueEmpty(queue))
		{
			while (curWidth != 0)
			{
				curWidth --;
				dequeue(&queue,&tree);
				if (tree->leftChild != NULL)
				{
					enqueue(&queue,tree->leftChild);
					nextWidth++;
				}
				if (tree->rightChild != NULL)
				{
					enqueue(&queue,tree->rightChild);
					nextWidth++;
				}
			}
			if(nextWidth > maxWidth){
				maxWidth = nextWidth;
			}
			curWidth = nextWidth;
			nextWidth = 0;
		}
		return maxWidth;
	}
	return 0;//空表宽度为0
}

//查找祖先
bool treeGetAllParent(Tree tree,ElementType data){
	if (tree != NULL)
	{
		if (tree->data == data)
		{
			return true;
		}
		if (treeGetAllParent(tree->leftChild,data) || treeGetAllParent(tree->rightChild,data))
		{
			printf("%d\t",tree->data);
			return true;
		}

	}
	return false;
}
//判断是不是完全二叉树
//利用层序 遍历
//在层序遍历时,出现了 空子树以后,又出现了非空子树,不是完全二叉树
bool treeIsFull(Tree tree){
	bool isFindNull = false;//是不是发现空子树了
	LinkQueue queue;
	queueInit(&queue);
	enqueue(&queue,tree);
	while (!queueEmpty(queue))
	{
		dequeue(&queue,&tree);
		if (tree == NULL)
		{
			isFindNull = true;
		}
		else {
			if(isFindNull)//在 出现了空子树后,出现了 非空节点
			{
				return false;
			}
			else
			{
				//在还没发现空时,所有节点 都得 入队
				//在发现了空了,非空节点不需要入队
				//(算法优化)以前 无判断
				//enqueue(&queue,tree->leftChild);
				if (tree->leftChild != NULL || isFindNull == false)
				{
					enqueue(&queue,tree->leftChild);
				}
				if (tree->rightChild != NULL || isFindNull == false)
				{
					enqueue(&queue,tree->rightChild);
				}
			}
		}
	}
	//销毁队列
	queueDestory(&queue);
	return true;//空树 是完全二叉树
}

//交换左右子树
void treeExchangeChild(Tree t){
	if (t != NULL)
	{
		if (t->leftChild != NULL || t->rightChild != NULL)
		{
			Tree temp = t->leftChild;
			t->leftChild = t->rightChild;
			t->rightChild = temp;
		}
		treeExchangeChild(t->leftChild);
		treeExchangeChild(t->rightChild);
	}
}

/*
//求二叉树节点的最大路径数.
//一棵二叉树中相距最远的两个节点之间的距离。
//"距离"为两节点之间边的个数
int treeMaxPath(Tree t){
}

//寻找节点child1 和 child2 的最近 共同祖先
//后序遍历 子树
Tree treeFindCommonAncestor(Tree tree,Tree child1,Tree child2){
}*/


//递归算法 先序
void preOrderTraverse(Tree tree){
	if (tree != NULL)
	{
		printf("%d\t",tree->data);
		preOrderTraverse(tree->leftChild);
		preOrderTraverse(tree->rightChild);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	Tree tree;
	printf("---------------创建树(先序,0代表子树为空)-----------------\n");
	treeCreate(&tree);
	printf("------------先序递归遍历----------------\n");
	preOrderTraverse(tree);
	int width = treeWidth(tree);
	char * isFull = treeIsFull(tree) ? "是" : "不是";
	printf("\n树的宽度是:%d,树是否是完全二叉树:%s\n",width,isFull);
	printf("-----------打印5的所有祖先-------------\n");
	treeGetAllParent(tree,5);//打印5的所有祖先。
	printf("\n");
	printf("-----------交互左右子树后-------------\n");
	treeExchangeChild(tree);
	preOrderTraverse(tree);
	printf("\n-----------创建完全二叉树-------------\n");
	Tree fullTree;
	treeCreate(&fullTree);
	isFull = treeIsFull(fullTree) ? "是" : "不是";
	printf("树是否是完全二叉树:%s\n",isFull);
	//及时释放内存是个好习惯..
	treeDestory(&fullTree);
	treeDestory(&tree);
	return 0;
}
运行截图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值