完全二叉树:是除最后一层外,其余层节点全满,且最后一层节点都靠左排列的二叉树,它的结构特性让它可以用连续数组高效存储(无需指针 / 引用),这也是堆(优先队列)的底层实现原理。
一、核心规则
我们约定:数组下标从 0 开始(最常用),对完全二叉树任意一个节点 i:
父节点下标:(i - 1) /2 (整数除法)
左孩子下标:2 * i + 1
右孩子下标:2 * i + 2
二、示例演示说明
- 完全二叉树结构
0 (根节点)
/ \
1 2
/ \ /
3 4 5 - 对应数组
0, 1, 2, 3, 4, 5
- 公式验证
节点 1(下标 1):父 =(1-1)/2=0,左 = 3,右 = 4
节点 2(下标 2):父 =(2-1)/2=0,左 = 5,右 = 6(正常如果有右孩子的话是6,本示例无右孩子)
节点 5(下标 5):父 =(5-1)/2=2
三、C语言实现方法
c
#include <stdio.h>
// 求父节点下标
int getParent(int i)
{
if(i == 0)
return -1; // 根节点无父节点
return (i - 1) / 2;
}
// 求左孩子下标
int getLeft(int i)
{
return 2 * i + 1;
}
// 求右孩子下标
int getRight(int i)
{
return 2 * i + 2;
}
int main()
{
// 完全二叉树数组:0 1 2 3 4 5
int tree[] = {0, 1, 2, 3, 4, 5};
int n = sizeof(tree) / sizeof(tree[0]);
printf("完全二叉树数组元素:");
for(int i = 0; i < n; i++)
{
printf("%d ", tree[i]);
}
printf("\n\n");
// 遍历每个节点,打印父子关系
for(int i = 0; i < n; i++)
{
printf("下标%d 节点值 = %d\n", i, tree[i]);
int p = getParent(i);
if(p == -1)
printf(" -> 根节点,无父节点\n");
else
printf(" -> 父节点下标:%d,值:%d\n", p, tree[p]);
int L = getLeft(i);
if(L < n)
printf(" -> 左孩子下标:%d,值:%d\n", L, tree[L]);
else
printf(" -> 无左孩子\n");
int R = getRight(i);
if(R < n)
printf(" -> 右孩子下标:%d,值:%d\n", R, tree[R]);
else
printf(" -> 无右孩子\n");
printf("------------------------\n");
}
return 0;
}
运行输出:
下标0 节点值 = 0
-> 根节点,无父节点
-> 左孩子下标:1,值:1
-> 右孩子下标:2,值:2
下标3 节点值 = 3
-> 父节点下标:1,值:1
-> 无左孩子
-> 无右孩子
下标5 节点值 = 5
-> 父节点下标:2,值:2
-> 无左孩子
-> 无右孩子
四、数组表示法的特点
优点
内存高效:连续数组存储,无额外指针开销
访问极快:通过公式直接计算父子节点,O (1) 时间复杂度
结构天然:完全二叉树不会产生数组空洞,空间利用率 100%
缺点
仅适用于完全二叉树:普通二叉树用数组会产生大量空位,浪费空间