【数据结构】4. 树与二叉树(3)
依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映出结点之间的逻辑关系,这样既能最大可能地节省存储空间,又可以利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。 但对于一般的二叉树,为了让数组下标能反映二叉树中结点之间的逻辑关系,只能添加一些并不存在的空结点让其每个结点与完全二叉树上的结点相对照,再存储到一维数组的相应分量中。
(2)链式存储结构由于顺序存储对空间利用率较低,因此,一般二叉树都采用链式存储结构。 图 4-6 所示为常用的二叉链表的存储结构。 二叉树的链式存储结构描述如下: typedef struct BiTNode { ElemType data; //数据域 struct BiTNode *lchild,*rchild; //左、 右孩子指针 } BiTNode,*BiTree; 使用不同的存储结构,实现二叉树操作的算法也会不同,因此,要根据实际应用的场合(二叉树的形态和需要进行的运算)来选择合适的存储结构。 4.3 二叉树的遍历和线索二叉树4.3.1 二叉树的遍历所谓二叉树的遍历,是指按某条搜索路径访问树中的每个结点,使得每个结点均被访问一次,而且仅被访问一次。 (1)先序遍历(PreOrder)先序遍历的操作过程为:
对应的递归算法如下: void PreOrder(BiTree T) { if(T!=NULL) { visit(T); //访问根结点 PreOrder(T->lchild); //递归遍历左子树 PreOrder(T->rchild); //递归遍历右子树 } } 对于图 4-4 所示的二叉树,先序遍历所得到的结点序列为:1 2 4 6 3 5。 (2)中序遍历(InOrder)中序遍历的操作过程为:
对应的递归算法如下: void InOrder(BiTree T) { if(T!=NULL) { InOrder(T->lchild); visit(T); InOrder(T->rchild); } } 对于图 4-4 所示的二叉树,中序遍历所得到的结点序列为:2 6 4 1 3 5。 (3)后序遍历(PostOrder)后序遍历的操作过程为:
对应的递归算法如下: void PostOrder(BiTree T) { if(T!=NULL) { PostOrder(T->lchild); //递归遇历左子树 PostOrder(T->rchild); //递归遍历右子树 visit(T); //访问根结点 } } 对于图 4-4 所示的二叉树,后序遍历所得到的结点序列为:6 4 2 5 3 1。 三种遍历算法中递归遍历左、右子树的顺序都是固定的,只是访问根结点的顺序不同。
|