Inorder traversal of the clue binary tree of the data structure (detailed explanation)

According to the explanation in my previous blog, everyone should have a certain understanding of the clue binary tree. The clue binary tree uses the pointer pointing to NULL to prevent it from being wasted, so a node has two pointers, which are left pointer and right pointer respectively. Let Originally pointing to NULL, the left pointer and right pointer point to the predecessor node and successor node of the node after the in-order traversal respectively. If there is no predecessor node, just point to NULL.

Each node looks like this:

 

b29767d71c334f75a1e90efb5647d66d.png

The specific implementation code of the structure is as follows:

typedef struct stu
{
    char name[28];
    int num;
    int ltag,rtag    //标志结点
    struct stu *lchild,*rchild //左指针右指针
};

When we implement it, we need to pay attention to the need to assign values ​​​​to ltag and rtag when creating a binary tree.

code show as below:

struct stu* create()
{
	stu *p;
	p = new stu();
	cout << "请按照顺序输入名字和学号,学号为0时为NULL:" << endl;
	cin >> p->name >> p->num;
	if (p->num == 0)
	{
		p = NULL;
	}
	else
	{
		p->ltag = 0;
		p->rtag = 0;
		p->lchild = create();
		p->rchild = create();
	}
	return p;
}

Compared with the general binary tree creation, there is only one more assignment to indicate whether the sign is the left child or the clue, but this assignment is very important in the later use. In this code, when the sign is 0, it means that there is a child. The sign is 1 means no children and points to the predecessor node or successor node.

The specific clue is to traverse the binary tree and assign the value it should have to the flag, then set a head node to point to the root node of the binary tree, and keep looping when the binary tree is not equal to the head node, and then let The right pointer of the last node in the binary tree traversal points to the head node.

The specific threading code is as follows:

struct stu* pre = NULL;
void inthread(stu* p)
{
	if (p != NULL)
	{
		inthread(p->lchild);
		if (p->lchild == NULL)
		{
			p->lchild = pre;
			p->ltag = 1;
		}
		if (pre->rchild == NULL&&pre!=NULL)
		{
			pre->rchild = p;
			pre->rtag = 1;
		}
		pre = p;
		inthread(p->rchild);
	}
}

struct stu* head(stu* p)
{
	stu* T;
	T = new stu();
	T->ltag = 0;
	T->rtag = 1;
	T->lchild = T;
	if (p == NULL)
		T->lchild = T;
	else
	{
		T->lchild = p;
		T->ltag = 1;
		pre = T;
		inthread(p);//出来之后的pre是二叉树访问的最后一个节点,将他的后继设为头节点
		pre->rtag = 1;
		pre->rchild = T;
		T->rchild = pre;
	}
	return T;
}

The setting of threading is very simple. The most important thing here is the setting of the head node. First create a head node and then let its left flag be 0 (that is, there is a left child), and let the right flag be 1 (no right child). Then if the root node is empty, no threading is performed, because there is no corresponding data, so the left child is equal to itself. If the root node is not empty, let the left pointer of the head node point to the right node of the binary tree, then let the left flag be 1 to make it threaded, and then use the threaded function to find the last node pre visited by the binary tree, Let the right flag of pre be 1, and let its right pointer point to the head node as the adjustment for the end of the loop.

The final implementation of the traversal code is as follows:

#include<iostream>
using namespace std;

typedef struct stu {
	char name[28];
	int num;
	int ltag, rtag;		
	struct stu* lchild, *rchild;	
}stu;
stu* pre = NULL;
struct stu* create()
{
	stu *p;
	p = new stu();
	cout << "请按照顺序输入名字和学号,学号为0时为NULL:" << endl;
	cin >> p->name >> p->num;
	if (p->num == 0)
	{
		p = NULL;
	}
	else
	{
		p->ltag = 0;
		p->rtag = 0;
		p->lchild = create();
		p->rchild = create();
	}
	return p;
}

void inthread(stu* p)
{
	if (p != NULL)
	{
		inthread(p->lchild);
		if (p->lchild == NULL)
		{
			p->lchild = pre;
			p->ltag = 1;
		}
		if (pre->rchild == NULL&&pre!=NULL)
		{
			pre->rchild = p;
			pre->rtag = 1;
		}
		pre = p;
		inthread(p->rchild);
	}
}

struct stu* head(stu* p)
{
	stu* T;
	T = new stu();
	T->ltag = 0;
	T->rtag = 1;
	T->lchild = T;
	if (p == NULL)
		T->lchild = T;
	else
	{
		T->lchild = p;
		T->ltag = 1;
		pre = T;
		inthread(p);
		pre->rtag = 1;
		pre->rchild = T;
		T->rchild = pre;
	}
	return T;
}

void print(stu* p)
{
	stu* s;
	s = p->lchild;
	while(s != p)
	{
		while (s->ltag == 0)
			s = s->lchild;
		cout << s->name << "\t" << s->num << endl;
		while (s->rtag == 1 && s->rchild != p)
		{
			s = s->rchild;
			cout << s->name << "\t" << s->num << endl;
		}
		s = s->rchild;
	}
}

int main()
{
	stu* p;
	stu* T;
	p = create();
	T = head(p);
	print(T);
	return 0;
}

For the output function, the loop ends when the p node is equal to the head node. First, find the first node of the in-order traversal, that is, the node in the lower left corner, and then output it, and then if the node has no right The child finds its successor node and performs an output operation. If there is a right child, it finds the right child (the right child has no left child) and outputs. It has been output to the root node, and then the root node has a right child, so it jumps out of the bottom loop and then enters the right subtree of the root node, then performs in-order traversal to find the node output in the lower left corner, and so on until s points to the head node It is considered the end (if the head node is not set, it is impossible to judge when the loop will end).

The input structure diagram is as follows:

3b623c9451b346a38a0ab0535a4800be.png 

 

The input data and output results of the program are as follows:

 0251cc46da5149d4b706a976fa684570.png

fde853eb9ee44e7daa09383b3bf14a3e.png 

 Well, what I want to talk about today is the threading of the in-order traversal of the binary tree and the output problem after threading. Threading solves the waste of pointers and at the same time facilitates us to find the successor or predecessor of a certain node. .

I hope everyone can walk slowly in their own world and don't follow the crowd! ! ! Just go the way you want to go.

 

Guess you like

Origin blog.csdn.net/m0_61886762/article/details/124609052