顺序存储
完全二叉树的顺序存储
可以让第一个位置空缺,保证数组下标和接地那编号一致
初始化时所有结点标记为空
#define ElemType int
//顺序存储结构
#define MaxSize 100
struct TreeNode{
ElemType value;//结点中的数据元素
bool isEmpty;//结点是否为空
};
/*定义一个长度为MaxSize的数组t,按照从上至下,
从左至右的顺序依次存储 完全二叉树 中的各个结点*/
TreeNode t[MaxSize];
for(int i=0;i<MaxSize;i++){
t[i].isEmpty=true;//初始化是所以结点均标记为空
}
因为i的左孩子为2i , 则若2i>n时说明左孩子不存在,左孩子都没有,则必定没有右孩子,所以只要满足2i>n 即 i>
⌊
n
/
2
⌋
\lfloor n/2 \rfloor
⌊n/2⌋ 则 i 结点必为叶子结点
一般二叉树的顺序存储
对于一般的二叉树,为了让数组下标能反映二叉树中结点之间的逻辑关系,智能添加一些并不存在的空节点,让其每个结点与完全二叉树上的结点相对照,在存储到一维数组的相应分量中。即保持一般二叉树中节点的编号和完全二叉树中对应结点编号相同。
这样做的原因是:
编号为i的结点:
i 的左孩子:2i
i 的右孩子:2i+1 这时只能通过结点2i+1的isEmpty来判断 i 是否有右孩子
i 的父节点:
⌊
i
/
2
⌋
\lfloor i/2 \rfloor
⌊i/2⌋
结点的编号不仅反映了存储位置,也隐含了结点之间的逻辑关系。
最坏情况:高度为h且只有h个接地那的单支树(所有结点只有右孩子),也至少需要
2
h
2^h
2h-1个存储单元
所以:二叉树的顺序存储结构,只适合存储完全二叉树
链式存储
二叉链表(lchild, rchild)(常考)
找到指定结点p的左右孩子较容易
如何找到指定结点p的父节点?只能从根节点开始遍历寻找.
可以用三叉链表来方便地找到父节点
//二叉树的链式存储结构
#define ElemType int
typedef struct BiTNode{
ElemType data;//数据域
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode, *BiTree;
在含有n个结点的二叉链表中,有2n个指针域,(n-1)个用来存放指针,则有n+1个空链域,后面会利用这些空链域来组成另一种链表结构----线索链表
三叉链表(lchild, rchild, parent)
多加了一个指向父节点的指针,方便找其父节点
//二叉树的结点 链式存储 三叉链表
typedef struct BiTNode{
ElemType data;//数据域
struct BiTNode *lchild,*rchild;//左右孩子指针
struct BiTNode *parent;//父节点指针
}BiTNode,*BiTree;