二叉树

一、说明

本文的Stack.h参考博客中的栈,Queue.h参考博客中的队列。

二、二叉树概念

一棵二叉树时结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别为左子树和右子树组成;二叉树每个结点最多有两棵子树,子树有左右之分,次序不能颠倒。

三、二叉树的前中后非递归遍历

二叉树的前中后递归遍历非常简单,但是非递归有点小难,所以我把非递归的算法思想说一下,在实现非递归时我们需要利用到栈。

前序:我们先说一下前序的非递归(以下全是非递归,不再作说明),光靠文字表述可能会不清楚,所以我画了个草图,以下也用此二叉树为例。

 因为前序的顺序是根左右,所以我们先遍历和入栈的顺序是A、B、D,当入到D时发现无左右结点所以D出栈,看B是否有右结点,发现B也没,所以也出栈,找A,A有,从C开始上述的过程直到栈为空而且右子树指针为空。每入栈一个元素就输出,这样就完成了前序遍历。

中序 :中序的顺序是左根右,所用的方法跟前序差不多,只不过前序是入栈就输出,而中序是出栈才输出。

后序:后序的顺序是左右根,与前后不一样的是只有在结点无右孩子时才出栈和输出。

四、二叉树的层序遍历

二叉树的层序遍历顾名思义就是一层一层的遍历,本算法用队列来解决。

先将第一层的结点入队 ,每次将队头左右结点入队并进行出队操作,出队顺序就是层序遍历的结果。

五、完全二叉树的判断

满二叉树:在一棵二叉树中,如果所有的分支结点都存在左子树和右子树,并且所有的叶子节点都在同一层上。

完全二叉树:一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同。

我们先把第一层结点入队,然后将它的左右孩子入队(如果为空入队“#”)并且进行出队操作,当他的队头为空时停止操作;接下来就是判断,如果队头为空但是队列不为空时此二叉树不是完全二叉树,如果队列为空就是完全二叉树,因为完全二叉树的话结点为空后面不可能有结点的。

六、源代码

1、bintree.h

#ifndef _BINTREE__H_
#define _BINTREE__H_

#include "stdio.h"
#include "malloc.h"
#include "assert.h"
#include "stdlib.h"
#include "Queue.h"
#include "Stack.h"

typedef char BTDataType;
typedef struct BTNode
{
	struct BTNode* left;
	struct BTNode* right;
	BTDataType data;
}BTNode;

BTNode* BTCreate(BTDataType* a, int n, int *pi);
void BTDestory(BTNode* *root);
int BTSize(BTNode* root);
int BTLeafSize(BTNode* root);
int BTLevelkSize(BTNode* root,int x);
BTNode* BTFind(BTNode* root,BTDataType x);
void BTPrevOrder(BTNode* root);
void BTInOrder(BTNode* root);
void BTPostOrder(BTNode* root);
void BTLeveOrder(BTNode* root);
int BTComplete(BTNode* root);
void BTPrevOrderNonR(BTNode* root);
void BTInOrderNonR(BTNode* root);
void BTPostOrderNonR(BTNode* root);

#endif

2、bintree.c

#include "bintree.h"
//创建结点
BTNode* BuyBTNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	node->left = node->right = NULL;
	node->data = x;
	return node;
}
//搭建二叉树
BTNode* BTCreate(BTDataType* a, int n, int *pi)
{
	if (a[*pi] != '#')
	{
		BTNode* root = BuyBTNode(a[*pi]);
		++(*pi);
		root->left = BTCreate(a, n, pi);
		++(*pi);
		root->right = BTCreate(a, n, pi);
		return root;
	}
	return NULL;
}
//清除二叉树
void BTDestory(BTNode* *root)
{
	BTNode* tmp;
	tmp = *root;
	BTDestory(&tmp->left);
	BTDestory(&tmp->right);
	free(root);
	tmp = NULL;
}
//结点数
int BTSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	return BTSize(root->left) + BTSize(root->right) + 1;
}
//左孩子结点数
int BTLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL&&root->right == NULL)
	{
		return 1;
	}
	return BTLeafSize(root->left) + BTLeafSize(root->right);
}
//第x层的结点数
int BTLevelkSize(BTNode* root, int x)
{
	if (root == NULL)
		return 0;
	if (x == 1)
		return 1;
	return BTLevelkSize(root->left, x - 1) + BTLevelkSize(root->right, x - 1);
}
//查找指定元素
BTNode* BTFind(BTNode* root, BTDataType x)
{
	BTNode* ret = NULL;
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	ret = BTFind(root->left, x);
	if (ret)
		return ret;
	ret = BTFind(root->right, x);
	if (ret)
		return ret;
	return NULL;
}
//前序遍历(递归)
void BTPrevOrder(BTNode* root)
{
	if (root == NULL)
		return;
	printf("%c", root->data);
	BTPrevOrder(root->left);
	BTPrevOrder(root->right);
}
//中序遍历(递归)
void BTInOrder(BTNode* root)
{
	if (root == NULL)
		return;
	BTInOrder(root->left);
	printf("%c", root->data);
	BTInOrder(root->right);
}
//后序遍历(递归)
void BTPostOrder(BTNode* root)
{
	if (root == NULL)
		return;
	BTPostOrder(root->left);
	BTPostOrder(root->right);
	printf("%c", root->data);
}
//层序遍历
void BTLeveOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	BTNode* front;
	if (root)
		QueuePush(&q, root);
	while (QueueEmpty(&q))
	{
		front = QueueFront(&q);
		printf("%c", front->data);
		QueuePop(&q);
		if (front->left!=NULL)
		{
			QueuePush(&q, front->left);
		}
		if (front->right!=NULL)
		{
			QueuePush(&q, front->right);
		}
	}
}
//判断是否是完全二叉树
int BTComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	BTNode* front;
	if (root)
		QueuePush(&q, root);
	while (QueueEmpty(&q))
	{
		front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
		else
			break;
	}
	while (QueueEmpty(&q))
	{
		front = QueueFront(&q);
		if (front)
		{
			QueueDestory(&q);
			return 0;
		}
		else
			QueuePop(&q);
	}
	return 1;
}
//前序遍历(非递归)
void BTPrevOrderNonR(BTNode* root)
{
	Stack s;
	StackInit(&s, 20);
	BTNode* top;
	BTNode* cur = root;
	while (cur || StackEmpty(&s)!=0)
	{
		while (cur)
		{
			printf("%c", cur->data);
			StackPush(&s, cur);
			cur = cur->left;
		}
		top = StackTop(&s);
		StackPop(&s);
		cur = top->right;
	}
	printf("\n");
}
//中序遍历(非递归)
void BTInOrderNonR(BTNode* root)
{
	Stack s;
	StackInit(&s, 20);
	BTNode* top;
	BTNode* cur = root;
	while (cur || StackEmpty(&s) != 0)
	{
		while (cur)
		{
			StackPush(&s, cur);
			cur = cur->left;
		}
		top = StackTop(&s);
		printf("%c", top->data);
		StackPop(&s);
		cur = top->right;
	}
	printf("\n");
}
//后序遍历(非递归)
void BTPostOrderNonR(BTNode* root)
{
	Stack s;
	StackInit(&s, 20);
	BTNode* top, *prav=NULL;
	BTNode* cur = root;
	while (cur || StackEmpty(&s) != 0)
	{
		while (cur)
		{
			StackPush(&s, cur);
			cur = cur->left;
		}
		top = StackTop(&s);
		if (top->right == NULL || top->right == prav)
		{
			printf("%c", top->data);
			prav = top;
			StackPop(&s);

		}
		else
		{
			cur = top->right;
		}
	}
	printf("\n");
}

3、写一个测试(test.c)让代码跑起来并加以验证

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值