(数据结构初阶)二叉树 (二)

目录

一 树的链式存储结构

二 树的链式结构简单实现

1.基本结构

2.结点创建

3.前中后序遍历为深度优先遍历,层序遍历为广度优先遍历

4.求结点个数

5.求叶子结点个数

6.求第K层结点个数

7.查找树里面值为x的那个结点

8.销毁树

9.判断一棵树是不是完全二叉树

三 完整文件

1.BinaryTree.h

2.BinaryTree.c

3.test.c

四 总结


一 树的链式存储结构

1.四种遍历顺序:前序遍历(先根)、中序遍历(中根)、后序遍历(后根)、层序遍历。

2.递归:子问题。②结束条件

3.排序二叉树:①又称二叉搜索树,它的左孩子都小于父亲,右孩子都大于父亲。②普通二叉树的增删查改没有意义,排序二叉树的增删查改才有意义。③极端情况下(数据为有序数列),搜索二叉树的效率退化为O(N)。④二叉搜索树的中序遍历为升序。

二 树的链式结构简单实现

1.基本结构

typedef char BTDateType;
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	BTDateType date;
}BTNode;

2.结点创建

//创建一颗二叉树
BTNode* CreateTreeNode(BTDateType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}

3.前中后序遍历为深度优先遍历,层序遍历为广度优先遍历

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	printf("%c  ", root->date);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	InOrder(root->left);
	printf("%c  ", root->date);
	InOrder(root->right);
}

//后续遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c  ", root->date);
}

//层序遍历(广度优先遍历)
void TreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q,root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->date);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}
	QueueDestroy(&q);
}

4.求结点个数

求树的结点个数,思路一:遍历。
//void TreeSize(BTNode* root, int* size)
//{
//	if (root == NULL)
//	{
//		return;
//	}
//	++(*size);
//	TreeSize(root->left, size);
//	TreeSize(root->right,size);
//}
//思路二:分治算法(把大问题拆解成子问题)
int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

5.求叶子结点个数

//求叶子结点个数
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

6.求第K层结点个数

//求第K层结点个数:k>0(转化为求左孩子的K-1层+右孩子的K-1层)
int TreeKlevelSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeKlevelSize(root->left, k - 1) + TreeKlevelSize(root->right, k - 1);
}

7.查找树里面值为x的那个结点

//查找树里面值为x的那个结点
BTNode* TreeFind(BTNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->date == x)
	{
		return root;
	}

	BTNode* ltemp = TreeFind(root->left, x);
	if (ltemp)
		return ltemp;

	BTNode* rtemp = TreeFind(root->right, x);
	if(rtemp)
	    return rtemp;

	return NULL;
}

8.销毁树

//销毁树(传一级指针,调用此函数的人自己将指针置空,保持接口的一致性)
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

9.判断一棵树是不是完全二叉树

9.1完全二叉树按层序走,结点是连续的,当出到空了以后,后面全是空就是完全二叉树,如果后面有非空,那么就不是。(因为说明层序走,非空结点不连续。)

9.2判断是不是完全二叉树代码实现

//判断是不是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root!=NULL)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front==NULL)
		{
			break;
		}
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front!=NULL)
		{
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

三 完整文件

1.BinaryTree.h

#define _CRT_SECURE_NO_WARNINGS 1

#include 
#include 
#include 
#include 
#include 

typedef char BTDateType;
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	BTDateType date;
}BTNode;

BTNode* CreateTreeNode(BTDateType x);
void PrevOrder(BTNode* root);
void InOrder(BTNode* root);
void PostOrder(BTNode* root);
//void TreeSize(BTNode* root, int* size);
int TreeSize(BTNode* root);
int TreeLeafSize(BTNode* root);
int TreeKlevelSize(BTNode* root, int k);
BTNode* TreeFind(BTNode* root, BTDateType x);

//求第K层结点个数:(转化为求左孩子的K-1层+右孩子的K-1层)
int TreeKlevelSize(BTNode* root, int k);

//查找树里面值为x的那个结点
BTNode* TreeFind(BTNode* root, BTDateType x);

//销毁树(传一级指针,调用此函数的人自己将指针置空,保持接口的一致性)
void BinaryTreeDestory(BTNode* root);

//层序遍历(广度优先遍历)
void TreeLevelOrder(BTNode* root);
//判断是否为完全二叉树
bool BinaryTreeComplete(BTNode* root);


2.BinaryTree.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"BinaryTree.h"
#include"queue.h"

//创建一颗二叉树
BTNode* CreateTreeNode(BTDateType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	printf("%c  ", root->date);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	InOrder(root->left);
	printf("%c  ", root->date);
	InOrder(root->right);
}

//后续遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL  ");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c  ", root->date);
}

求树的结点个数,思路一:遍历。
//void TreeSize(BTNode* root, int* size)
//{
//	if (root == NULL)
//	{
//		return;
//	}
//	++(*size);
//	TreeSize(root->left, size);
//	TreeSize(root->right,size);
//}
//思路二:分治算法(把大问题拆解成子问题)
int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

//求叶子结点个数
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}


//求第K层结点个数:k>0(转化为求左孩子的K-1层+右孩子的K-1层)
int TreeKlevelSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeKlevelSize(root->left, k - 1) + TreeKlevelSize(root->right, k - 1);
}

//查找树里面值为x的那个结点
BTNode* TreeFind(BTNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->date == x)
	{
		return root;
	}

	BTNode* ltemp = TreeFind(root->left, x);
	if (ltemp)
		return ltemp;

	BTNode* rtemp = TreeFind(root->right, x);
	if(rtemp)
	    return rtemp;

	return NULL;
}

//销毁树(传一级指针,调用此函数的人自己将指针置空,保持接口的一致性)
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

//层序遍历(广度优先遍历)
void TreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q,root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->date);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}
	QueueDestroy(&q);
}

//判断是不是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root!=NULL)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front==NULL)
		{
			break;
		}
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front!=NULL)
		{
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

3.test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"BinaryTree.h"
#include"queue.h"

int main()
{
	BTNode* A = CreateTreeNode('A');
	BTNode* B = CreateTreeNode('B');
	BTNode* C = CreateTreeNode('C');
	BTNode* D = CreateTreeNode('D');
	BTNode* E = CreateTreeNode('E');
	//BTNode* F = CreateTreeNode('F');
	BTNode* G = CreateTreeNode('G');

	A->left = B;
	A->right = C;
	B->left = D;
	B->right = E;
	//C->left = F;
	C->right = G;

	//PrevOrder(A);
	//printf("\n\n");
	//InOrder(A);
	//printf("\n\n");
	//PostOrder(A);

	//int size = 0;
	//TreeSize(A, &size);
	//printf("%d\n",size);
 //   size = 0;
	//TreeSize(A, &size);
	//printf("%d\n", size);

	printf("%d\n", TreeLeafSize(A));
	printf("%d\n", TreeLeafSize(A));

	printf("%d\n", TreeKlevelSize(A,3));

	//printf("%p\n", F);
	//printf("%p\n",TreeFind(A,'F'));
	
	TreeLevelOrder(A);

	printf("%d\n", BinaryTreeComplete(A));
	
	BinaryTreeDestory(A);
	A = NULL;
	return 0;
}


四 总结

1.深度优先遍历:前中后序遍历,一般用递归。

2.广度优先遍历:层序遍历,一般借助队列。

3.求结点的个数(前序),左子树结点个数+右子树结点个数+1。

4.求树的高度(后序),fmax(左树高度,右树高度)+1。

你可能感兴趣的:(C/C++学习笔记,数据结构)