clue binary tree

clue binary tree

1 Introduction

The clue binary tree is mainly for the convenience of determining the direct predecessor and direct successor of an element of the binary tree. It utilizes the empty chain field of the node on the basis of the chain binary tree, and is used to store the predecessor and successor information of the node. In order to distinguish whether the node chain field points to its left (right) child or to its predecessor (successor), the node structure of the original chained binary tree is improved:


Among them, when the lchild chain domain points to the left child, lTag= 0; when the lchild chain domain points to its predecessor, lTag= 1. rchild is similar.

A binary tree using this storage structure (actually a binary linked list) is a clue binary tree. The process of turning a chained binary tree into a threaded binary tree is threaded. That is, the empty chain field of the node in the chained binary tree is modified to point to the predecessor or successor of the node.

A binary tree as shown below:

When the binary tree is stored in the common first node structure, it has 8 empty chain fields (the chain fields marked in gray in the above figure). Generally, a binary tree with n nodes will have n+1 empty chain fields. When the binary tree is stored in the second node structure, it looks like this:

When threading, in order to imitate the storage structure of the linear table, a head node is added to the binary tree. And the lchild chain field of the head node points to the root node of the binary tree, and its rchild chain field points to the last node visited during traversal. At the same time, the lchild chain field of the first element and the rchild chain field of the last element accessed when the binary tree is traversed point to the head node. After the clue is made, the empty chain field in the binary tree is pointed to the predecessor or successor of its traversal ( various traversal methods are different, and the predecessor and successor of the node are different ). The clues in the clue binary tree are shown in the following figure:

The above figure is the threading result of in-order traversal of the binary tree. By splitting the above figure according to the clues, you can get the clue list of the binary tree obtained by traversing the binary tree according to the inorder as shown in the figure below.

2. Code

When traversing a binary tree in in-order, the threading code is as follows:
Status inOrderThreading(binaryThrTree &thrT, binaryThrTree T){
	//thrT is the head node after threading, T is the binary tree to be threading
binaryThrTree pre;

	thrT = new binaryThrNode;//New head node
	if(!thrT) exit(-1);

	thrT->lTag = Link; //The left link domain of the head node is marked as a pointer
	thrT->rTag = Thread; //The right chain domain of the head node is marked as a thread
	thrT->rchild = thrT; //The right chain field of the head node is marked as a clue pointing to the last node visited by in-order traversal (initialized to point to the node itself first)

	if(!T)thrT->lchild = thrT;//If the binary tree is empty, point the left chain domain of the head node to the head node
	else{
		thrT->lchild = T; //If the binary tree is not empty, point the left chain field of the head node to the root of the binary tree
		pre = thrT;//Record the node just visited

		InThreading(T ,pre);//Threaded binary tree

		pre->rchild = thrT;//After the threading is over, pre saves the last node visited after the in-order traversal, and then makes the right chain domain of the node point to the head node
		pre->rTag = Thread;//Identified as a thread
		thrT->rchild = pre;//Point the right chain field of the head node to the last visited node after the in-order traversal
	}
	return 1;
}

The core code of the threaded binary tree:

void InThreading(binaryThrTree p, binaryThrTree &pre){
	if(p){
		InThreading(p->lchild, pre);//Left subtree of the current node

		if(!p->lchild){p->lTag = Thread;p->lchild = pre;}//Precursor clue
		if(!pre->rchild){pre->rTag = Thread;pre->rchild = p;}//Subsequent thread
		pre = p;

		InThreading(p->rchild, pre);//Thread the right subtree of the current node
	}
}

After the binary tree is threaded, it can be traversed:

Status InOrderTraverse_Threads(binaryThrTree thrT){
	binaryThrTree p = thrT->lchild;//Find the root node of the binary tree
	while(p != thrT){//The binary tree is empty or p points to the head node when the threaded binary tree is traversed
		while(p->lTag == Link) p = p->lchild;
		cout<<p->data<<" ";//Access the node whose left subtree is empty
		while(p->rTag == Thread && p->rchild!= thrT){//Access the successor node according to the clue
			p = p->rchild;
			cout<<p->data<<" ";
		}
		p = p->rchild;
	}
	return 1;
}

The complete code is as follows:

// binaryThrTree.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <iostream>

using namespace std;

typedef string tElemType;
typedef int Status;
typedef enum PointerTag{Link, Thread};

typedef struct binaryThrNode{
	tElemType data;
	struct binaryThrNode *lchild, *rchild;
	PointerTag lTag, rTag;
}binaryThrNode, *binaryThrTree;

Status createthrTree(binaryThrTree &thrT){
	//create a thread binary tree in pre-order.
	//after this work finished, the attributes lTag and rTag of this thread binary tree is not initialised.

	string starts;
	cin>>starts;
	if(starts == "#") thrT = NULL;
	else{
		thrT = new binaryThrNode;
		if (!thrT) exit(-1);

		thrT->data = starts;
		thrT->lTag = Link;
		thrT->rTag = Link;
		createthrTree(thrT->lchild);
		createthrTree(thrT->rchild);
	}
	return 1;
}

Status inOrderTraverse(binaryThrTree T){
	if(T){
		inOrderTraverse(T->lchild);
		cout<<(T->data)<<" ";
		inOrderTraverse(T->rchild);
	}
	return 1;
}

void InThreading(binaryThrTree p, binaryThrTree &pre){
	
	if(p){
		InThreading(p->lchild, pre);
		if(!p->lchild){p->lTag = Thread;p->lchild = pre;}
		if(!pre->rchild){pre->rTag = Thread;pre->rchild = p;}
		pre = p;
		InThreading(p->rchild, pre);
	}
}

Status inOrderThreading(binaryThrTree &thrT, binaryThrTree T){
	binaryThrTree pre;

	thrT = new binaryThrNode;
	if(!thrT) exit(-1);

	thrT->lTag = Link;
	thrT->rTag = Thread;
	thrT->rchild = thrT;

	if(!T)thrT->lchild = thrT;
	else{
		thrT->lchild = T;
		pre = thrT;

		InThreading(T ,pre);

		pre->rchild = thrT;
		pre->rTag = Thread;
		thrT->rchild = pre;
	}
	return 1;
}

Status InOrderTraverse_Threads(binaryThrTree thrT){
	binaryThrTree p = thrT->lchild;
	while(p != thrT){
		while(p->lTag == Link) p = p->lchild;
		cout<<p->data<<" ";
		while(p->rTag == Thread && p->rchild!= thrT){
			p = p->rchild;
			cout<<p->data<<" ";
		}
		p = p->rchild;
	}
	return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	binaryThrTree T = new binaryThrNode;
	if(!T) exit(-1);
	
	cout<<"Try to create a thread binary tree..."<<endl;
	createthrTree(T);
	cout<<"creation is finished!"<<endl;
	cout<<"Try to traverse it:"<<endl;
	inOrderTraverse(T);

	binaryThrTree thrT;
	
	cout<<endl<<"Try to thread the binary thread tree..."<<endl;
	inOrderThreading(thrT, T);
	cout<<"Try to traverse the binary thread tree with threads:"<<endl;
	InOrderTraverse_Threads(thrT);
	
	delete thrT;
	delete T;

	system("pause");
	return 0;
}

The effect is as follows:


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325835618&siteId=291194637