【数据结构】模拟实现二叉树(二叉树的实现,查找,前中后层序,深度,叶节点,K层,结点数)

1.概念

1.二叉树每个结点最多有两颗子树,且有左右之分,次序不能颠倒。
2.完全二叉树:K-1层结点为满,K层从左至右为连续。
3.满二叉树:二叉树的结点个数为2k-1,K-1层的左右子树(叶子)为满。
4.存储分为:链式和顺序。
链式可以直接通过指针访问:
在这里插入图片描述
顺序访问:
在这里插入图片描述
若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
parent = (i-1)/2
leftchild = 2i+1<=n
rightchild = 2i+2<=n
5.性质

  1. 若规定根节点的层数为0,则一棵非空二叉树的第i层上最多有2^i 个结点.
  2. 若规定只有根节点的二叉树的深度为0,则深度为h的二叉树的最大结点数是2^(h+1) - 1.
  3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
  4. 具有n个结点的完全二叉树的深度h=Log2(n+1). (ps:Log2(n+1)是log以2为底,n+1为对数)
    6.例题
    在这里插入图片描述

2.代码展示

BinaryTree.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

// 链式结构:表示队列
typedef BTNode* QDataType;
typedef struct QListNode
{
	struct QListNode* _pNext;
	QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
	QNode* _front;//队头
	QNode* _rear;//队尾
}Queue;


// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);


// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
//二叉树的深度
int BinaryTreedepth(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

BinaryTree.c

#include"BinaryTree.h"
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi) 
{	
	if (a[*pi] == '#')
	{
		return NULL;
	}
	else
	{
		BTNode * root = (BTNode*)malloc(sizeof(BTNode));
		root-> _data = a[*pi];
		printf("%c ", root->_data);
		++(*pi);
		root->_left = BinaryTreeCreate(a, n, pi);
		++(*pi);
		root->_right = BinaryTreeCreate(a, n, pi);
		return root;
	}
}
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		return ;
	}
	printf("%c ",root->_data);
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		return ;
	}
	BinaryTreeInOrder(root->_left);
	printf("%c ", root->_data);
	BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		return ;
	}
	BinaryTreePostOrder(root->_left);
	BinaryTreePostOrder(root->_right);
	printf("%c ", root->_data);
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root != NULL)
	{
		QueuePush(&q, root);
	}
	while (QueueEmpty(&q) != 0)
	{
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_data);
		QueuePop(&q);
		if (front->_left)
		{
			QueuePush(&q, front->_left);
		}
		if (front->_right)
		{
			QueuePush(&q, front->_right);
		}
	}
	QueueDestroy(&q);
}

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{	//通过队列,等到入NULL时,看NULL后面有没有非NULL的情况,有就是不是完全二叉树,直到全部出队,就是完全二叉树。
	Queue q;
	QueueInit(&q);
	if (root != NULL)
	{
		QueuePush(&q, root);
	}
	while (QueueEmpty(&q) != 0)
	{
		BTNode* front = QueueFront(&q);

		QueuePop(&q);
		if (front == NULL)
		{
			break;
		}
		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}
	while (QueueEmpty(&q) != 0)
	{
		if (QueueFront(&q) == NULL)
		{
			QueuePop(&q);
		}
		else
		{
			return 0;
		}
	}
	return 1;
	QueueDestroy(&q);
}

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}

	int a= BinaryTreeLevelKSize(root->_left, k-1) + BinaryTreeLevelKSize(root->_right,k-1);
	return a;
	
}

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->_data == x)
	{
		return root;
	}
	BTNode* ret = BinaryTreeFind(root->_left, x);
	if (ret)
	{
		return ret;
	}
	ret = BinaryTreeFind(root->_right, x);
	if (ret)
	{
		return ret;
	}
	return NULL;
}

//二叉树的深度
int BinaryTreedepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	int a = BinaryTreedepth(root->_left);
	int b = BinaryTreedepth(root->_right);
	return a > b ? a + 1 : b + 1;

}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);
}

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL)
	{
		return 1;
	}
	return  BinaryTreeLeafSize(root->_left)+
	 BinaryTreeLeafSize(root->_right);
	
} 

// 初始化队列
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
}

// 队头出队列
void QueuePop(Queue* q)
{
	assert(q&& q->_front);
	//只有一个元素 需要将队尾也置空
	//两个 
	if (q->_front->_pNext == NULL)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	else
	{
		QNode* next = q->_front->_pNext;
		free(q->_front);
		q->_front = next;
	}

}

// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->_data = data;
	newnode->_pNext = NULL;
	if (q->_rear == NULL)
	{
		q->_front = q->_rear = newnode;
	}
	else
	{
		q->_rear->_pNext = newnode;
		q->_rear = newnode;
	}
}

// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
	assert(q);
	return q->_front->_data;
}

// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
	assert(q);
	return q->_rear->_data;
}

// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
	assert(q);
	int count = 0;
	QNode* cur = q->_front;
	while (cur)
	{
		++count;
		cur = cur->_pNext;
	}
	return count;
}

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->_front == NULL ? 0 : 1;
}

// 销毁队列
void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* cur = q->_front;
	while (cur)
	{
		QNode* next = cur->_pNext;
		free(cur);
		cur = next;
	}
	q->_front = q->_rear = NULL;
}



test() 
{
	char arr[100] = "ABC##DE#G##F###";
	int n = strlen(arr);
	int i = 0;
	BTNode * root = BinaryTreeCreate(arr, n,&i);
	printf("\n");
	BinaryTreePrevOrder(root);
	printf("\n");
	BinaryTreeInOrder(root);
	printf("\n");
	BinaryTreePostOrder(root);
	printf("\n");
	BinaryTreeLevelOrder(root);
	printf("\n");
	if (BinaryTreeComplete(root) == 0)
	{
		printf("不是完全二叉树\n");
	}
	else
	{
		printf("是完全二叉树\n");
	}
	
	char x;
	scanf("%c", &x);
	root = BinaryTreeFind(root, x);
	if (root == NULL)
		printf("%c不在二叉树中\n",x);
	else
		printf("%c在二叉树中\n", x);
	
	printf("%d\n",BinaryTreeSize(root));	//所有节点
	printf("%d\n", BinaryTreeLeafSize(root));//叶子节点
	printf("%d\n", BinaryTreeLevelKSize(root,4));//K层节点
	printf("%d\n", BinaryTreedepth(root));//深度

}

test.c

#include"BinaryTree.h"
int main()
{
	test();
	system("pause");
	return 0;
}

3.结果展示

在这里插入图片描述

4.心得体会

通过实现二叉树,我对递归有了深刻的认识。同时在判断是否为完全二叉树时,我对队列的理解加深了。递归要注意结束条件。有的地方要判断是否为
空树。

发布了79 篇原创文章 · 获赞 6 · 访问量 3765

猜你喜欢

转载自blog.csdn.net/qq_41152046/article/details/105291472