目录
树是一种非线性的数据结构,它是由N个有限节点组成的具有层次关系的集合。同时树形结构中不能具有交集,否则就不是树形结构。
像这样下图的上三个都不能被称作树;

节点的度:一个节点含有的子树的个数称为该节点的度;
叶节点或终端节点:度为0的节点称为叶节点;
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
兄弟节点:具有相同父节点的节点互称为兄弟节点;
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次;
森林:由M(M > 0)棵互不相交的树的集合称为森林;
一棵二叉树是结点的一个有限集合,该集合:
1. 为空;
2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成;

由图可以看出来:二叉树节点的度都不能大于 2;二叉树有左子树右子树之分,是有序树;
还有两个特殊的二叉树:
满二叉树:根据名字很容易理解,就是每个枝桠上都用两个分桠(最后一层除外)它的总节点数为 2^k - 1 K为层数。
完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于层数为K的,有n个结点的二叉树,当且仅当其每一个结点都与层数为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树,它的总结点数的范围为[2^(k-1) - 1 , 2^k - 1]。
堆:有一组集合 的元素按照完全二叉树的顺序储存方式存储到一个一维数组中,根据存储的顺序不同分为小堆与大堆。
堆 形象逻辑上的 结构是树形的 如下图的(a) 抽象的实际的储存结构是 以顺序表的形式 来存储的。
下标的表示方法 从上到下 从左到右依次变大;

任何一个孩子与双亲节点都有下面这种关系:

- typedef struct Heap
- {
- int* a;
- int capacity;
- int size;
- }Heap;
先来看 Push 函数; 我们的堆 当进行插入的时候还要必须保持堆的结构;当我们插入的数 并不符合 这个 堆的结构的时候 我们要思考如何将 新插入的数与原堆融为一体?我们需要将 不符合结构的这个数与它的双亲节点进行互换 就行了; 用代码来实现就是这样:
我们将向上调整的方法进行封装成函数,有了利于实现 低耦合 高内聚 的特点;
- swap(int* x, int* y)
- {
- assert(x && y);
- int tmp = *x;
- *x = *y;
- *y = tmp;
- }
- void Adjustup(int* a, int size, int x)
- {
- assert(a);
- int child = size - 1;
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- if (a[child] < a[parent])
- {
- swap(&a[child], &a[parent]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
- void HeapPush(Heap* SL, int x)
- {
- assert(SL);
- if (SL->capacity == SL->size)
- {
- int newcapacity = SL->capacity == 0 ? 4 : (SL->capacity * 2);
- int* newnode = (int*)realloc(SL->a, sizeof(int) * newcapacity);
- if (newnode == NULL)
- {
- perror("realloc fail");
- exit(-1);
- }
- SL->capacity = newcapacity;
- SL->a = newnode;
- }
- SL->a[SL->size] = x;
- SL->size++;
-
- Adjustup(SL->a, SL->size, x);
-
- }
- void HeapPrintf(Heap* SL)
- {
- assert(SL);
- int i = 0;
- for (i = 0; i < SL->size; i++)
- {
- printf("%d ", SL->a[i]);
- }
- printf("\n");
- }
同样的 我们对堆 进行删除的时候 同样会破坏对的结构;有一种解决思路是这样的:
将 根节点 与 尾节点 进行互换 把Size减减;再重新向下调整更新一下堆, 把新的头调整到适当的位置。具体做法 我们来看代码的实现:
- void AdjustDown(int* a,int size)
- {
- assert(a);
- int parent = 0;
- int minchild = parent * 2 + 1;
-
- while (minchild < size - 1)
- {
- if (a[minchild + 1] < a[minchild])
- {
- minchild++;
- }
- if (a[parent] > a[minchild])
- {
- swap(&a[parent], &a[minchild]);
- parent = minchild;
- minchild = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
-
- void HeapPop(Heap* SL)
- {
- assert(SL);
- if (SL->size == 0)
- {
- return;
- }
- swap(&SL->a[0], &SL->a[(SL->size) - 1]);
- SL->size--;
- AdjustDown(SL->a,SL->size);
- }
- bool HeapEmpty(Heap* SL)
- {
- assert(SL);
- return SL->size == 0;
- }
-
- int HeapTop(Heap* SL)
- {
- assert(SL);
- return SL->a[0];
- }
-
- void HeapDestory(Heap* SL)
- {
- assert(SL);
- free(SL->a);
- SL->a = NULL;
- SL->capacity = SL->size = 0;
- }
- #include"标头.h"
-
- test()
- {
- Heap SL;
- HeapInit(&SL);
- HeapPush(&SL, 6);
- HeapPush(&SL, 7);
- HeapPush(&SL, 10);
- HeapPush(&SL, 23);
- HeapPush(&SL, 2);
- HeapPush(&SL, 35);
- HeapPrintf(&SL);
- HeapPop(&SL);
- HeapPrintf(&SL);
- int a = HeapEmpty(&SL);
- printf("%d\n", a);
- int b = HeapTop(&SL);
- printf("%d\n", b);
- HeapDestory(&SL);
- }
-
- int main()
- {
- test();
- return 0;
- }
运行结果:

