二叉树的链式存储

1. 分析顺序存储二叉树的优缺点

2. 使用孩子表示法实现二叉树的以下操作:

typedef char BTDataType; 
typedef struct BTNode 
{ 
struct BTNode* _pLeft; 
struct BTNode* _pRight; 
BTDataType _data; 
}BTNode; 


// 二叉树的创建 
BTNode* CreateBinTree(BTDataType* array, int size, BTDataType invalid); 

// 二叉树的拷贝 
BTNode* CopyBinTree(BTNode* pRoot); 

// 二叉树的销毁 
void DestroyBinTree(BTNode** pRoot); 

// 递归:前序遍历 
void PreOrder(BTNode* pRoot); 

// 递归:中序遍历 
void InOrder(BTNode* pRoot); 

// 递归:后序遍历 
void PostOrder(BTNode* pRoot); 

// 层序遍历 
void LevelOrder(BTNode* pRoot); 

// 获取二叉树中节点个数 
int GetBinTreeSize(BTNode* pRoot); 

// 获取二叉树中第K层节点个数 
int GetKLevelNodeCount(BTNode* pRoot, int K); 

// 获取二叉树中叶子节点个数 
int GetLeafCount(BTNode* pRoot); 

// 获取二叉树深度(高度) 
int GetBinTreeHeight(BTNode* pRoot); 

// 检测值为x的元素是否在二叉树中,在返回该节点的地址,否则返回NULL 
BTNode* BinaryTreeFind(BTNode* root, BTDataType x); 

// 二叉树的镜像 
void Mirror(BTNode* pRoot); 

// 判断二叉树是否是完全二叉树 
int BinaryTreeComplete(BTNode* root); 
 1.分析顺序存储二叉树的优缺点

顺序存储是用一段连续的存储单元(数组)存储线性表的数据元素
优点: 存储密度大,存储空间利用率高
缺点: 插入或删除元素是不方便
仅仅比较适合完全二叉树,否则会造成资源浪费

2.使用孩子表示法实现二叉树的以下操作:

代码如下:
这里要利用队列的代码:(详细见前面队列博客)
栈和队列
这里只上传二叉树的代码,队列的详见链接

BinTree.h

#pragma once
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>

//孩子表示法
typedef char BTDataType;
typedef struct BTNode
{
	struct BTNode* _pLeft;
	struct BTNode* _pRight;
	BTDataType _data;
}BTNode;

// 二叉树的创建 
BTNode* CreateBinTree(BTDataType* array, int size, BTDataType invalid);

// 二叉树的拷贝 
BTNode* CopyBinTree(BTNode* pRoot);

// 二叉树的销毁 
void DestroyBinTree(BTNode** pRoot);

// 递归:前序遍历 
void PreOrder(BTNode* pRoot);

// 递归:中序遍历 
void InOrder(BTNode* pRoot);

// 递归:后序遍历 
void PostOrder(BTNode* pRoot);

// 层序遍历 
void LevelOrder(BTNode* pRoot);

// 获取二叉树中节点个数 
int GetBinTreeSize(BTNode* pRoot);

// 获取二叉树中第K层节点个数 
int GetKLevelNodeCount(BTNode* pRoot, int K);

// 获取二叉树中叶子节点个数 
int GetLeafCount(BTNode* pRoot);

// 获取二叉树深度(高度) 
int GetBinTreeHeight(BTNode* pRoot);

// 检测值为x的元素是否在二叉树中,在返回该节点的地址,否则返回NULL 
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

// 二叉树的镜像 
void Mirror(BTNode* pRoot);
void MirrorNor(BTNode* pRoot);

// 判断二叉树是否是完全二叉树 
int BinaryTreeComplete(BTNode* root);


//队列(队列中每个元素是树的节点BTNode*)
//这里队列的实现详见上面链接
typedef BTNode* QDataType;
typedef struct QNode
{
	struct QNode* _pNext;
	QDataType _data;
}QNode,*pQNode;
typedef struct Queue
{
	QNode* _front;
	QNode* _back;
}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);
int QueueEmpty(Queue* q);
void QueueDestroy(Queue* q);
//void TestQueue();

BinTree.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "BinTree.h"

BTNode* BuyBinNode(BTDataType data)
{
	BTNode* pNewNode = (BTNode*)malloc(sizeof(BTNode));
	if (NULL == pNewNode)
	{
		assert(0);
		return NULL;
	}
	pNewNode->_data = data;
	pNewNode->_pLeft = NULL; 
	pNewNode->_pRight = NULL;
	return pNewNode;
}
BTNode* _CreateBinTree(BTDataType* array, int size, int* index, BTDataType invalid)
{
	/*if (array = NULL)
		return NULL;*/
	BTNode* pRoot = NULL;
	if ((*index) < size && array[*index] != invalid)
	{
		// 根节点
		pRoot = BuyBinNode(array[*index]);//树的根节点
		// 根的左子树
		++(*index);
		pRoot->_pLeft = _CreateBinTree(array, size, index, invalid);
		// 根的右子树
		++(*index);
		pRoot->_pRight = _CreateBinTree(array, size, index, invalid);
	}
	return pRoot;
}


// 二叉树的创建 
BTNode* CreateBinTree(BTDataType* array, int size, BTDataType invalid)
{
	int index = 0;//要是函数参数少一个的话,封装一次就OK
	return _CreateBinTree(array, size, &index, invalid);
}

// 二叉树的拷贝 
BTNode* CopyBinTree(BTNode* pRoot)
{
	BTNode* pNewroot = NULL;
	if (pRoot)
	{
		pNewroot = BuyBinNode(pRoot->_data);
		pNewroot->_pLeft = CopyBinTree(pRoot->_pLeft);
		pNewroot->_pRight = CopyBinTree(pRoot->_pRight);
	}
	return pNewroot;
}

// 二叉树的销毁 
void DestroyBinTree(BTNode** pRoot)//为什么要传二级指针
{
	//assert(pRoot);
	if (*pRoot)
	{
		DestroyBinTree(&(*pRoot)->_pLeft);
		DestroyBinTree(&(*pRoot)->_pRight);
		free(*pRoot);
		*pRoot = NULL;
	}
}

// 递归:前序遍历 
void PreOrder(BTNode* pRoot)
{
	//assert(pRoot);
	if (pRoot)//结束条件不能忘
	{
		printf("%c ", pRoot->_data);
		PreOrder(pRoot->_pLeft);
		PreOrder(pRoot->_pRight);
	}
}

// 递归:中序遍历 
void InOrder(BTNode* pRoot)
{
	//assert(pRoot);
	if (pRoot)
	{
		InOrder(pRoot->_pLeft);
		printf("%c ", pRoot->_data);
		InOrder(pRoot->_pRight);
	}
}

// 递归:后序遍历 
void PostOrder(BTNode* pRoot)
{
	//assert(pRoot);
	if (pRoot)
	{
		PostOrder(pRoot->_pLeft);
		PostOrder(pRoot->_pRight);
		printf("%c ", pRoot->_data);
	}
}

// 层序遍历 
void LevelOrder(BTNode* pRoot)
{
	Queue q;
	if (NULL == pRoot)
		return;
	QueueInit(&q);
	QueuePush(&q, pRoot);//队列里面放的是树节点
	while (!QueueEmpty(&q))
	{
		BTNode* pCur = QueueFront(&q);
		printf("%c ", pCur->_data);

		// 如果左孩子存在,保存当前节点的左孩子
		if (pCur->_pLeft)//判空(注意)
		QueuePush(&q, pCur->_pLeft);

		// 如果右孩子存在,保存当前节点的右孩子
		if (pCur->_pRight)//判空(注意)
		QueuePush(&q, pCur->_pRight);

		QueuePop(&q);//队列删除,其实是头删
	}
	QueueDestroy(&q);//记得销毁队列
	printf("\n");
}

// 获取二叉树中节点个数 
int GetBinTreeSize(BTNode* pRoot)//
{
	//assert(pRoot);
	if (NULL == pRoot)
		return 0;
	//if (pRoot)
		//return 1;
	return 1 + GetBinTreeSize(pRoot->_pLeft) + GetBinTreeSize(pRoot->_pRight);
}

// 获取二叉树中第K层节点个数 
int GetKLevelNodeCount(BTNode* pRoot, int K)
{
	if (NULL == pRoot || K < 0)
		return 0;
	if (K == 1)
		return 1;
	return GetKLevelNodeCount(pRoot->_pLeft, K - 1) + GetKLevelNodeCount(pRoot->_pRight, K - 1);
}

// 获取二叉树中叶子节点个数 
int GetLeafCount(BTNode* pRoot)
{
	if (NULL == pRoot)
		return 0;
	if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
		return 1;
	return GetLeafCount(pRoot->_pLeft) + GetLeafCount(pRoot->_pRight);
}

// 获取二叉树深度(高度) 
int GetBinTreeHeight(BTNode* pRoot)
{
	BTNode* pTmp = pRoot;
	int deep = 0;
	if (pTmp)
	{
		int leftdeep = GetBinTreeHeight(pTmp->_pLeft);
		int rightdeep = GetBinTreeHeight(pTmp->_pRight);
		deep = leftdeep >= rightdeep ? leftdeep + 1 : rightdeep + 1;
	}
	return deep;
}

// 检测值为x的元素是否在二叉树中,在返回该节点的地址,否则返回NULL 
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	BTNode* pRet = NULL;
	if (root == NULL)
		return NULL;
	if (root->_data == x)
		return root;
	if (pRet = BinaryTreeFind(root->_pLeft, x))
		return pRet;
	return BinaryTreeFind(root->_pRight, x);
}

void Swap(BTNode** pleft, BTNode** pright)
{
	BTNode* pTmp = *pleft;
	*pleft = *pright;
	*pright = pTmp;
}

// 二叉树的镜像 
void Mirror(BTNode* pRoot)
{
	if (pRoot)
	{
		Swap(&pRoot->_pLeft, &pRoot->_pRight);
		Mirror(pRoot->_pLeft);
		Mirror(pRoot->_pRight);
	}
}

void MirrorNor(BTNode* pRoot)
{
	Queue q;
	if (NULL == pRoot)
		return;
	QueueInit(&q);
	QueuePush(&q, pRoot);
	while (!QueueEmpty(&q))
	{
		BTNode* pCur = QueueFront(&q);
		Swap(&pCur->_pLeft, &pCur->_pRight);
		if (pCur->_pLeft)
			QueuePush(&q, pCur->_pLeft);
		if (pCur->_pRight)
			QueuePush(&q, pCur->_pRight); 
		QueuePop(&q);
	}
	QueueDestroy(&q);
}

// 判断二叉树是否是完全二叉树 
int BinaryTreeComplete(BTNode* root)
{
	if (NULL == root)
		return 1;
	int left = GetBinTreeHeight(root->_pLeft);
	int right = GetBinTreeHeight(root->_pRight);
	int diff = left - right;
	if (diff < -1 || diff > 1)
		return 0;
	return BinaryTreeComplete(root->_pLeft) && BinaryTreeComplete(root->_pRight);
}

void TestBinTree()
{
	char* str = "ABD$$$CE$$F";
	BTNode* pRoot = CreateBinTree(str, strlen(str), '$');
	Mirror(pRoot);
	MirrorNor(pRoot);
	printf("前序遍历结果:");
	PreOrder(pRoot);
	printf("\n");

	printf("中序遍历结果:");
	InOrder(pRoot);
	printf("\n");

	printf("后序遍历结果:");
	PostOrder(pRoot);
	printf("\n");

	printf("层序遍历结果:");
	LevelOrder(pRoot);
	printf("\n");
	int size = GetBinTreeSize(pRoot);
	printf("该二叉树的节点个数为:%d\n", size);

	int count = GetKLevelNodeCount(pRoot, 3);
	printf("第3层的节点个数为:%d\n", count);

	int leave = GetLeafCount(pRoot);
	printf("该二叉树中的叶子结点的个数为:%d\n", leave);

	int height = GetBinTreeHeight(pRoot);
	printf("该二叉树的深度为:%d\n", height);

	//判断是否为完全二叉树,a = 0 不是,  a = 1 是
	//int a = BinaryTreeComplete(pRoot);
	//if (a == 1)
	//	printf("是完全二叉树\n");
	//else
	//	printf("不是完全二叉树\n");

	//判断E是否在二叉树内
	if (BinaryTreeFind(pRoot, 'E'))
	{
		printf("E is in BTree!!!\n");
	}
	else
	{
		printf("E is not in BTree!!!\n");
	}
	DestroyBinTree(&pRoot);
}

int main()
{
	TestBinTree();
	system("pause");
	return 0;
}

测试二叉树结构如图:
在这里插入图片描述

测试结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值