在前几天写的树,我们已经了解到树的存储,⼆叉树也是树,也是可以⽤vector数组或者链式前向星来存储。仅需在存储的过程中标记谁是左孩⼦,谁是右孩⼦即可。
- ⽐如⽤ vector 数组存储时,可以先尾插左孩⼦,再尾插右孩⼦;
- ⽤链式前向星存储时,可以先头插左孩⼦,再头插右孩⼦。只不过这样存储下来,遍历孩⼦的时候先遇到的是右孩⼦,这点需要注意。
但是,由于⼆叉树结构的特殊性,我们除了⽤上述两种⽅式来存储,还可以⽤符合⼆叉树结构特性的⽅式:分别是顺序存储和链式存储。
顺序存储
顺序存储就是用数组来存储二叉树。根据满二叉树的性质,我们了解到:按照层序遍历将二叉树从根节点开始从1开始编号,父子之间的编号是可以计算出来的。那么在存储完全二叉树的时候,就可以根据编号,依次将结点放在数组对应的位置上即可。然后通过计算,就可以找到父子。
完全二叉树的性质,使我们可以在存储结构中快速的找到 i 的父子关系,,对于第i号结点:
- 如果左孩子存在,左孩子编号:ix2;
- 如果右孩子存在,右孩子编号:ix2+1;
- 如果父结点存在,父结点编号:i/2
那如果不是满二叉树或者完全二叉树呢?
也是可以顺序存储,只不过要先将缺失的部分补齐,然后再去编号。如果直接编号,就不能通过计算,找到左右孩子以及父亲的位置(5的父亲是5/2=2,找到的B显然不是G的父亲)。
- 应该已经能看到缺陷了,那就是空间利用率不高(在这个逻辑结构里只有5个结点,但是在存储结构里要创建大小为10的数组才能把它存下来)
如果是下面这种极端情况的二叉树,顺序存储就特别浪费空间
单单这4个结点,要创建1个大小为15的数组,如果有n 个结点,那就需要2”-1个存储单元这显然会造成巨大的浪费。所以顺序存储只适用于存储满二叉树或者完全二叉树或者接近满的二叉树
这里的顺序存储我们只要知道有这个东西以及如何用就可以了,以后我们学习到堆和线段树的时候在继续讨论