树的存储结构主要由双亲表示法和孩子表示法,以及它们的各种改造版本。
由于计算机内存是线性的,而线性关系不能直接表示树的存储结构,因此我们需要设计一种能够在线性环境下表示树的数据结构的存储方式。可以存储树的数据结构很多,每种结构有自己的特点和适用的场景,根据实际需要来使用。
双亲表示法:
双亲表示法是指在每个节点中表示它的父节点的位置。整个树的节点作为一个数组或链表存放。
/*双亲表示法*/ typedef struct { type data; int parent; } node; typedef struct { node nodes[MAXNUM]; int n; int r; } tree;
孩子表示法:
孩子表示法是指给每个节点加上孩子的信息。如果树的度确定,比如二叉树,那么可以直接在每个节点中存储每个孩子的指针,很简单有效,不多说了。但是对于度不确定或者很大的情况下,这样的存储方式是非常浪费空间的。因此还有另一种表示方法,节点存放于线性表中,每个节点的全部孩子节点的信息组成一个链表,该节点的指针指向这个链表,链表以nil表示结束。这样的存储结构尽管也有一小部分nil指针,但减少了很多,而且比较灵活。
/*孩子表示法 孩子链表形式*/ typedef struct child { int child; struct child* next; } child; typedef struct { type data; child* child; } node; typedef struct { node nodes[MAXNUM]; int n; int r; } tree;
孩子兄弟表示法:
孩子兄弟表示法实际上是用一个二叉树来表示树的结构。每个节点的一个指针指向第一个孩子,第二个指针指向右边的第一个兄弟节点。这种存储方式节省空间,操作方便,但树的原本的层次结构被破坏了。
孩子双亲表示法:
孩子双亲表示法是对上面两种方法的综合。双亲表示法不便从上往下查找,孩子表示法不便从下网上查找,那么孩子双亲表示法就把两种信息都放到一起,这样可以有更好的访问速度,但是也会占用更多空间。
二叉树作为一种特殊的树,可以有其他的存储方式。
顺序存储:假如是完全二叉树或者接近完全二叉树,那么可以按照层序关系直接顺序排列,因为根据公式可以知道每个元素应该在哪里。缺点是仅适用于接近满的二叉树,否则很浪费空间。
二叉链表:完全按照树的结构,用指针连起来。最直观的方式,也很省空间。
三叉链表:比二叉链表多了一个向上的指针。这个看具体情况吧。