现在的位置: 首页 > 综合 > 正文

二叉树的线索化

2013年06月28日 ⁄ 综合 ⁄ 共 1479字 ⁄ 字号 评论关闭

 【版权声明:转载请保留出处:blog.csdn.net/algorithm_only。邮箱:liuy0711@foxmail.com

前面说到二叉树的二叉链表表示实现,当以二叉树作为存储结构时,只能找到节点的左右孩子信息,不能直接得到结点在任一序列中的前驱和后继信息,只有在遍历过程中才能得到这种信息。我们知道,在n个结点的二叉链表栈必定存在n+1个空链域,因此,可以利用这些空链域来存放这些结点信息。所以作如下规定:若结点右左子树,则其lchild域指向其左孩子,否则令lchild域指向其前驱;若结点有右子树,其rchild域指向其右孩子,否则指向其后继。以这种结构构成的二叉链表叫做线索链表。

  • 线索链表的存储结构
typedef enum {link, thread}	pointer_tag;
typedef struct tnode {
	elemtype		data;
	struct tnode		*lchild, *rchild;
	pointer_tag		ltag, rtag;
}bithrnode, *bithrtree;
  • 二叉树的线索化(中序线索化)
int inorder_threading(bithrtree *thrt, bithrtree bt)
{
	*thrt = (bithrtree) malloc (sizeof(bithrnode));
	if (!*thrt)
		exit(OVERFLOW);
                                                   /* 将头结点线索化 */
	(*thrt)->ltag = link;
	(*thrt)->rtag = thread;
	(*thrt)->rchild = (*thrt);

	if (!bt)                                     /* 若二叉树为空,则将lchild指向自己 */
		(*thrt)->lchild = (*thrt);
	else {
		(*thrt)->lchild = bt;                   /* 头结点左指针指向根结点 */
		pre = (*thrt);
		in_threading(bt);                       /* 中序遍历进行中序线索化 */
		pre->rchild = *thrt;
		pre->rtag = thread;
		(*thrt)->rchild = pre;
	}
	return OK;
}
void in_threading(bithrtree t)
{
	if (t) {
		in_threading(t->lchild);

		if (!t->lchild) {
			t->ltag = thread;
			t->lchild = pre;
		}
		if (!pre->rchild) {
			pre->rtag = thread;
			pre->rchild = t;
		}
		pre = t;
		in_threading(t->rchild);
	}
}

线索化的实质是将二叉链表中的空指针改为指向前驱或后继的线索,前驱和后继的信息是在遍历过程中才能得到,故线索化的过程即为在遍历过程中修改空指针的过程。

  • 线索二叉树的遍历(中序)
int inorder_traverse_thr(bithrtree thrt, int (*visit)(bithrtree t))
{
	bithrtree		p;

	p = thrt->lchild;
	while (p != thrt) {
		while (p->ltag == link)
			p = p->lchild;
		visit(p);

		while (p->rtag == thread && p->rchild != thrt) {
			p = p->rchild;
			visit(p);
		}
		p = p->rchild;
	}
	return OK;
}
  • 总结
在中序线索二叉树上遍历二叉树,虽然时间复杂度任然为O(n),但相比上节所讲遍历算法,不需要栈和队列等辅助空间。
  • 算法实现源码
【上篇】
【下篇】

抱歉!评论已关闭.