能不能像链表那样方便的快速遍历二叉树呢?
线索化二叉树
-
线索化二叉树指的是将二叉树中的结点进行逻辑意义上的"重排列”,使其可以线性的方式访问每一个结点
-
二叉树线索化之后每个结点都有一个线性下标,通过这个下标可以快速访问结点,而不需要遍历二叉树
线索化方法1
利用结点中的空指针域,使其指向后继结点
线索化方法2(推荐)
线索化二叉树
#include <stdio.h>
#include <stdlib.h>
#include "BTree.h"
#include "SeqList.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Node
{
BTreeNode header;
char v;
};
void printf_data(BTreeNode* node)
{
if( node != NULL )
{
printf("%c", ((struct Node*)node)->v);
}
}
void thread_via_left(BTreeNode* root, BTreeNode** pp)//传递局部变量本身到函数里,而不是传值。用二级指针
{
if( (root != NULL) && (pp != NULL) )
{
if( *pp != NULL )
{
(*pp)->left = root;//二级指针,通过*打开就是变量本身
*pp = NULL;
}
if( root->left == NULL )
{
*pp = root;
}
thread_via_left(root->left, pp);
thread_via_left(root->right, pp);
}
}
void thread_via_list(BTreeNode* root, SeqList* list)
{
if( (root != NULL) && (list != NULL) )
{
SeqList_Insert(list, (SeqListNode*)root, SeqList_Length(list));
thread_via_list(root->left, list);//前序遍历
thread_via_list(root->right, list);//前序遍历
}
}
int main(int argc, char *argv[])
{
BTree* tree = BTree_Create();
BTreeNode* current = NULL;
BTreeNode* p = NULL;
SeqList* list = NULL;//声明链表指针
int i = 0;
struct Node n1 = {{NULL, NULL}, 'A'};
struct Node n2 = {{NULL, NULL}, 'B'};
struct Node n3 = {{NULL, NULL}, 'C'};
struct Node n4 = {{NULL, NULL}, 'D'};
struct Node n5 = {{NULL, NULL}, 'E'};
struct Node n6 = {{NULL, NULL}, 'F'};
BTree_Insert(tree, (BTreeNode*)&n1, 0, 0, 0);
BTree_Insert(tree, (BTreeNode*)&n2, 0x00, 1, 0);
BTree_Insert(tree, (BTreeNode*)&n3, 0x01, 1, 0);
BTree_Insert(tree, (BTreeNode*)&n4, 0x00, 2, 0);
BTree_Insert(tree, (BTreeNode*)&n5, 0x02, 2, 0);
BTree_Insert(tree, (BTreeNode*)&n6, 0x02, 3, 0);
printf("Full Tree: \n");
BTree_Display(tree, printf_data, 4, '-');
printf("Thread via List:\n");
list = SeqList_Create(BTree_Count(tree));//顺序表,指定大小,大小是这棵树里面结点的数量
thread_via_list(BTree_Root(tree), list);//调用线索化函数
for(i=0; i<SeqList_Length(list); i++)
{
printf("%c, ", ((struct Node*)SeqList_Get(list, i))->v);
}
printf("\n");
printf("Thread via Left:\n");
current = BTree_Root(tree);
thread_via_left(current, &p);//&p,把变量本身传进去
while( current != NULL )
{
printf("%c, ", ((struct Node*)current)->v);
current = current->left;
}
printf("\n");
BTree_Destroy(tree);
return 0;
}
小结
-
利用结点空指针线索化的方法会破坏树的结构
-
利用结点空指针线索化二叉树之后不能够再恢复
-
这两个问题可以在树结点中加入一个线索化指针而得以解决
-
然而线索化指针的加入又会浪费内存空间,不够灵活
-
-
链表线索化方法不会破化树的结构,不需要时线索化时销毁链表即可
-
链表线索化方法可以很容易的以任何一种遍历顺序对二叉树进行线索化