树
- 树的概念
- 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合
- 树的结构
- 节点的度:一个节点含有的子树的个数称为该节点的度
- 叶节点或终端节点:度为0的节点称为叶节点
- 非终端节点或分支节点:度不为0的节点
- 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
- 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点
- 兄弟节点:具有相同父节点的节点互称为兄弟节点
- 树的度:一棵树中,最大的节点的度称为树的度
- 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
- 树的高度或深度:树中节点的最大层次
- 堂兄弟节点:双亲在同一层的节点互为堂兄弟
- 节点的祖先:从根到该节点所经分支上的所有节点
- 子孙:以某节点为根的子树中任一节点都称为该节点的子孙
- 森林:由m(m>0)棵互不相交的树的集合称为森林
- 树的表示
typedef int DataType;
struct Node
{
struct Node* _FirstChild;
struct Node* _NextBrother;
DataType _data;
};
二叉树
- 二叉树的概念
- 二叉树不存在度大于2的结点
- 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
- 满二叉树
![在这里插入图片描述](https://img-blog.csdnimg.cn/78afacbc1c9d47b8b29bb14037da9cff.png)
- 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树
- 也就是说,如果一个二叉树的层数为K,且结点总数是2^k-1,则它就是满二叉树
- 完全二叉树
![在这里插入图片描述](https://img-blog.csdnimg.cn/8b484582a3404f509a9d472e1679f370.png)
- 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的
- 对于深度为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否则无右孩子
堆
- 堆是一棵完全二叉树
- 堆中某个节点的值总是不大于或不小于其父节点的值
如果是任意节点都大于它的所有孩子,就是大堆
如果是任意节点都小于它的所有孩子,就是小堆
![在这里插入图片描述](https://img-blog.csdnimg.cn/2f34d7d4d2894d10ad0008200f1a8d81.png)
- 堆的定义
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;
}