【数据结构】二叉树的基本操作

本文介绍了二叉树的基本操作,包括头文件BinTree.h、BinTree.c以及用于测试的test.c,详细讲解了二叉树的插入、删除、遍历等核心功能。
摘要由CSDN通过智能技术生成

二叉树的基本操作

BinTree.h

	#pragma once

	#include<stdio.h>
	#include<stddef.h>
	#include<assert.h>

	typedef char BinTreeType;

	typedef struct BinTreeNode {
		BinTreeType data;
		struct BinTreeNode* lchild;
		struct BinTreeNode* rchild;
	}BinTreeNode;

	/*初始化*/
	void BinTreeInit(BinTreeNode** root);

	/*创建一个二叉树结点*/
	BinTreeNode* CreateBinTreeNode(BinTreeType value);
	/*
	**前序遍历
	**递归和非递归实现
	*/
	void BinTreePreOrder1(BinTreeNode* root);
	void BinTreePreOrder2(BinTreeNode* root);

	/*
	**中序遍历
	**递归和非递归实现
	*/
	void BinTreeInOrder1(BinTreeNode* root);
	void BinTreeInOrder2(BinTreeNode* root);

	/*
	**后续遍历
	**递归和非递归实现
	*/
	void BinTreePostOrder1(BinTreeNode* root);
	void BinTreePostOrder2(BinTreeNode* root);

	/*层级遍历*/
	void BinTreeLevelOrder(BinTreeNode* root);

	/*给定一个树的前序遍历,求出树,带空结点标记*/

	BinTreeNode* GetBinTree_Pre(BinTreeType array[], size_t size, BinTreeType null_node);

	/*销毁树*/
	void BinTreeDestory(BinTreeNode** root);

	//复制树
	BinTreeNode* BinTreeClone(BinTreeNode* root, BinTreeNode* new_root);

	/*求树的结点的个数*/
	size_t BinTreeSize(BinTreeNode* root);

	/*求叶子结点的个数*/
	size_t BinTreeLeafSize(BinTreeNode* root);

	/*第k层的结点的个数*/
	size_t BinTreeKlevelSize(BinTreeNode* root, int k);

	/*树的高度*/
	size_t BinTreeHeight(BinTreeNode* root);

	/*在树中查找某个结点*/
	BinTreeNode* BinTreeFind(BinTreeNode* root, BinTreeType to_find);

	/*
	**查找左孩子结点,
	**查找右孩子结点,
	**查找双亲结点
	*/
	BinTreeNode* BinTreeLChild(BinTreeNode* node);
	BinTreeNode* BinTreerChild(BinTreeNode* node);
	BinTreeNode* BinTreeParent(BinTreeNode* root, BinTreeNode* node);

	/*把链表镜像反转*/
	void BinTreeMirror(BinTreeNode* root);

	/*判断当前链表是否是完全二叉树*/
	int IsCompleteTree(BinTreeNode* root);

	/*由前序遍历序列和中序遍历序列重建二叉树*/
	BinTreeNode* ReBulidBinTree(BinTreeType pre_array[], size_t pre_size, 
								BinTreeType in_array[], size_t in_size);



BinTree.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Bin_Tree.h"
#include"SeqStack.h"
#include"SeqQueue.h"

void BinTreeInit(BinTreeNode** root) {
	if (root == NULL) {
		return;
	}
	*root = NULL;
}

BinTreeNode* CreateBinTreeNode(BinTreeType value) {
	BinTreeNode* node = (BinTreeNode*)malloc(sizeof(BinTreeNode));

	if (node != NULL) {
		node->data = value;
		node->lchild = NULL;
		node->rchild = NULL;
	}
	return node;
}

/*
**前序遍历
**递归实现
*/
void BinTreePreOrder1(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	printf("%c ", root->data);
	BinTreePreOrder1(root->lchild);
	BinTreePreOrder1(root->rchild);
}
/*非递归实现*/
void BinTreePreOrder2(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	SeqStack seq;
	SeqStackInit(&seq);
	SeqStackPush(&seq, root);

	BinTreeNode* top = NULL;
	while (1) {
		/*判断栈是不是空,如果是表示树已经遍历完毕*/
		if (isEmpty(&seq)) {
			break;
		}
		/*取了个栈顶元素,然后出栈一个元素*/
		top = SeqStackTopValue(&seq);
		SeqStackPop(&seq);
		printf("%c ", top->data);

		if (top->rchild != NULL) {
			SeqStackPush(&seq, top->rchild);
		}
		if (top->lchild != NULL) {
			SeqStackPush(&seq, top->lchild);
		}
	}
	printf("\n");
}

/*
**中序遍历
*/
//递归
void BinTreeInOrder1(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	BinTreeInOrder1(root->lchild);
	printf("%c ", root->data);
	BinTreeInOrder1(root->rchild);
}
//非递归
void BinTreeInOrder2(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	SeqStack seq;
	SeqStackInit(&seq);

	while (NULL != root || !isEmpty(&seq)) {
		while (root) {
			SeqStackPush(&seq, root);
			root = root->lchild;
		}
		root = SeqStackTopValue(&seq);
		printf("%c ", root->data);
		SeqStackPop(&seq);

		/*如果当前结点右子树为空,就把root置为空再继续循环*/
		if (root->rchild == NULL) {
			root = NULL;
		}
		else {
			/*如果当前结点的右子树不为空,就访问root的右子树*/
			root = root->rchild;
		}
	}
	printf("\n");
}

/*
**后续遍历
**递归和非递归实现
*/
//递归实现
void BinTreePostOrder1(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	BinTreePostOrder1(root->lchild);
	BinTreePostOrder1(root->rchild);

	printf("%c ", root->data);
}

//非递归实现
void BinTreePostOrder2(BinTreeNode* root) {
	if (root == NULL) {
		return;
	}
	SeqStack stack;
	SeqStackInit(&stack);
	
	BinTreeNode* prev = NULL;
	while (root != NULL || !isEmpty(&stack)) {
		/*直接让root走到当前树的最左边的叶节点*/
		while (root) {
			SeqStackPush(&stack, root);
			root = root->lchild;
		}

		/*root等于当前栈顶元素*/
		root = SeqStackTopValue(&stack);

		/*
		**如果当前结点的右孩子结点为空,或者,
		**已经出栈打印的上一个结点等于当前结点的右孩子结点
		*/
		if (root->rchild == NULL || prev == root->rchild) {
			/*prev表示最后打印的结点,即已经遍历完的最后一个结点*/
			prev = root;
			printf("%c ", root->data);
			SeqStackPop(&stack);
			root = NULL;
		}
		else {
			/*让
二叉树是一种重要的数据结构,由于其特殊的结构和性质,需要具备一些基本的操作来对二叉树进行处理。 首先是创建二叉树。可以通过读取用户输入或者其他方式来构建一个二叉树。创建二叉树的过程可以使用递归的方式,通过不断地输入节点的值和连接关系来构造二叉树。 其次是遍历二叉树。常见的遍历方式有前序遍历、中序遍历和后序遍历。前序遍历先访问根节点,然后遍历左子树和右子树;中序遍历按照左子树、根节点和右子树的顺序遍历;后序遍历先遍历左子树和右子树,最后访问根节点。通过递归的方式,可以实现这三种遍历方式。 另外一个常用的操作是查找二叉树中的节点。可以通过比较节点的值,逐层搜索二叉树,找到目标节点。如果目标节点不存在,可以返回一个特定的值来表示找不到。 还有一个重要的操作是插入节点。可以通过比较节点的值,找到插入的位置。如果待插入的节点小于当前节点,就插入到左子树中;如果待插入的节点大于当前节点,就插入到右子树中。插入节点后,需要调整二叉树的结构,保持二叉树的性质。 最后,删除节点也是一个常见的操作。删除节点时,需要考虑节点的左右子树。可以通过将节点的左子树的最大节点或者右子树的最小节点上移来替代被删除的节点。删除节点后,同样需要调整二叉树的结构,保持二叉树的性质。 这些是二叉树基本操作,它们在实际应用中有广泛的应用,比如在搜索、排序和图等领域。掌握这些操作,可以更好地理解和应用二叉树
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值