二叉树的基本操作

目录

一、基本概念

二、基本操作

(一)先序遍历

1.图解

2.代码

(二)中序遍历

1.图解

2.代码

(三)后序遍历

代码

(四)求结点个数

1.图解

2.代码

(五)叶子结点个数

1.图解

2.代码

(六)树的高度

1.图解

2.代码

(七)求树第k层的结点数量

1.图解

2.代码

(八)查找数据是x的结点

(九)销毁

(十)层序遍历

(十一)判断是不是完全二叉树

三、完整代码

四、层序遍历+判断完全二叉树


一、基本概念

  • 节点的度:一个节点含有的子树的个数称为该节点的度
  • 叶节点或终端节点:度为0的节点称为叶节点
  • 非终端节点或分支节点:度不为0的节点
  • 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点
  • 树的度:一棵树中,最大的节点的度称为树的度
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
  • 树的高度或深度:树中节点的最大层次
  • 堂兄弟节点:双亲在同一层的节点互为堂兄弟
  • 节点的祖先:从根到该节点所经分支上的所有节点
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙
  • 森林:由m(m>0)棵互不相交的树的集合称为森林

二、基本操作

(一)先序遍历

1.图解

2.代码

void PreOrder(BTNode* root)//先序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

(二)中序遍历

1.图解

2.代码

void InOrder(BTNode* root)//中序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

(三)后序遍历

代码

void PostOrder(BTNode* root)//后序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->data);
}

(四)求结点个数

1.图解

2.代码

int BTreeSize(BTNode* root)//求结点个数
{
	if (root == NULL)
		return 0;
	return BTreeSize(root->left) 
		  + BTreeSize(root->right) + 1;//左子树的结点+右子树结点+再加其本身一个
}

(五)叶子结点个数

1.图解

2.代码

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

	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}

(六)树的高度

1.图解

2.代码

int BTreeHeight(BTNode* root)//树的高度
{
	if (root == NULL)
		return 0;
	int leftH = BTreeHeight(root->left);
	int rightH = BTreeHeight(root->right);

	return leftH > rightH ? leftH + 1 : rightH + 1;
}

(七)求树第k层的结点数量

1.图解

2.代码

int BTreeLevelK(BTNode* root, int k)//第k层结点个数
{
	if (root == NULL)
		return 0;
	//后面意味着root都不为空
	if (k == 1)
		return 1;
	k = k - 1;
	return BTreeLevelK(root->left, k) 
		+ BTreeLevelK(root->right, k);
}

(八)查找数据是x的结点

BTNode* BTreeFind(BTNode* root, BTDataType x)//查找数据是x的结点
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;

	int ret1 = BTreeFind(root->left, x);//记录左树查找的结果
	int ret2 = BTreeFind(root->right, x);//记录右树查找的结果

	if (ret1 != NULL)
		return ret1;
	if (ret2 != NULL)
		return ret2;

	return NULL;
} 

(九)销毁

void BTreeDestroy(BTNode* root)
{
	if (root == NULL)
		return true;

	BTreeDestroy(root->left);
	BTreeDestroy(root->right);
	free(root);
}

(十)层序遍历

void LevelOrder(BTNode* root)//层序遍历
{
	Queue q;
	QInit(&q);

	if (root)//根结点先入队
	{
		QPush(&q, root);
	}

	while (!ISEmpty(&q))//循环进队
	{
		BTNode* front = QFront(&q);//先保存对头结点
		QPop(&q);

		if (front != NULL)
		{
			printf("%d ", front->data);
			if (front->left)
				QPush(&q, front->left);
			if (front->right)
				QPush(&q, front->right);
		}
	}

}

(十一)判断是不是完全二叉树

 

bool BTreeComplete(BTNode* root)//判断完全二叉树
{
	Queue q;
	QInit(&q);

	if (root)
		QPush(&q,root);

	while (!ISEmpty(&q))
	{
		BTNode* front = QFront(&q);
		QPop(&q);

		if (front!=NULL)
		{
			QPush(&q,front->left);
			QPush(&q,front->right);
		}

		if (front == NULL)
			break;
	}

	while (!ISEmpty(&q))
	{
		if(QFront(&q)== NULL)
		  QPop(&q);
		else
		{
			QDestroy(&q);
			return false;
		}

	}

	QDestroy(&q);
	return true;
}

 

三、完整代码

//BinaryTree.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTree
{
	BTDataType data;
	struct BinaryTree* left;
	struct BinaryTree* right;
}BTNode;

BTNode* NewNode(BTDataType x);//建立结点
BTNode* CreateTree();//创建一棵树
void PreOrder(BTNode* root);//先序遍历
void InOrder(BTNode* root);//中序遍历
void PostOrder(BTNode* root);//后序遍历
int BTreeSize(BTNode* root);//求结点个数
int BTreeLeafSize(BTNode* root);//叶子结点个数
int BTreeHeight(BTNode* root);//树的高度(左子树的高度+1/右子树的高度+1)
int BTreeLevelK(BTNode* root, int k);//第k层结点个数

BTNode* BTreeFind(BTNode* root, BTDataType x);//查找数据是x的结点
//BinaryTree.c

#include"BinaryTree.h"
BTNode* NewNode(BTDataType  x)//建立结点
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		return;
	}

	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;

	return newnode;
}

BTNode* CreateTree()//创建一棵树
{
	 BTNode* node1=NewNode(12);
	 BTNode* node2 = NewNode(39);
	 BTNode* node3 = NewNode(46);
	 BTNode* node4 = NewNode(87);
	 BTNode* node5 = NewNode(66);
	 BTNode* node6 = NewNode(53);
	 



	 //将结点连接起来
	 node1->left = node2;
	 node1->right = node3;
	 node2->left = node4;
	 node2->right = node5;
	 node3->left = node6;


	 return node1;

}

void PreOrder(BTNode* root)//先序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

void InOrder(BTNode* root)//中序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

void PostOrder(BTNode* root)//后序遍历
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->data);
}

int BTreeSize(BTNode* root)//求结点个数
{
	if (root == NULL)
		return 0;
	return BTreeSize(root->left) + BTreeSize(root->right) + 1;//左子树的结点+右子树结点+再加其本身一个
}

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

	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}

int BTreeHeight(BTNode* root)//树的高度
{
	if (root == NULL)
		return 0;
	int leftH = BTreeHeight(root->left);
	int rightH = BTreeHeight(root->right);

	return leftH > rightH ? leftH + 1 : rightH + 1;
}


int BTreeLevelK(BTNode* root, int k)//第k层结点个数
{
	if (root == NULL)
		return 0;
	//后面意味着root都不为空
	if (k == 1)
		return 1;
	k = k - 1;
	return BTreeLevelK(root->left, k) 
		+ BTreeLevelK(root->right, k);
}


BTNode* BTreeFind(BTNode* root, BTDataType x)//查找数据是x的结点
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;

	int ret1 = BTreeFind(root->left, x);//记录左树查找的结果
	int ret2 = BTreeFind(root->right, x);//记录右树查找的结果

	if (ret1 != NULL)
		return ret1;
	if (ret2 != NULL)
		return ret2;

	return NULL;
} 

//Test.c
#include"BinaryTree.h"
int main()
{
	BTNode* root = CreateTree();
	 //                       12
     //                     /    \
	 //                   39     46
	 //                 /    \  / 
	 //                87    66 53
	 //
	 //
	printf("先序遍历:");
	PreOrder(root);//先序遍历
	printf("\n");

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

	printf("后序遍历:");
	PostOrder(root);
	printf("\n");

	//结点个数
	printf("结点个数:");
	printf("%d\n", BTreeSize(root));

	//叶子结点个数
	printf("叶子结点个数:");
	printf("%d\n", BTreeLeafSize(root));

	//树的高度
	printf("树的高度:");
	printf("%d\n", BTreeHeight(root));

	BTNode* r = BTreeFind(root, 109);
	if (r == NULL)
	{
		printf("未找到!\n");
	}
	else
	{
		printf("%d\n", r->data);
	}

	//求第k层的结点个数
	int k = 3;
	printf("第%d层结点数量:%d\n", k,BTreeLevelK(root,k));
	return 0;
}

四、层序遍历+判断完全二叉树

//BinaryTree.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int BTDataType;
typedef struct BinaryTree
{
	BTDataType data;
	struct BinaryTree* left;
	struct BinaryTree* right;
}BTNode;

BTNode* NewNode(BTDataType x);//建立结点
BTNode* CreateTree();//创建一棵树
void LevelOrder(BTNode* root);//层序遍历
bool BTreeComplete(BTNode* root);//判断完全二叉树


//队列的定义
typedef struct BinaryTree* ElemType;
typedef struct QueueNode
{
	struct QueueNode* next;
	ElemType data;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* tail;
	int size;
}Queue;

void QInit(Queue* p);//初始化
void QDestroy(Queue* p);//销毁
bool ISEmpty(Queue* p);//判空
void QPush(Queue* p, ElemType x);//进队
void QPop(Queue* p);//出队
ElemType QFront(Queue* p);//获取队头元素
ElemType QBack(Queue* p);//获取队尾元素
//BinaryTree.c

#include"BinaryTree.h"
BTNode* NewNode(BTDataType  x)//建立结点
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		return;
	}

	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;

	return newnode;
}

BTNode* CreateTree()//创建一棵树
{
	BTNode* node1 = NewNode(12);
	BTNode* node2 = NewNode(39);
	BTNode* node3 = NewNode(46);
	BTNode* node4 = NewNode(87);
	BTNode* node5 = NewNode(66);
	BTNode* node6 = NewNode(53);




	//将结点连接起来
	node1->left = node2;
	node1->right = node3;
	node2->left = node4;
	node2->right = node5;
	node3->right = node6;


	return node1;

}

void LevelOrder(BTNode* root)//层序遍历
{
	Queue q;
	QInit(&q);

	if (root)//根结点先入队
	{
		QPush(&q, root);
	}

	while (!ISEmpty(&q))//循环进队
	{
		BTNode* front = QFront(&q);//先保存对头结点
		QPop(&q);

		if (front != NULL)
		{
			printf("%d ", front->data);
			if (front->left)
				QPush(&q, front->left);
			if (front->right)
				QPush(&q, front->right);
		}
	}

}

bool BTreeComplete(BTNode* root)//判断完全二叉树
{
	Queue q;
	QInit(&q);

	if (root)
		QPush(&q,root);

	while (!ISEmpty(&q))
	{
		BTNode* front = QFront(&q);
		QPop(&q);

		if (front!=NULL)
		{
			QPush(&q,front->left);
			QPush(&q,front->right);
		}

		if (front == NULL)
			break;
	}

	while (!ISEmpty(&q))
	{
		if(QFront(&q)== NULL)
		  QPop(&q);
		else
		{
			QDestroy(&q);
			return false;
		}

	}

	QDestroy(&q);
	return true;
}


//队列
void QInit(Queue* p)//初始化
{
	assert(p);

	p->phead = p->tail = NULL;
	p->size = 0;
}

void QDestroy(Queue* p)//销毁
{
	assert(p);

	QNode* cur = p->phead;
	while (cur != NULL)
	{
		QNode* next = cur->next;//先保存cur的下一个结点
		free(cur);
		cur = next;
	}

	p->phead = p->tail = NULL;
	p->size = 0;
}

bool ISEmpty(Queue* p)//判空
{
	assert(p);

	return p->size == 0;
}


void QPush(Queue* p, ElemType x)//进队
{
	assert(p);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		return;
	}
	//新生成的结点存放x
	newnode->data = x;
	newnode->next = NULL;

	if (ISEmpty(p))//原来的队列为空
	{
		p->phead = newnode;
		p->tail = newnode;
	}
	else
	{
		p->tail->next = newnode;
		p->tail = newnode;
	}

	p->size++;
}

void QPop(Queue* p)//出队
{
	assert(p);

	if (ISEmpty(p))
	{
		printf("已空!\n");
		return;
	}
	else if (p->phead->next == NULL)
	{
		free(p->phead);
		p->phead = p->tail = NULL;
		p->size = 0;
	}
	else
	{
		QNode* second = p->phead->next;
		free(p->phead);
		p->phead = second;
		p->size--;
	}
}

ElemType QFront(Queue* p)//获取队头元素
{
	assert(p);
	assert(!ISEmpty(p));
	return p->phead->data;
}

ElemType QBack(Queue* p)//获取队尾元素
{
	assert(p);
	assert(!ISEmpty(p));
	return p->tail->data;
}

//Test.c
#include"BinaryTree.h"
int main()
{
	BTNode* root = CreateTree();
	//                       12
	//                     /    \
	 //                   39     46
	 //                 /    \     \
	 //                87    66     53
	 //
	 //

	printf("层序遍历结果:");
	LevelOrder(root);
	printf("\n");

	if (BTreeComplete(root))
		printf("是完全二叉树!\n");
	else
		printf("不是完全二叉树!\n");
	return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值