线索二叉树的线索化的实现以及遍历的实现

10 篇文章 0 订阅
6 篇文章 0 订阅

      线索二叉树:(threaded binary tree):n个结点的二叉链表中含有n+1(2n-(n-1)=n+1)个空指针域。利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针

【注】已知二叉树的节点个数n,那么边的个数n-1。

现在给出树节点的定义:

class TreeNode
{
public:
    TreeNode(int x) { val = x; }
    int val;
    TreeNode *left;
    int lflag;
    TreeNode *right;
    int rflag;
};

ltag=0 时lchild指向左子女;

ltag=1 时lchild指向前驱;

rtag=0 时rchild指向右子女;

rtag=1 时rchild指向后继;

 

1.第一步线索化:

设置pre为了将它的空指针域指向p,设置其后继结点

在将p的空左节点 前驱节点指向pre,将所有的空节点均填满

void InThread(TreeNode *&root, TreeNode*&pre)//pre为p的前驱节点  p为pre的后继结点
{
    if (root)
    {
        InThread(root->left, pre);//线索化左子树
        if (!root->left)//左节点是空
        {
            root->lflag = 1;//指向前驱节点
            root->left = pre;
        }
        if (pre && !pre->right)//pre后是空
        {
            pre->rflag = 1;
            pre->right = root;//指向后继结点
        }
        pre = root;
        InThread(root->right, pre);//线索化右子树
    }
}

2.线索遍历:
 

TreeNode* FirstNode( TreeNode *t)

{
   if(!t)return(NULL);
   while(t->lflag==0) t=t->left;//找到最左边的节点

}

TReeNode*NextNode(TreeNode *t)

{
if(rflag==1) return(t->right);
else return(FirstNode(t->right));//返回右节点的最左下节点
}

给出代码:

#include "stdafx.h"
#include <iostream>
#include <queue>
using namespace std;
class TreeNode
{
public:
	TreeNode(int x) { val = x; }   //constructor
	int val;
	TreeNode *left;
	int lflag;
	TreeNode *right;
	int rflag;
};
void CreateTree(TreeNode*&t) //先序遍历
{
	cout << "input the x:" << endl;
	int x;
	cin >> x;
	if (x != 0)
	{
		t = (TreeNode *)new TreeNode(x);
		CreateTree(t->left);
		CreateTree(t->right);
	}
	else
		t = NULL;
}
//中序遍历
void Inorder(TreeNode*p)
{
	if (p)
	{
		Inorder(p->left);
		cout << p->val << endl;
		Inorder(p->right);
	}
}
//层次遍历
void LevelOrder(TreeNode *root)
{
	queue<TreeNode* > q;
	q.push(root);
	while (!q.empty())
	{
		TreeNode *temp = q.front();
		q.pop(); //出队
		cout << temp->val << "  ";
		if (temp->left)
			q.push(temp->left);
		if (temp->right)
			q.push(temp->right);
	}
}
//中序线索化--比较常见
void InThread(TreeNode *&root, TreeNode*&pre)//pre为p的前驱节点  p为pre的后继结点
{
	if (root)
	{
		InThread(root->left, pre);//线索化左子树
		if (!root->left)//左节点是空
		{
			root->lflag = 1;//指向前驱节点
			root->left = pre;
		}
		if (pre && !pre->right)//pre后是空
		{
			pre->rflag = 1;
			pre->right = root;//指向后继结点
		}
		pre = root;
		InThread(root->right, pre);//线索化右子树
	}
}
void CreateThreaded(TreeNode*& root)
{
	if (root)
	{
		TreeNode*pre = NULL;
		InThread(root, pre);//线索化
							//处理最后的pre
		pre->right = NULL;
		pre->rflag = 0;
	}
}
TreeNode* FirstNode( TreeNode*t)
{
	if (!t) return(NULL);
	while (t->lflag == 0)//找到最左下节点
		t = t->left;
	return(t);
}
TreeNode* NextNode(TreeNode*t)
{
	if (t->rflag == 1)//直接后继结点
		return(t->right);
	else//右子树并不是直接的next节点  就找到其最左端节点
		return(FirstNode(t->right));
}
int main()
{
	//先序初始化  建树
	TreeNode *root;
	 CreateTree(root);
	if (root == NULL) cout << "root==NULL" << endl;
	else cout << root->val << endl;
	cout << "Inorder" << endl;
	Inorder(root);
	cout << "LevelOrder" << endl;
	LevelOrder(root);
	cout << "start to threading:" << endl;
	CreateThreaded(root);
	//开始线索遍历
	for (TreeNode*p = FirstNode(root); p != NULL; p = NextNode(p))
		cout << p->val << endl;
	system("pause");
}

 【注】这里用中序遍历来验证建树是否正确,假设n,m分别是一棵树上的2个节点,那么Inorder的过程中,n在m之前的充要条件是n在m的左边。其中这个在南开大学的硕士入学考试中出现过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值