IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C语言描述数据结构 —— 二叉树(3)普通二叉树 -> 正文阅读

[数据结构与算法]C语言描述数据结构 —— 二叉树(3)普通二叉树

1.完全二叉树与普通二叉树的对比

我们前面介绍过完全二叉树以及堆(一种完全二叉树),并且实现了堆用顺序结构存储的数据结构。还介绍了两个基本算法:向上调整算法、向下调整算法。在此基础上使用堆解决了 Top-K 问题,以及堆排序。我们通过完全二叉树的规律可以发现,完全二叉树如果不看最后一层,那么它是一棵满二叉树;最后一层的节点必须是上一层连续节点并且依次是左孩子、右孩子。那么现在要介绍的是普通二叉树。普通二叉树只满足二叉树的基本定义,它不满足完全二叉树的定义。那么普通二叉树的结构可能是下面这几种:

?可以发现普通二叉树的结构没有规律,如果用顺序结构存储的话那么物理空间不一定是连续的。

如果是这样,那么数据的存储就没有意义。我们可以试想一下,当我们真正进行数据存储的时候,我们会把数据不连续的存储起来吗?这样做的意义只有增加工作量、难度而已。?不单单是存储数据没有意义,就连删除也没有意义。我们想要访问二叉树的节点时候也是一个难题。所以普通二叉树我们一般使用链式结构,即用链表串联起来,需要注意,这样做的目的不是赋予它适合增删查改的能力,而是使用链式结构可以实现我们从来没有接触过的功能。例如二叉搜索树:

我们使用百科上面的例子做一个分析:

?当然我们现在是简单的举一些普通二叉树的应用,本篇介绍的目的是为了打好基础,做好铺垫,为以后的学习打下地基。?

2.二叉树的性质

我们实现过堆用顺序结构存储的数据结构,里面也涉及到了不少的二叉树性质。那么现在将详细介绍二叉树的性质。

? ? ? ? 1.若规定根节点的层数为1,那么一颗非空二叉树的第k层最多有 2^(k-1) 个节点?

? ? ? ? 2.若规定根节点的层数为1,那么深度(高度)为h的二叉树最多一共有 2^h-1 个节点?

?????????3.对任意一颗二叉树而言,如果度为2的节点个数为n2,度为0的节点个数为n0,那么有n0=n2+1

?????????4.如果规定根节点的层数为1,那么总共有n个节点的满二叉树的深度就为h=log(n+1)

对应这条性质的解释就是数学公式,总节点数为 2^h-1 ,在这个表达式上计算 h ,就用到了对数。

? ? ? ? 5.在用顺序结构存储的完全二叉树中有下面几个规律:

? ? ? ? ? ? ? ? 1.如果 child != 0 ,那么 parent = (child-1)/2 ;如果 child = 0,那么这个节点为根节点

? ? ? ? ? ? ? ? 2.如果总节点个数为 n,假设 parent*2+1<n ,那么 parent*2+1 的值就是左孩子的下标

? ? ? ? ? ? ? ? 3.如果总节点个数为 n,假设 parent*2+2<n ,那么 parent*2+2 的值就是右孩子的下标

这三条性质在我们实现堆的顺序结构的时候使用过,当然也是基于数学上得来的公式。

2.1二叉树性质有关练习

1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )
A 不存在这样的二叉树
B 200
C 198
D 199
答案: A 。根据公式 n0=n2+1 可知,度为 0 的节点个数比度为 2 的节点个数多一个。
2. 下列数据结构中,不适合采用顺序存储结构的是()
A 非完全二叉树
B
C 队列
D

答案:A。即使队列不推荐使用顺序结构存储,但即使使用,也比非完全二叉树效率高。

3. 在具有 2n 个结点的完全二叉树中,叶子结点个数为()
A n
B n+1
C n-1
D n/2
答案: A 。在二叉树中,节点的分类只有三种,即度为2的节点,度为1的节点和度为0的节点。那么表达式就为 2n = n2+n1+n0 ,又因为 n2=n0+1 ,所以 2n = 2n0-1+n1;又因为 2n 的结果只能是整数,所以 n1 必须等于 1。故n0 = n。
4. 一棵完全二叉树的节点数位为 531 个,那么这棵树的高度为()
A 11
B 10
C 8
D 12
答案: B 。完全二叉树的节点个数在 [2^(h-1),2^h-1] 这个区间内。那么将 10 带入这个表达式之中,那么区间就为 [512,1023] ,恰好 531 在这个区间之内,所以高度为 10。
5. 一个具有 767 个节点的完全二叉树,其叶子节点个数为()
A 383
B 384
C 385
D 386
答案: B 。n2+n1+n0=767,因为n2=n0+1,所以得 2n0-1+n1=767,即2n0+n1=768,因为 2n0 的结果必为偶数,所以n1必为0( 完全二叉树特性,度为1的节点个数要不为0要不为1 ),所以n0=384。

3.二叉树的递归遍历

我们再回顾一下二叉树的性质,我们提到过二叉树是递归定义的。

在任意一颗二叉树中,只有两种可能:要不为空;要不就为根节点、左子树和右子树组成。?

?了解了递归定义之后,我们就着手前序遍历、中序遍历和后序遍历。

  • 前序遍历,在每一颗树中,它的遍历顺序总为:根节点、左子树、右子树。
  • 中序遍历,在每一颗树中,它的遍历顺序总为:左子树、根节点、右子树。
  • 后序遍历,在每一颗树中,它的遍历顺序总为:左子树、右子树、根节点。

注意我的用词,在每一颗树中。每一颗树,相当于左子树是一棵树,左子树当中又分为根节点、左子树和右子树,左子树的左子树又是一颗树,它又分为根节点、左子树和右子树……

我们先画一下前序遍历的顺序图。

?就像这样层层递归,就可以完成遍历。那么中序遍历、后序遍历和前序遍历一样,那么这里的顺序图就省略了,我们直接看结果:

清楚了遍历顺序之后,就可以开始着手代码。这里注意,因为现在的部分是为了后续学习打基础,所以在这里手动构造与例子相同的二叉树。

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

typedef int BinaryData;
typedef struct Node
{
	BinaryData val;
	struct Node* left;
	struct Node* right;
}Node;

Node* CreateNode()
{
	Node* n1 = (Node*)malloc(sizeof(Node));
	assert(n1);
	Node* n2 = (Node*)malloc(sizeof(Node));
	assert(n2);
	Node* n3 = (Node*)malloc(sizeof(Node));
	assert(n3);
	Node* n4 = (Node*)malloc(sizeof(Node));
	assert(n4);
	Node* n5 = (Node*)malloc(sizeof(Node));
	assert(n5);
	Node* n6 = (Node*)malloc(sizeof(Node));
	assert(n6);

	n1->val = 1;
	n2->val = 2;
	n3->val = 3;
	n4->val = 4;
	n5->val = 5;
	n6->val = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}

//前序遍历
void PreTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->val);
	PreTraval(root->left);
	PreTraval(root->right);
}

//中序遍历
void MidTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	MidTraval(root->left);
	printf("%d ", root->val);
	MidTraval(root->right);
}

//后序遍历
void PosTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	PosTraval(root->left);
	PosTraval(root->right);
	printf("%d ", root->val);
}

int main()
{
	Node* root = CreateNode();
	PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");
	return 0;
}

4.递归遍历的衍生问题

了解了遍历之后,现在有很多衍生问题:怎么求节点个数?怎么求第k层的节点个数?如何求叶节点个数?如何查找值为x的节点?

4.1节点个数

我们逐个分析,如何求节点个数。求个数呢,通用方法是计数法,那么计数法在我们的递归上面也可以使用。

//求节点个数
int count = 0;//使用全局变量
int NodeSize(Node* root)
{
	if (root == NULL)
	{
		return 0;
	}
	//static int count = 0;//使用static修饰的静态变量
	count++;
	NodeSize(root->left);
	NodeSize(root->right);
	return count;
}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	printf("NodeSize = %d\n", NodeSize(root));
	printf("NodeSize = %d\n", NodeSize(root));
	return 0;
}

可以看到我们使用计数法是可以帮助我们完成任务的,但是当我们第二次调用这个函数就出现了问题。原因是全局变量和static修饰的静态变量只能被初始化一次。所以我们的计数方法是不够好的,那我们就要着手递归的方法了。

//求节点个数
int NodeSize(Node* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return NodeSize(root->left) + NodeSize(root->right) + 1;
}
//int count = 0;//使用全局变量
//int NodeSize(Node* root)
//{
//	if (root == NULL)
//	{
//		return 0;
//	}
//	//static int count = 0;//使用static修饰的静态变量
//	count++;
//	NodeSize(root->left);
//	NodeSize(root->right);
//	return count;
//}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	printf("NodeSize = %d\n", NodeSize(root));
	printf("NodeSize = %d\n", NodeSize(root));
	return 0;
}

可以看到,递归的方式完美的解决了计数的"BUG"。

4.2第k层的节点个数

通过公式我们就可以发现,k是一定要被减1的,那么在递归当中也不例外。既然是要求某一层的节点个数,我们只要加一个条件:即递归到了指定层数的时候,才有返回值。?

//求第k层的节点个数
int KSize(Node* root,int k)
{
	assert(k > 0);//层数大于0才有意义
	if (root == NULL)
	{
		return 0;
	}
	//加一个特定条件,必须在这一层才具有返回值
	if (k == 1)
	{
		return 1;
	}
	//否则继续往下递归找到指定层数
	return KSize(root->left,k-1) + KSize(root->right,k-1);
}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	printf("KSize = %d\n", KSize(root, 3));
	printf("KSize = %d\n", KSize(root, 1));

	return 0;
}

4.3求叶节点个数

叶节点的特征为度为0,即左右孩子都为空。不言而喻,需要添加一个条件来具有返回值。

//求叶节点的个数
int LeafSize(Node* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return LeafSize(root->left) + LeafSize(root->right);
}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	//printf("KSize = %d\n", KSize(root, 3));
	//printf("KSize = %d\n", KSize(root, 1));

	printf("LeafSize = %d\n", LeafSize(root));
	return 0;
}

?

4.4查找值为x的节点

很明显,我们需要添加一个条件来限定返回值。那么其难点在于,如果左子树当中找到了节点,那么右子树就不要遍历了;如果左子树当中没有找到指定节点才需要遍历右子树。如果左右子树都找不到指定节点才返回空。这时就要用到分治的思想。?

//查找值为x的节点
Node* NodeFind(Node* root, int x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->val == x)
	{
		return root;
	}
	Node* LeftRet = NodeFind(root->left, x);
	if (LeftRet != NULL)
	{
		return LeftRet;
	}
	Node* RightRet = NodeFind(root->right, x);
	if (RightRet != NULL)
	{
		return RightRet;
	}
	return NULL;
}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	//printf("KSize = %d\n", KSize(root, 3));
	//printf("KSize = %d\n", KSize(root, 1));

	//printf("LeafSize = %d\n", LeafSize(root));

	printf("NodeFind = %p\n", NodeFind(root, 1));
	printf("NodeFind = %p\n", NodeFind(root, 3));
	printf("NodeFind = %p\n", NodeFind(root, 100));

	return 0;
}

4.5二叉树的销毁

二叉树的销毁,就是销毁所有的节点。后序遍历是非常契合的。

//二叉树销毁
void BinaryDestroy(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryDestroy(root->left);
	BinaryDestroy(root->right);
	free(root);
}

5.二叉树的非递归遍历

5.1层序遍历

我们可以发现,上面提到的前序、中序、后序遍历好像都在往深的地方走,走到无路可走再退回到上一层继续往深的地方走。由此我们可以总结,前序、中序、后序遍历它们都是一种深度优先遍历(DFS)。现在我们要介绍二叉树的非递归遍历,即层序遍历层序遍历是一种广度优先遍历(BFS)。?

?那么层序遍历实现的思路是怎么样的呢?我们需要借助一个工具——队列。我们看图:

那么我们上手代码时要注意,在C语言的库中没有队列这个数据结构,所以我们需要将实现队列的代码CV过来。这个问题在C++中会得到解决。那么代码我们就可以这么写:

//层序遍历
void LayerTraval(Node* root)
{
	HeadTail q;
	QueueInit(&q);

	//为空则为空树
	if (root == NULL)
	{
		return;
	}
	//非空则入队列
	QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		printf("%d ", tmp->val);

		if (tmp->left != NULL)
		{
			QueuePush(&q, tmp->left);
		}
		if (tmp->right != NULL)
		{
			QueuePush(&q, tmp->right);
		}
	}
	QueueDestroy(&q);
}

int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	//printf("KSize = %d\n", KSize(root, 3));
	//printf("KSize = %d\n", KSize(root, 1));

	//printf("LeafSize = %d\n", LeafSize(root));

	//printf("NodeFind = %p\n", NodeFind(root, 1));
	//printf("NodeFind = %p\n", NodeFind(root, 3));
	//printf("NodeFind = %p\n", NodeFind(root, 100));

	LayerTraval(root);
	return 0;
}

6.层序遍历的衍生问题

6.1判断二叉树是否为完全二叉树

碰到问题我们大胆地去想,首先便是通过节点个数能不能确定二叉树是否为完全二叉树。答案很明显不可能,因为完全二叉树的最后一层需要保证节点是连续的。但是这个方法是可以确定满二叉树的。

既然我们要通过层序遍历,那我们试着遍历任意几颗完全二叉树寻找规律:

?我们遍历两颗普通二叉树:

可以发现一个非常明显的规律,即完全二叉树使用层序遍历的结果 NULL 总为连续的;而普通二叉树使用层序遍历的结果 NULL 是不连续的。?

那么这个规律,便是我们代码的突破口。

//判断是否为完全二叉树
bool FuncTree(Node* root)
{
	HeadTail q;
	QueueInit(&q);
	if (root == NULL)
	{
		return;
	}
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		//一旦拿到空,就跳出循环进行判断
		//此时队列后面要不有节点,要不为空
		//不用担心二叉树的所有节点是否完全存放在队列里面
		if (tmp == NULL)
		{
			break;
		}
		QueuePush(&q, tmp->left);
		QueuePush(&q, tmp->right);
		
	}
	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		if (tmp != NULL)
		{
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}


int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	//printf("KSize = %d\n", KSize(root, 3));
	//printf("KSize = %d\n", KSize(root, 1));

	//printf("LeafSize = %d\n", LeafSize(root));

	//printf("NodeFind = %p\n", NodeFind(root, 1));
	//printf("NodeFind = %p\n", NodeFind(root, 3));
	//printf("NodeFind = %p\n", NodeFind(root, 100));

	//LayerTraval(root);
	printf("FuncTree = %d\n", FuncTree(root));
	return 0;
}

?8.结尾

为了方便,我把完整代码放在这里(队列各接口除外)。

//队列的声明
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>

typedef int BinaryData;
typedef struct Node
{
	BinaryData val;
	struct Node* left;
	struct Node* right;
}Node;


//链表的结点
typedef Node* QueueData;
typedef struct QueueNode
{
	QueueData val;
	struct QueueNode* next;
}QueueNode;
//存储头、尾结点地址的指针
typedef struct HeadTail
{
	QueueNode* head;
	QueueNode* tail;
	int size;//记录队列有几个元素
}HeadTail;

void QueueInit(HeadTail* p);//初始化队列
void QueuePush(HeadTail* p,QueueData x);//进入队列
QueueData QueueHead(HeadTail* p);//获取队头元素
QueueData QueueTail(HeadTail* p);//获取队尾元素
void QueuePop(HeadTail* p);//删除操作,出队
bool QueueEmpty(HeadTail* p);//检查队列是否为空
int QueueSize(HeadTail* p);//获取队列元素个数
void QueuePopTail(HeadTail* p);
void QueueDestroy(HeadTail* p);//销毁队列
#include "Queue.h"


Node* CreateNode()
{
	Node* n1 = (Node*)malloc(sizeof(Node));
	assert(n1);
	Node* n2 = (Node*)malloc(sizeof(Node));
	assert(n2);
	Node* n3 = (Node*)malloc(sizeof(Node));
	assert(n3);
	Node* n4 = (Node*)malloc(sizeof(Node));
	assert(n4);
	Node* n5 = (Node*)malloc(sizeof(Node));
	assert(n5);
	Node* n6 = (Node*)malloc(sizeof(Node));
	assert(n6);

	n1->val = 1;
	n2->val = 2;
	n3->val = 3;
	n4->val = 4;
	n5->val = 5;
	n6->val = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}

//前序遍历
void PreTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->val);
	PreTraval(root->left);
	PreTraval(root->right);
}

//中序遍历
void MidTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	MidTraval(root->left);
	printf("%d ", root->val);
	MidTraval(root->right);
}

//后序遍历
void PosTraval(Node* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	PosTraval(root->left);
	PosTraval(root->right);
	printf("%d ", root->val);
}

//求节点个数
int NodeSize(Node* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return NodeSize(root->left) + NodeSize(root->right) + 1;
}
//int count = 0;//使用全局变量
//int NodeSize(Node* root)
//{
//	if (root == NULL)
//	{
//		return 0;
//	}
//	//static int count = 0;//使用static修饰的静态变量
//	count++;
//	NodeSize(root->left);
//	NodeSize(root->right);
//	return count;
//}

//求第k层的节点个数
int KSize(Node* root,int k)
{
	assert(k > 0);//层数大于0才有意义
	if (root == NULL)
	{
		return 0;
	}
	//加一个特定条件,必须在这一层才具有返回值
	if (k == 1)
	{
		return 1;
	}
	//否则继续往下递归找到指定层数
	return KSize(root->left,k-1) + KSize(root->right,k-1);
}

//求叶节点的个数
int LeafSize(Node* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return LeafSize(root->left) + LeafSize(root->right);
}

//查找值为x的节点
Node* NodeFind(Node* root, int x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->val == x)
	{
		return root;
	}
	Node* LeftRet = NodeFind(root->left, x);
	if (LeftRet != NULL)
	{
		return LeftRet;
	}
	Node* RightRet = NodeFind(root->right, x);
	if (RightRet != NULL)
	{
		return RightRet;
	}
	return NULL;
}

//层序遍历
void LayerTraval(Node* root)
{
	HeadTail q;
	QueueInit(&q);

	//为空则为空树
	if (root == NULL)
	{
		return;
	}
	//非空则入队列
	QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		printf("%d ", tmp->val);

		if (tmp->left != NULL)
		{
			QueuePush(&q, tmp->left);
		}
		if (tmp->right != NULL)
		{
			QueuePush(&q, tmp->right);
		}
	}
	QueueDestroy(&q);
}

//二叉树销毁
void BinaryDestroy(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryDestroy(root->left);
	BinaryDestroy(root->right);
	free(root);
}

//判断是否为完全二叉树
bool FuncTree(Node* root)
{
	HeadTail q;
	QueueInit(&q);
	if (root == NULL)
	{
		return;
	}
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		//一旦拿到空,就跳出循环进行判断
		//此时队列后面要不有节点,要不为空
		//不用担心二叉树的所有节点是否完全存放在队列里面
		if (tmp == NULL)
		{
			break;
		}
		QueuePush(&q, tmp->left);
		QueuePush(&q, tmp->right);
		
	}
	while (!QueueEmpty(&q))
	{
		Node* tmp = QueueHead(&q);
		QueuePop(&q);
		if (tmp != NULL)
		{
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}


int main()
{
	Node* root = CreateNode();
	/*PreTraval(root);
	printf("\n");
	MidTraval(root);
	printf("\n");
	PosTraval(root);
	printf("\n");*/

	//printf("NodeSize = %d\n", NodeSize(root));
	//printf("NodeSize = %d\n", NodeSize(root));

	//printf("KSize = %d\n", KSize(root, 3));
	//printf("KSize = %d\n", KSize(root, 1));

	//printf("LeafSize = %d\n", LeafSize(root));

	//printf("NodeFind = %p\n", NodeFind(root, 1));
	//printf("NodeFind = %p\n", NodeFind(root, 3));
	//printf("NodeFind = %p\n", NodeFind(root, 100));

	//LayerTraval(root);
	printf("FuncTree = %d\n", FuncTree(root));
	return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:36:44  更:2022-09-04 01:41:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:53:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码