线索化二叉树指的是将二叉树中的结点进行逻辑意义上的“重排列”,使其可以线性的方式访问
每一个结点。二叉树线索化之后每个结点都有一个线性下标,通过这个下标可以快速访问结点,而不
需要遍历二叉树。线索化二叉树有两种方法:
1、利用结点中的空指针域,使其指向后继结点。
算法思想:
初始化位置指针:p = NULL
前序遍历二叉树:若p不为空,将p->left指向当前结点,并将p置为NULL;若当前结点的左子树为空时,将p指向当前结点
2、利用线性表保存二叉树的遍历顺序
算法思想:
初始化顺序表s1;
前序遍历二叉树:遍历过程中将当前结点插入顺序表s1(借助之前实现的顺序表)
-
/**实现代码ThreadBTree.c**/
-
#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);
-
-
while( current != NULL )
-
{
-
printf("%c,", ((struct Node*)current)->v);
-
-
current = current->left;
-
}
-
-
printf("\n");
-
-
BTree_Destroy(tree);
-
printf("please enter to continue...");
-
getchar();
-
return 0;
-
}
小结:
1>利用结点空指针线索化的方法会破坏树的结构;利用结点空指针线索化二叉树之后不能够再恢复,
这两个问题可以在树结点中加入一个线索化指针而得以解决,然而线索化指针的加入又会浪费内存空
间,不够灵活;
2>链表线索化方法不会破坏树的结构不需要时线索化时销毁链表即可;链表线索化方法可以很容易的
以任何一种遍历顺序对二叉树进行线索化。
阅读(2367) | 评论(0) | 转发(0) |