二叉树

- 树的概念

  • 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合

- 树的结构

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

- 树的表示

typedef int DataType;
struct Node
{
	struct Node* _FirstChild; // 第一个孩子结点
	struct Node* _NextBrother; // 指向其下一个兄弟结点
	DataType _data; // 结点中的数据
};

二叉树

- 二叉树的概念

  • 二叉树不存在度大于2的结点
  • 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

- 满二叉树

在这里插入图片描述

  • 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树
  • 也就是说,如果一个二叉树的层数为K,且结点总数是2^k-1,则它就是满二叉树

- 完全二叉树

在这里插入图片描述

  • 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的
  • 对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树
  • 满二叉树是一种特殊的完全二叉树

- 二叉树的性质

  • 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
  • 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h-1
  • 对任何一棵二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有 n0= n2+1
  • 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1)
  • 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:
    若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
    若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
    若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

  • 堆是一棵完全二叉树
  • 堆中某个节点的值总是不大于或不小于其父节点的值
    如果是任意节点都大于它的所有孩子,就是大堆
    如果是任意节点都小于它的所有孩子,就是小堆
    在这里插入图片描述

- 堆的定义

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _arr;
	int _size;
	int _capacity;
}Heap;

- 接口函数

// 堆的构建
void HeapCreate(Heap* hp, HPDataType* arr, int n);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
bool HeapEmpty(Heap* hp);

- 堆的构建

// 堆的构建
void HeapCreate(Heap* hp, HPDataType* arr, int n)
{
	assert(arr);
	hp->_arr = (HPDataType*)malloc(sizeof(HPDataType) * (n+1));
	hp->_size = 0;
	hp->_capacity = n;
	if (n)
	{
		for (int i = 0; i < n; i++)
		{
			HeapPush(hp, arr[i]);
		}
	}
}

- 堆的销毁

void HeapDestory(Heap* hp)
{
	free(hp->_arr);
	hp->_arr = NULL;
	hp->_capacity = hp->_size = 0;
}

- 堆的插入

  • 这里实现的是小堆插入
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child != 0)
	{
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && child < n && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	if (hp->_size == hp->_capacity)
	{
		hp->_arr = (HPDataType*)realloc(hp->_arr, sizeof(HPDataType) * hp->_capacity*2);
		hp->_capacity *= 2;
	}
	hp->_arr[hp->_size] = x;
	AdjustUp(hp->_arr, hp->_size);
	hp->_size++;
}

- 堆的删除

void HeapPop(Heap* hp)
{
	assert(hp);
	assert(hp->_size > 0);
	Swap(&hp->_arr[0], &hp->_arr[hp->_size-1]);
	hp->_size--;
	AdjustDown(hp->_arr, hp->_size, 0);
}

- 堆顶的数据

HPDataType HeapTop(Heap* hp)
{
	assert(hp);
	assert(hp->_size>0);
	return hp->_arr[0];
}

- 堆的数据个数

int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->_size;
}

- 堆的判空

bool HeapEmpty(Heap* hp)
{
	assert(hp);
	return hp->_size?0:1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值