目录
前言
构成
2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成,二叉树是有序树,基本构成如下所示。
特殊的二叉树
1. 满二叉树
说,如果一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
2.完全二叉树
的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
3.二叉树的性质
1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 个结点.
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 .
3. 对任何一棵二叉树, 如果度为0其叶结点个数为 , 度为2的分支结点个数为 ,则有 = +1
4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= . (ps: 是log以2为底,n+1为对数)
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:
1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
3. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
4.二叉树的存储结构
1. 顺序存储
二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
2. 链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。
二叉树的顺序结构及实现
1 二叉树的顺序结构
普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
2 堆的概念及结构
堆中某个节点的值总是不大于或不小于其父节点的值;堆总是一棵完全二叉树.完全二叉树的节点必须满足:如果任意节点都比其他孩子节点小,将其称为小堆。如果任意节点都比其他孩子节点大,将其称为大堆。
大根堆示意图
3 堆的实现
以27为根的左右子树都满足堆的特性,只有根节点不满足。所以只需要调整根节点即可。
最终构成的大堆为8 7 6 5 1 3 .建堆的时间复杂度为O(N)
4 堆的插入
5 堆的删除
6 堆的代码实现
typedef int DataType;
typedef int(*c)(int left, int right) ;
typedef struct Heap
{
DataType *Array;
int size;
int capacity;
c compare;
}Heap;
// 堆的构建
void HeapCreate(Heap* hp,DataType* a, int n);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, DataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
DataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);
void adjustup(int array[], int size, int parent);
int Less(int left,int right)
{
return left < right;
}
int greater(int left, int right)
{
return left > right;
}
void swap(int*a, int*b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//小堆调整
void adjustdown(Heap* hp,int parent)
{
int size = hp->size;
int *array = hp->Array;
int child = 2*parent + 1;
while (child<size)
{
if (child + 1<size&&hp->compare(array[child+1],array[child]))
{
child += 1;
}
if(hp->compare(array[child], array[parent]))
{
swap(&array[child], &array[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
return;
}
}
}
void adjustup(Heap* hp, int child)
{
int size = hp->size;
int *array = hp->Array;
int parent = (child - 1) / 2;
while (child)
{
if (hp->compare(array[child],array[parent]))
{
swap(&array[child], &array[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
return;
}
}
}
// 堆的构建
void HeapCreate(Heap* hp, DataType* a, int n,c compare)
{
//将数组传入堆
hp->Array = (DataType*)malloc(sizeof(DataType)*n);
hp->capacity = n;
memcpy(hp->Array, a, sizeof(DataType)*n);
hp->size = n;
hp->compare = compare;
for (int root = (n - 2)/2; root >=0;root--)
{
adjustdown(hp,root);
}
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
free(hp->Array);
hp->Array = NULL;
hp->capacity = 0;
hp->size = 0;
}
//扩容
void checkheapcapacity(Heap* hp)
{
if (hp->capacity==hp->size)
{
int newcapacity = 2 * hp->capacity;
DataType *ret = (DataType*)malloc(sizeof(DataType)*newcapacity);
memcpy(ret, hp->Array, sizeof(DataType)*hp->size);
free(hp->Array);
hp->Array = ret;
hp->capacity = newcapacity;
}
}
// 堆的插入
void HeapPush(Heap* hp, DataType x)
{
checkheapcapacity(hp);
hp->Array[hp->size] = x;
hp->size++;
adjustup(hp, hp->size - 1);
}
// 堆的删除
void HeapPop(Heap* hp)
{
if (HeapEmpty(hp))
{
return;
}
//将堆首与堆尾交换
swap(&hp->Array[0],&hp->Array[hp->size-1]);
hp->size--;
//调整
adjustdown(hp, 0);
}
// 取堆顶的数据
DataType HeapTop(Heap* hp)
{
return hp->Array[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{
return hp->size;
}
// 堆的判空
int HeapEmpty(Heap* hp)
{
return 0 == hp->size;
}