详细解读二叉树基本操作

二叉树的详细解读

二叉树的概念

  • 一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的二叉树组成
  • 二叉树的特点:每个结点最多有两棵子树,即二叉树不存在度大于2的结点
  • 二叉树的子树有左右之分,其子树的次序不能颠倒
    在这里插入图片描述
  • 因此:二叉树是通过上述5中形式的组合或嵌套而形成

满二叉树&完全二叉树

  • 满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子节点都在同一层上
  • 完全二叉树:如果一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树
    在这里插入图片描述

二叉树性质

  • 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1) (i>0)个结点
  • 若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大结点数是(2^k)-1 (k>=0)
  • 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数 为 n2,则有n0=n2+1
  • 具有n个结点的完全二叉树的深度k为 Log2(n+1) 上取整
  • 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序 对所有节点从0开始编号,则对于序号为i的结点有:
    • 若i>0,双亲序号:(i-1)/2;
      i=0,i为根节点编号,无双亲结点
    • 若2i+1<n,左孩子序号:2i+1,否则无左孩子
    • 若2i+2<n,右孩子序号:2i+2,否则无右孩子

二叉树存储结构

  • 二叉树主要有顺序存储链式存储结构
  • 顺序存储结构 对于一棵完全二叉树所有结点按照层序自顶向下,同一层自左向右顺 序编号,就得到一个节点的顺序序列
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 优点:存储完全二叉树,简单省空间
  • 缺点:存储一般二叉树尤其单支树,存储空间利用不高
    链式存储
    在这里插入图片描述

二叉树的基本操作

  • 二叉树的遍历

  • 遵循某种次序,遍历二叉树中的所有节点,使得每个结点被访问一 次,而且仅访问一次。“访问”:即对结点施行某些操作。
    若规定VLR分别代表:遍历根节点、遍历根节点的左子树、遍历根节 点的右子树,

  • 则有:

  • 前序:VLR

  • 中序:LVR

  • 后序:LRV

  • 二叉树层序遍历

  • 按照二叉树的层序次序(即从根节点层到叶结点层),同一层中按先左 子树再右子树的次序遍历二叉树

  • 因此:在所有未被访问结点的集合中,排列在已访问结点集合中最前 面结点的左子树的根节点将最先被访问,然后是该结点的右子树的根 节点。

  • 二叉树的其他操作

  • 求二叉树的高度

  • 求二叉树叶子结点的个数

  • 求二叉树结点的个数

  • 求二叉树第K层结点的个数

  • 判断一个节点是否在一棵二叉树中

  • 获取一个节点的双亲结点

  • 获取一个节点的左孩子结点

  • 获取一个节点的右孩子结点

  • 将三种递归遍历方式转换为非递归形式

  • 求二叉树的镜像(递归&非递归)

  • 判断一棵二叉树是否为完全二叉树(层序遍历变形)

  • 创建二叉树

  • 前/中/后遍历二叉树(递归&非递归)

  • 层序遍历二叉树

  • 求二叉树中两个结点的最近公共祖先结点

  • 判断一棵二叉树是否是平衡二叉树

  • 求二叉树中最远的两个结点之间的距离

  • 有前序遍历和中序遍历重建二叉树(前序遍历结果:1,2,3,4,5,6 中序 遍历结果:4,2,5,1,6,3)

  • 判断一棵二叉树是否是完全二叉树

  • 求二叉树的镜像

好了,到了看代码的时间了

  • 先来看看我定义的结构体
typedef char DataType;

typedef struct BTNode
{
	DataType _data; //数据
	struct BTNode* _pLeft;  //左子树
	struct BTNode* _pRight;  //右子树
}BTNode;
  • 创建二叉树,我是利用递归创建的,用的先序遍历的思想。即先创建根节点,然后创建左子树,后创建右子树。
BTNode* BuyBTNode(DataType data)
{
	BTNode* temp = (BTNode*)malloc(sizeof(BTNode));
	if (!temp)
	{
		assert(0);
		return;
	}
	temp->_data = data;
	temp->_pLeft = NULL;
	temp->_pRight = NULL;
}

//str 存放元素的数组,size 元素个数,index 递归到第几个个元素,invalid 树中空位置
void CreateBinTree(BTNode** pRoot, char* str, int size, int* index, DataType invalid)
{
	assert(pRoot);
	assert(index);
	if (*index < size && str[*index] != invalid)
	{
		*pRoot = BuyBTNode(str[*index]);//创建根节点

		++(*index);
		CreateBinTree(&((*pRoot)->_pLeft), str, size, index, invalid);//创建左节点

		++(*index);
		CreateBinTree(&((*pRoot)->_pRight), str, size, index, invalid);//创建右节点
	}
}
  • 先序遍历(递归),递归代码比较简单,我就不罗嗦了。
void PreOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	printf("%c ", pRoot->_data);
	PreOrder(pRoot->_pLeft);
	PreOrder(pRoot->_pRight);
}
  • 先序遍历(非递归):这里用到栈的数据结构。先将根节点入栈,然后进入循环,判断条件是栈是否为空;在循环中,我们先取到栈顶元素,打印完之后出栈,接下来,我们将这个节点的左右子树入栈,如果为空,则不入。这里顺序必须先是右子树,再是左子树;因为栈具有后进先出的性质。然后让他循环就好了。
void PreOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	Stack s;
	BTNode* temp = NULL;
	InitStack(&s);

	PushStack(&s, pRoot);
	while (!EmptyStack(&s))
	{
		temp = TopStack(&s);
		PopStack(&s);
		printf("%c ", temp->_data);

		if (temp->_pRight)
			PushStack(&s, temp->_pRight);
		if (temp->_pLeft)
			PushStack(&s, temp->_pLeft);
	}
}
  • 中序遍历(递归)
void InOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	InOrder(pRoot->_pLeft);
	printf("%c ", pRoot->_data);
	InOrder(pRoot->_pRight);
}
  • 中序遍历(非递归):开始初始化时将我的temp设置为pRoot根节点,进入循环,条件是temp不为空或者栈不为空;循环里面,我们先将temp中所有左子树入栈,接下来打印temp的元素,并且出栈,最后让temp指向他的右子树就好了。继续让他循环就好了。
void InOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	Stack s;
	BTNode* temp = pRoot;
	InitStack(&s);

	while (temp != NULL || !EmptyStack(&s))
	{		
		while (temp)
		{
			PushStack(&s, temp);
			temp = temp->_pLeft;
		}

		temp = TopStack(&s);
		printf("%c ", temp->_data);
		PopStack(&s);

		temp = temp->_pRight;
	}
}
  • 后序遍历(递归)

void PostOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	PostOrder(pRoot->_pLeft);
	PostOrder(pRoot->_pRight);
	printf("%c ", pRoot->_data);
}

  • 后序遍历(非递归):先初始化一个栈,将根节点入栈,然后进入循环,循环条件是栈不为空;循环里面一个判断条件是栈顶元素是叶子节点或者叶子节点的根节点,那么我们就打印并且出栈。最后将此元素的左右孩子入栈,还有有顺序的,必须是先右孩子,然后才能入左孩子。
void PostOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	BTNode* cur = NULL;
	BTNode* prev = NULL;
	Stack s;
	InitStack(&s);

	PushStack(&s, pRoot);
	while (!EmptyStack(&s))
	{
		cur = TopStack(&s);
		if ((cur->_pLeft == NULL && cur->_pRight == NULL) 
			|| ((prev != NULL) && (prev == cur->_pLeft || prev == cur->_pRight)))
		{
			printf("%c ", cur->_data);
			PopStack(&s);
			prev = cur;
			continue;
		}

		if (cur->_pRight)
			PushStack(&s, cur->_pRight);
		if (cur->_pLeft)
			PushStack(&s, cur->_pLeft);
	}
}
  • 层序遍历:使用到队列的数据结构,我们先将根节点入队列中,进入循环,用temp拿到队首元素,并且打印,然后拿到temp的左右孩子进行入队列,这时顺序必须是先左后有右,因为队列的性质是后进先出的
void LevelOrder(BTNode* pRoot)
{
	assert(pRoot);
	Queue q;
	BTNode* temp = NULL;
	InitQueue(&q);

	PushQueue(&q, pRoot);
	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		printf("%c ", temp->_data);

		if (temp->_pLeft)
			PushQueue(&q, temp->_pLeft);
		if (temp->_pRight)
			PushQueue(&q, temp->_pRight);

		PopQueue(&q);
	}
}
  • 拷贝二叉树:采用递归的方式,先拷贝根节点,然后在拷贝左右子树。
BTNode* CopyBinTree(BTNode* pRoot)
{
	BTNode* pNewRoot = NULL;
	if (pRoot)
	{
		pNewRoot = BuyBTNode(pRoot->_data);

		if (pRoot->_pLeft)
			pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft);

		if (pRoot->_pRight)
			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;
	}
}
  • 获取二叉树的节点个数:采取递归的方式,最后一定要加上根节点那个1;
int GetBTNodeCount(BTNode* pRoot)
{
	if (NULL == pRoot)
		return 0;
	return GetBTNodeCount(pRoot->_pLeft) + GetBTNodeCount(pRoot->_pRight) + 1;
}
  • 获取叶子节点个数:叶子节点就是此节点的左右孩子都为空。
int GetLeafNodeCount(BTNode* pRoot)
{
	if (NULL == pRoot)
		return 0;
	if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
		return 1;
	return GetLeafNodeCount(pRoot->_pLeft) + GetLeafNodeCount(pRoot->_pRight);
}

  • 获取第K层节点个数:首先要检验参数是否正确,然后第一层只有根节点那就只有1个节点。接下来递归调用就好了。
int GetKLevelNodeCount(BTNode* pRoot, int K)
{
	if (K <= 0 || pRoot == NULL)
		return 0;
	if (K == 1)
		return 1;
	return GetKLevelNodeCount(pRoot->_pLeft, K - 1) + GetKLevelNodeCount(pRoot->_pRight, K - 1);

}
  • 获取树的高度:定义两个变量,分别表示根节点的左右子树的高度,树的高度就是左右子树最高高度再加上1。
int Height(BTNode* pRoot)
{
	int LeftHeight = 0;
	int RightHeight = 0;
	if (NULL == pRoot)
		return 0;

	LeftHeight = Height(pRoot->_pLeft);
	RightHeight = Height(pRoot->_pRight);

	return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
}
  • 判断节点是否在二叉树中:采用递归的方式,遍历二叉树的所有节点,如果相等那么就返回1,没有就返回0。
int IsBTNodeInBinTree(BTNode* pRoot, BTNode* pNode)
{
	if (pRoot == NULL || pNode == NULL)
		return 0;
	if (pRoot == pNode)
		return 1;
	if (IsBTNodeInBinTree(pRoot->_pLeft, pNode))
		return 1;
	return IsBTNodeInBinTree(pRoot->_pRight, pNode);
}
  • 获取节点的母亲节点:如果根节点是空或者给的节点是空或者给的节点就是根节点,那么就返回NULL;然后给的节点如果是母亲节点的左孩子或者右孩子,就返回这个节点的母亲节点。
BTNode*  GetBTNodeParent(BTNode* pRoot, BTNode* pNode)
{
	BTNode* pParent = NULL;
	if (pRoot == NULL || pNode == NULL || pRoot == pNode)
		return NULL;
	if (pNode == pRoot->_pLeft || pNode == pRoot->_pRight)
		return pRoot;
	if (pParent = GetBTNodeParent(pRoot->_pLeft, pNode))
		return pParent;
	return GetBTNodeParent(pRoot->_pRight, pNode);
}
  • 求二叉树的镜像:采用递归的方式,交换这个节点的左右孩子;接下来处理这个节点的左右孩子。
void Swap(BTNode** Left, BTNode** Right)
{
	BTNode* temp = *Left;
	*Left = *Right;
	*Right = temp;
}

void MirrorBinTree(BTNode* pRoot)
{
	if (pRoot)
	{
		Swap(&pRoot->_pLeft, &pRoot->_pRight);
		MirrorBinTree(pRoot->_pLeft);
		MirrorBinTree(pRoot->_pRight);
	}
}
  • 求二叉树的镜像:将递归转换为循环,采用栈的循环,近似与前序遍历的思想。
void MirrorBinTreeNor(BTNode* pRoot)
{
	Queue q;
	BTNode* temp = NULL;
	if (NULL == pRoot)
		return;
	InitQueue(&q);
	PushQueue(&q, pRoot);

	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		Swap(&temp->_pLeft, &temp->_pRight);

		if (temp->_pLeft)
			PushQueue(&q, temp->_pLeft);
		if (temp->_pRight)
			PushQueue(&q, temp->_pRight);

		PopQueue(&q);
	}
}
  • 判断是否是完全二叉树:采用队列的数据结构。
  • 如果树为空,则直接返回错
  • 如果树不为空:层序遍历二叉树
  • 如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列;
  • 如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树;
  • 如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树;
int IsCompleteBinTree(BTNode* pRoot)
{
	Queue q;
	BTNode* temp = NULL;
	int Flag = 0;
	if (pRoot == NULL)
		return 1;
	InitQueue(&q);
	PushQueue(&q, pRoot);
	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		if (Flag)
		{
			if (temp->_pLeft || temp->_pRight)
				return 0;
		}
		else
		{
			if (temp->_pLeft && temp->_pRight)
			{
				PushQueue(&q, temp->_pLeft);
				PushQueue(&q, temp->_pRight);
			}
			else if (temp->_pLeft)
			{
				PushQueue(&q, temp->_pLeft);
				Flag = 1;
			}
			else if (temp->_pRight)
				return 0;
			else
				Flag = 1;
		}

		PopQueue(&q);
	}
}

最后附上所有代码,包括测试函数,还有需要用到的栈和队列的代码。

  • BTree.h:二叉树的所有函数
#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include"stack.h"
#include"queue.h"

//typedef char DataType;
//
//typedef struct BTNode
//{
//	DataType _data;
//	struct BTNode* _pLeft;
//	struct BTNode* _pRight;
//}BTNode;



BTNode* BuyBTNode(DataType data)
{
	BTNode* temp = (BTNode*)malloc(sizeof(BTNode));
	if (!temp)
	{
		assert(0);
		return;
	}
	temp->_data = data;
	temp->_pLeft = NULL;
	temp->_pRight = NULL;
}

//str 存放元素的数组,size 元素个数,index 递归到那个元素,invalid 树中空位置
void CreateBinTree(BTNode** pRoot, char* str, int size, int* index, DataType invalid)
{
	assert(pRoot);
	assert(index);
	if (*index < size && str[*index] != invalid)
	{
		*pRoot = BuyBTNode(str[*index]);//创建根节点

		++(*index);
		CreateBinTree(&((*pRoot)->_pLeft), str, size, index, invalid);//创建左节点

		++(*index);
		CreateBinTree(&((*pRoot)->_pRight), str, size, index, invalid);//创建右节点
	}
}


void PreOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	printf("%c ", pRoot->_data);
	PreOrder(pRoot->_pLeft);
	PreOrder(pRoot->_pRight);
}


void PreOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	Stack s;
	BTNode* temp = NULL;
	InitStack(&s);

	PushStack(&s, pRoot);
	while (!EmptyStack(&s))
	{
		temp = TopStack(&s);
		PopStack(&s);
		printf("%c ", temp->_data);

		if (temp->_pRight)
			PushStack(&s, temp->_pRight);
		if (temp->_pLeft)
			PushStack(&s, temp->_pLeft);
	}
}


void InOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	InOrder(pRoot->_pLeft);
	printf("%c ", pRoot->_data);
	InOrder(pRoot->_pRight);
}

void InOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	Stack s;
	BTNode* temp = pRoot;
	InitStack(&s);

	while (temp != NULL || !EmptyStack(&s))
	{		
		while (temp)
		{
			PushStack(&s, temp);
			temp = temp->_pLeft;
		}

		temp = TopStack(&s);
		printf("%c ", temp->_data);
		PopStack(&s);

		temp = temp->_pRight;
	}
}


void PostOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
		return;
	PostOrder(pRoot->_pLeft);
	PostOrder(pRoot->_pRight);
	printf("%c ", pRoot->_data);
}


void PostOrderNor(BTNode* pRoot)
{
	assert(pRoot);
	BTNode* cur = NULL;
	BTNode* prev = NULL;
	Stack s;
	InitStack(&s);

	PushStack(&s, pRoot);
	while (!EmptyStack(&s))
	{
		cur = TopStack(&s);
		if ((cur->_pLeft == NULL && cur->_pRight == NULL) 
			|| ((prev != NULL) && (prev == cur->_pLeft || prev == cur->_pRight)))
		{
			printf("%c ", cur->_data);
			PopStack(&s);
			prev = cur;
			continue;
		}

		if (cur->_pRight)
			PushStack(&s, cur->_pRight);
		if (cur->_pLeft)
			PushStack(&s, cur->_pLeft);
	}
}


void LevelOrder(BTNode* pRoot)
{
	assert(pRoot);
	Queue q;
	BTNode* temp = NULL;
	InitQueue(&q);

	PushQueue(&q, pRoot);
	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		printf("%c ", temp->_data);

		if (temp->_pLeft)
			PushQueue(&q, temp->_pLeft);
		if (temp->_pRight)
			PushQueue(&q, temp->_pRight);

		PopQueue(&q);
	}
}


BTNode* CopyBinTree(BTNode* pRoot)
{
	BTNode* pNewRoot = NULL;
	if (pRoot)
	{
		pNewRoot = BuyBTNode(pRoot->_data);

		if (pRoot->_pLeft)
			pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft);

		if (pRoot->_pRight)
			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;
	}
}


int GetBTNodeCount(BTNode* pRoot)
{
	if (NULL == pRoot)
		return 0;
	return GetBTNodeCount(pRoot->_pLeft) + GetBTNodeCount(pRoot->_pRight) + 1;
}

int GetLeafNodeCount(BTNode* pRoot)
{
	if (NULL == pRoot)
		return 0;
	if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
		return 1;
	return GetLeafNodeCount(pRoot->_pLeft) + GetLeafNodeCount(pRoot->_pRight);
}


int GetKLevelNodeCount(BTNode* pRoot, int K)
{
	if (K <= 0 || pRoot == NULL)
		return 0;
	if (K == 1)
		return 1;
	return GetKLevelNodeCount(pRoot->_pLeft, K - 1) + GetKLevelNodeCount(pRoot->_pRight, K - 1);

}


int Height(BTNode* pRoot)
{
	int LeftHeight = 0;
	int RightHeight = 0;
	if (NULL == pRoot)
		return 0;

	LeftHeight = Height(pRoot->_pLeft);
	RightHeight = Height(pRoot->_pRight);

	return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
}


int IsBTNodeInBinTree(BTNode* pRoot, BTNode* pNode)
{
	if (pRoot == NULL || pNode == NULL)
		return 0;
	if (pRoot == pNode)
		return 1;
	if (IsBTNodeInBinTree(pRoot->_pLeft, pNode))
		return 1;
	return IsBTNodeInBinTree(pRoot->_pRight, pNode);
}


BTNode*  GetBTNodeParent(BTNode* pRoot, BTNode* pNode)
{
	BTNode* pParent = NULL;
	if (pRoot == NULL || pNode == NULL || pRoot == pNode)
		return NULL;
	if (pNode == pRoot->_pLeft || pNode == pRoot->_pRight)
		return pRoot;
	if (pParent = GetBTNodeParent(pRoot->_pLeft, pNode))
		return pParent;
	return GetBTNodeParent(pRoot->_pRight, pNode);
}

void Swap(BTNode** Left, BTNode** Right)
{
	BTNode* temp = *Left;
	*Left = *Right;
	*Right = temp;
}

void MirrorBinTree(BTNode* pRoot)
{
	if (pRoot)
	{
		Swap(&pRoot->_pLeft, &pRoot->_pRight);
		MirrorBinTree(pRoot->_pLeft);
		MirrorBinTree(pRoot->_pRight);
	}
}

void MirrorBinTreeNor(BTNode* pRoot)
{
	Queue q;
	BTNode* temp = NULL;
	if (NULL == pRoot)
		return;
	InitQueue(&q);
	PushQueue(&q, pRoot);

	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		Swap(&temp->_pLeft, &temp->_pRight);

		if (temp->_pLeft)
			PushQueue(&q, temp->_pLeft);
		if (temp->_pRight)
			PushQueue(&q, temp->_pRight);

		PopQueue(&q);
	}
}



int IsCompleteBinTree(BTNode* pRoot)
{
	Queue q;
	BTNode* temp = NULL;
	int Flag = 0;
	if (pRoot == NULL)
		return 1;
	InitQueue(&q);
	PushQueue(&q, pRoot);
	while (!EmptyQueue(&q))
	{
		temp = FrontQueue(&q);
		if (Flag)
		{
			if (temp->_pLeft || temp->_pRight)
				return 0;
		}
		else
		{
			if (temp->_pLeft && temp->_pRight)
			{
				PushQueue(&q, temp->_pLeft);
				PushQueue(&q, temp->_pRight);
			}
			else if (temp->_pLeft)
			{
				PushQueue(&q, temp->_pLeft);
				Flag = 1;
			}
			else if (temp->_pRight)
				return 0;
			else
				Flag = 1;
		}

		PopQueue(&q);
	}
}


BTNode* LeftChild(BTNode* pNode)
{
	return (NULL != pNode) ? pNode->_pLeft : NULL;
}


BTNode* RightChild(BTNode* pNode)
{
	return (NULL != pNode) ? pNode->_pRight : NULL;
}

#include<string.h>

void TestBTree()
{
	char* pStr = "ABD###CE##F";
	BTNode* pRoot = NULL;
	int index = 0;
	BTNode* pRootC = NULL;

	CreateBinTree(&pRoot, pStr, strlen(pStr), &index, '#');
	printf("二叉树中节点的总个数为: %d\n", GetBTNodeCount(pRoot));
	printf("二叉树中叶子节点的总个数为: %d\n", GetLeafNodeCount(pRoot));
	printf("二叉树第3层中节点的个数为: %d\n", GetKLevelNodeCount(pRoot, 3));
	printf("二叉树的高度为: %d\n", Height(pRoot));
	if (IsCompleteBinTree(pRoot))
		printf("是完全二叉树!!!\n");
	else
		printf("不是完全二叉树!!!\n");

	MirrorBinTree(pRoot);
	MirrorBinTreeNor(pRoot);

	printf("前序递归遍历:");
	PreOrder(pRoot);
	printf("\n");
	printf("前序非递归遍历:");
	PreOrderNor(pRoot);
	printf("\n");

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

	printf("中序非递归遍历:");
	InOrderNor(pRoot);
	printf("\n");

	printf("后续遍历:");
	PostOrder(pRoot);
	printf("\n");

	printf("后续非递归遍历:");
	PostOrderNor(pRoot);
	printf("\n");

	printf("层序遍历:");
	LevelOrder(pRoot);
	printf("\n");

	pRootC = CopyBinTree(pRoot);
	printf("前序遍历:");
	PreOrder(pRootC);
	printf("\n");

	printf("中序遍历:");
	InOrder(pRootC);
	printf("\n");

	printf("后续遍历:");
	PostOrder(pRootC);
	printf("\n");

	DestroyBinTree(&pRoot);
	DestroyBinTree(&pRootC);
}
  • stack.c:栈的函数
#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>

#define INITSIZE 100
#define INCREASESIZE 10

typedef char DataType;

typedef struct BTNode
{
	DataType _data;
	struct BTNode* _pLeft;
	struct BTNode* _pRight;
}BTNode;

typedef BTNode* SDataType;

typedef struct Stack {
	SDataType* array;
	int size;
	int capacity;
}Stack;

void InitStack(Stack* s)
{
	assert(s);
	s->array = (SDataType*)malloc(INITSIZE*sizeof(SDataType));
	if (!s->array)
	{
		assert(0);
		return;
	}
	s->capacity = INITSIZE;
	s->size = 0;
}

void PushStack(Stack* s, SDataType data)
{
	assert(s);
	if (s->size >= s->capacity)
	{
		s->array = (SDataType*)realloc(s->array,(s->capacity + INCREASESIZE)* sizeof(SDataType));
		if (!s->array)
		{
			assert(0);
			return;
		}
		s->capacity = s->capacity + INCREASESIZE;
	}
	s->array[s->size] = data;
	s->size++;
}

void PopStack(Stack* s)
{
	assert(s);
	if (s->size == 0)
		return;
	else
		s->size--;
}

SDataType TopStack(Stack* s)
{
	assert(s);
	if (s->size == 0)
	{
		assert(0);
		return;
	}
	return (s->array[s->size - 1]);
}

int SizeStack(Stack* s)
{
	assert(s);
	return s->size;
}

int EmptyStack(Stack* s)
{
	assert(s);
	if (s->size == 0)
		return 1;
	else
		return 0;
}
  • queue.c:队列的函数
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"stack.h"


typedef BTNode* LDataType;

typedef struct Node{
	LDataType _data;
	struct Node* _next;
}Node;

typedef Node QDataType;

typedef struct Queue{
	
	QDataType* front;
	QDataType* rear;
	int size;
}Queue;


void InitQueue(Queue* q)
{
	assert(q);
	q->rear = (QDataType*)malloc(sizeof(QDataType));
	if (!q->front)
	{
		assert(0);
		return;
	}
	q->front = q->rear;
	q->size = 0;
}

void PushQueue(Queue* q, LDataType data)
{
	assert(q);
	QDataType* new_node = NULL;
	if (q->size == 0)
	{
		q->rear->_data = data;
		q->size++;
	}
	else
	{
		new_node = (QDataType*)malloc(sizeof(QDataType));
		if (!new_node)
		{
			assert(0);
			return;
		}
		new_node->_data = data;
		new_node->_next = NULL;

		q->rear->_next = new_node;
		q->rear = new_node;
		q->size++;
	}
}

void PopQueue(Queue* q)
{
	assert(q);
	QDataType* temp = NULL;
	if (q->size == 0)
	{
		return;
	}
	else if (q->size == 1)
	{
		q->size--;
	}
	else
	{
		temp = q->front->_next;
		free(q->front);
		q->front = temp;
		q->size--;
	}
}

LDataType FrontQueue(Queue* q)
{
	assert(q);
	if (q->size == 0)
		return NULL;
	else
		return q->front->_data;
}

int EmptyQueue(Queue* q)
{
	assert(q);
	if (q->size == 0)
		return 1;
	return 0;
}
  • 测试函数
#include"BTree.h"

int main()
{
	TestBTree();
	return 0;
}

总结:递归的思想应该懂得,还有栈和队列的思想解决问题。有什么问题的话欢迎下方留言。

猜你喜欢

转载自blog.csdn.net/qq_40421919/article/details/82933959