数据结构——树

41 篇文章 0 订阅
17 篇文章 0 订阅

节点的分类:

  • 节点拥有的子树数称为:节点的度(degree),度为0的节点称为叶节点(leaf)或终端节点,度不为0的节点称为非终端节点或分支节点。
  • 树的度是树内各节点度的最大值。
  • 在树中没有孩子的节点称为叶子。

二叉树的性质

  • 每个节点最多有两个子树。
  • 第i层有2^(i-1)个节点,深度为k的二叉树最多有2 ^(k)-1.
  • 度为2的节点数比叶子数多1。例如下图2中的数量关系为:1号+2号+3号+4号 = 8号+9号+10号。
  • 满二叉树:每个节点的度为2。
  • 一棵二叉树有n个元素,n>0, 它有n-1条边。
  • 一棵二叉树的高度为h, h≥0, 它最少有h个元素,最多有2^n-1个元素。
  • 一棵二叉树有n个元素, n>0,它的高度最大为n,最小高度为[log2 (n+ 1)](向上取整)。
  • 设完全二叉树的一元素其编号为i, 1≤i≤n。有以下关系成立:
  • 1 .如果i=1, 则该元素为二叉树的根。若i>1, 则其父节点的编号为[i/2」。
  • 2 .如果2i>n, 则该元素无左孩子。否则,其左孩子的编号为2i。
  • 3 .如果2i+1>n, 则该元素无右孩子。否则,其右孩子的编号为2i+1。

在这里插入图片描述

  • 完全二叉树:第k-1层和满二叉树一样,最后一层的叶子节点尽量靠左。
  • 具有n个节点的完全二叉树的深度为:[log2(n)]+1。
    在这里插入图片描述
  • 如果对一棵有 n个结点的完全二叉树的结点按层序编号,对任一结点i (1<i≤n)
  • 1.如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点[i/2」。
  • 2.如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点
  • 3.如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。

遍历二叉树

先序遍历

  • 先遍历根节点,再遍历左子树,再遍历右子树。
    在这里插入图片描述
void show_tree(binary_tree*b1)
{
	if (b1 == nullptr)
	{
		printf("本分支结束!!!\n\n");
		return;
	}
	printf("root_data = %d\n\n",*(int*)b1->user_data);
	show_tree(b1->left);
	show_tree(b1->right);
}

中序遍历

  • 先遍历左子树,再遍历根,再遍历右子树。
    在这里插入图片描述
void show_tree(binary_tree*b1)
{
	if (b1 == nullptr)
	{
		printf("本分支结束!!!\n\n");
		return;
	}
	show_tree(b1->left);
	printf("root_data = %d\n\n",*(int*)b1->user_data);
	show_tree(b1->right);
}

后序遍历

  • 先遍历左子树,再遍历右子树,再遍历根。
    在这里插入图片描述
void show_tree(binary_tree*b1)
{
	if (b1 == nullptr)
	{
		printf("本分支结束!!!\n\n");
		return;
	}
	show_tree(b1->left);
	show_tree(b1->right);
	printf("root_data = %d\n\n",*(int*)b1->user_data);
}

三种遍历方式总结

  • 如果去掉printf,从递归角度看,这三种算法是完全相同的,即访问路径相同。
    在这里插入图片描述

例子:

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>

typedef struct Binary_tree
{
	void* user_data;//用户数据
	Binary_tree* left;//左分支
	Binary_tree* right;//右分支
}binary_tree;

//采用前序遍历法
void show_tree(binary_tree*b1)
{
	if (b1 == nullptr)
	{
		printf("本分支结束!!!\n\n");
		return;
	}
	printf("root_data = %d\n\n",*(int*)b1->user_data);
	show_tree(b1->left);
	show_tree(b1->right);
}
int main()
{
	binary_tree* b1 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b2 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b3 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b4 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b5 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b6 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b7 = (binary_tree*)malloc(sizeof(binary_tree));
	binary_tree* b8 = (binary_tree*)malloc(sizeof(binary_tree));

	int u1 = 1111;
	b1->user_data = (void*) &u1;
	int u2 = 2222;
	b2->user_data = (void*)&u2;
	int u3 = 3333;
	b3->user_data = (void*)&u3;
	int u4 = 4444;
	b4->user_data = (void*)&u4;
	int u5 = 5555;
	b5->user_data = (void*)&u5;
	int u6 = 6666;
	b6->user_data = (void*)&u6;
	int u7 = 7777;
	b7->user_data = (void*)&u7;
	int u8 = 8888;
	b8->user_data = (void*)&u8;

	b1->left = b2;
	b1->right = b3;
	b2->left = b4;
	b2->right = b5;
	b3->left = b6;
	b3->right = b7;
	b4->left = b8;
	b4->right = nullptr;
	b5->left = nullptr;
	b5->right = nullptr;
	b6->left = nullptr;
	b6->right = nullptr;
	b7->left = nullptr;
	b7->right = nullptr;
	b8->left = nullptr;
	b8->right = nullptr;

	show_tree(b1);
	return 0;
}

求树的深度

  • 取左子树和右子树高度的最大值
求二叉树的深度:
int deep(binary_tree*b1)
{
	int left = 0;
	int right = 0;
	int root = 0;

	if (b1 == nullptr)
	{
		return 0;
	}
	left = deep(b1->left);
	right = deep(b1->right);

	root = 1 + (left > right ? left : right);
	return root;
}


树的拷贝

binary_tree* copy_tree(binary_tree*b1)
{
	printf("开始拷贝树!\n\n");
	binary_tree*left = nullptr;
	binary_tree*right = nullptr;
	binary_tree*new_root = nullptr;
	if (b1 == nullptr)
	{
		printf("树为空,无法拷贝!\n");
		return nullptr;
	}

	if (b1->left != nullptr)
	{
		left = copy_tree(b1->left);
	}
	else
	{
		left = nullptr;
	}

	if (b1->right != nullptr)
	{
		right = copy_tree(b1->right);
	}
	else
	{
		right = nullptr;
	}

	new_root = (binary_tree*)malloc(sizeof(binary_tree));
	if (new_root == nullptr)
	{
		printf("空间开辟错误!\n");
		return nullptr;
	}
	new_root->left = left;
	new_root->right = right;
	new_root->user_data = b1->user_data;
	return new_root;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值