数据结构之二叉树的代码实现 C语言版

前言

树是一种结合了另外两种数据结构的优点的结构
一种是顺序表,树结构的查询速度和有序数组一样快
一种是链表,树结构的插入数据和删除数据速度和链表一样快
在树的操作中,大量运用了递归的原理

1.二叉树的结构体表示

这个表示和前面链表的结构体表示有点类似,不过他内部包含了两个指针域。
大概可以这么理解,链表是一维的,你可以认为他只有宽度,而二叉树是二维的,既有深度也有“宽度”,有明显的层次关系,比链表要复杂一些

typedef struct BTNode
{
	TElemType data;
	struct BTNode *lchild,*rchild;
}BTNode,*BTree;

2.一些操作

二叉树的一些基本操作包括了创建,三种遍历,求结构个数,深度,叶子结点数
而这些操作中,都用到了递归的方法
以一颗二叉树作为典型:

二叉树

3.前序创建

二叉树用前序创建,空用‘#’来表示
如图:
前序遍历
遍历结果为:
ABDH#K###E##CFI###G#J##

代码

#include<stdio.h>
#include<stdlib.h>

#define OK 1
#define ERROR 0
typedef char TElemType;

//二叉树的二叉链表的结点结构定义代码
typedef struct BTNode
{
	TElemType data;
	struct BTNode *lchild,*rchild;
}BTNode,*BTree;

void CreatBTree(BTree *T);//前序遍历生成二叉树
void PrtOrderTraverse(BTree T);//前序遍历二叉树
void InOrderTraverse(BTree T);//中序遍历二叉树
void PostOrderTraverse(BTree T);//后序遍历二叉树
int Deep(BTree T);//求树的深度
int NodeCount(BTree T);//求树的结点数
int LeafCount(BTree T);//统计二叉树中叶子结点的个数

int main()
{
	BTree T = NULL;
	printf("先序遍历生成二叉树\n");
	CreatBTree(&T);
	printf("前序遍历\n");
	PrtOrderTraverse(T);
	printf("\n");
	printf("中序遍历\n");
	InOrderTraverse(T);
	printf("\n");
	printf("后序遍历\n");
	PostOrderTraverse(T);
	printf("\n");
	int m = Deep(T);
	printf("树的深度:%d\n",m);
	int n = NodeCount(T);
	printf("树的结点数:%d\n",n);
	int y = LeafCount(T);
	printf("叶子结点数:%d\n",y);
}

//前序遍历生成二叉树
void CreatBTree(BTree *T)
{
	TElemType ch;
	scanf("%c",&ch);
	if(ch == '#')
		*T = NULL;
	else
	{
		*T = (BTree)malloc(sizeof(BTNode));
		if(!*T)
			printf("失败\n");
		(*T)->data = ch;
		CreatBTree(&(*T)->lchild);//左子树
		CreatBTree(&(*T)->rchild);//右子树
	}
}

//前序遍历二叉树
void PrtOrderTraverse(BTree T)
{
	if(T == NULL)
		return;
	printf("%c ",T->data);
	PrtOrderTraverse(T->lchild);
	PrtOrderTraverse(T->rchild);
}

//中序遍历二叉树
void InOrderTraverse(BTree T)
{
	if(T == NULL)
		return;
	InOrderTraverse(T->lchild);
	printf("%c ",T->data);
	InOrderTraverse(T->rchild);
}

//后序遍历二叉树
void PostOrderTraverse(BTree T)
{
	if(T == NULL)
		return;
	PostOrderTraverse(T->lchild);
	PostOrderTraverse(T->rchild);
	printf("%c ",T->data);
}

int Deep(BTree T)
{
	if(T == NULL)
		return 0;
	else
	{
		int m = Deep(T->lchild);
		int n = Deep(T->rchild);
		if(m>n)
			return (m+1);
		else
			return (n+1);
	}
}

int NodeCount(BTree T)
{
	if(T == NULL)
		return 0;
	else
		return NodeCount(T->lchild) + NodeCount(T->rchild) +1;
}

int LeafCount(BTree T)//统计二叉树中叶子结点的个数
{
    if(!T)
		return 0;
    if(!T->lchild &&!T->rchild)//如果二叉树左子树和右子树皆为空,说明该二叉树根节点为叶子节点,加1.
	{
        return 1;
    }
	else
	{
        return LeafCount(T->lchild)+LeafCount(T->rchild);
    }
}

运行结果

运行结果

后记

当然,树是一种很复杂的数据结构,还有比如二叉排序树(二叉查找树),平衡二叉树,红黑树等。我们会在查找那一章中进行解答。

今天的内容就是二叉树的基本操作及其内容,喜欢我的多多支持哦~

  • 54
    点赞
  • 221
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
平衡二叉树(AVL)是一种自平衡的二叉搜索,它的左子和右子的高度差不超过1。下面是一个简单的平衡二叉树代码实现C语言): ```c #include <stdio.h> #include <stdlib.h> // 定义平衡二叉树节点结构 typedef struct AVLNode { int data; // 节点数据 int height; // 节点高度 struct AVLNode* left; // 左子指针 struct AVLNode* right; // 右子指针 } AVLNode; // 获取节点的高度 int getHeight(AVLNode* node) { if (node == NULL) { return 0; } return node->height; } // 计算节点的平衡因子 int getBalanceFactor(AVLNode* node) { if (node == NULL) { return 0; } return getHeight(node->left) - getHeight(node->right); } // 更新节点的高度 void updateHeight(AVLNode* node) { int leftHeight = getHeight(node->left); int rightHeight = getHeight(node->right); node->height = (leftHeight > rightHeight ? leftHeight : rightHeight) + 1; } // 左旋操作 AVLNode* leftRotate(AVLNode* node) { AVLNode* newRoot = node->right; node->right = newRoot->left; newRoot->left = node; updateHeight(node); updateHeight(newRoot); return newRoot; } // 右旋操作 AVLNode* rightRotate(AVLNode* node) { AVLNode* newRoot = node->left; node->left = newRoot->right; newRoot->right = node; updateHeight(node); updateHeight(newRoot); return newRoot; } // 插入节点 AVLNode* insertNode(AVLNode* root, int data) { if (root == NULL) { AVLNode* newNode = (AVLNode*)malloc(sizeof(AVLNode)); newNode->data = data; newNode->height = 1; newNode->left = NULL; newNode->right = NULL; return newNode; } if (data < root->data) { root->left = insertNode(root->left, data); } else if (data > root->data) { root->right = insertNode(root->right, data); } else { // 已存在相同节点,不进行插入 return root; } updateHeight(root); int balanceFactor = getBalanceFactor(root); // 左子高度大于右子 if (balanceFactor > 1) { if (data < root->left->data) { // 左左情况,进行右旋操作 return rightRotate(root); } else if (data > root->left->data) { // 左右情况,先对左子进行左旋操作,再对根节点进行右旋操作 root->left = leftRotate(root->left); return rightRotate(root); } } // 右子高度大于左子 if (balanceFactor < -1) { if (data > root->right->data) { // 右右情况,进行左旋操作 return leftRotate(root); } else if (data < root->right->data) { // 右左情况,先对右子进行右旋操作,再对根节点进行左旋操作 root->right = rightRotate(root->right); return leftRotate(root); } } return root; } // 中序遍历二叉树 void inorderTraversal(AVLNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } int main() { AVLNode* root = NULL; int data[] = {5, 3, 7, 2, 4, 6, 8}; int n = sizeof(data) / sizeof(data); for (int i = 0; i < n; i++) { root = insertNode(root, data[i]); } printf("中序遍历结果:"); inorderTraversal(root); printf("\n"); return 0; } ``` 这段代码实现了平衡二叉树的插入操作,并提供了一个简单的示例来演示插入操作后的中序遍历结果。你可以根据需要修改代码来适应其他操作,比如删除节点等。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值