Beiyou 22 Xintong: Chapter 6 Search: BST Tree Table (code with super detailed step-by-step diagrams)

A Beiyou 22 Xintong~   

Code and articles on data structures and algorithms are updated weekly following the progress of the course 

Continue to pay attention to the author to unlock more exclusive codes of Youyuan Xintong~

For more articles, please visit the column:

Beiyou 22 Letters and Communications_The green hills are like ink and the rain is picturesque blog-CSDN blog

Table of contents

explain

1. Constructor

2. Destructor

 3. Query function

4. Delete operation (emphasis)

First case:

Second case:

The third case:

Explain the third case in detail with examples

1. Delete 30:

 2. Delete 20:

code part

Renderings:

 code:

operation result:


explain

1. Constructor

One of the characteristics of the BST tree table is that if a node is randomly selected, the weight of any node in the left subtree is smaller than this node, and the weight of any node in the right subtree is greater than this node. According to this feature, in order to realize the writing of the constructor, we must consider such a problem: when a weight is given, where do we insert the weight into the tree table.

So first explain the insert_bst function:

The insert function passes in two parameters, one is the initial location of access, indicated by a pointer; the other parameter is the node to be inserted.

First, if the tree table is empty, directly insert the node to be inserted as the root node.

Secondly, if the tree table is not empty, there will be two situations: the weight of the node to be inserted is greater or less than the weight of the currently visited node. Apply recursive thinking, if it is greater than, call insert_bst, and pass in the right child node of the node where the current position is located and the node to be inserted; if it is less than, call insert_bst, and pass in the left child node of the node where the current position is and the node to be inserted.

code part:

template<class temp>
void BST<temp>::insert_bst(binnode<temp>*& r, binnode<temp>* s)
{
	if (r == NULL)
		r = s;
	else if (s->data < r->data)
		insert_bst(r->leftchild, s);
	else
		insert_bst(r->rightchild, s);
}

Through this insertion method, the binary tree can be made into an ordered BST tree.

After the insert function is implemented, the implementation of the constructor is obvious.

Every time a piece of data is passed in, create a new node, open up a heap space, assign a value to the new node, and call the insert function to directly insert the assigned node into the BST tree, thus realizing the construction of the BST tree.

2. Destructor

The implementation method of the destructor is the same as the implementation method of the binary tree destructor. The core idea is the recursive function, so I won’t go into details here.

code part:

template<class temp>
void BST<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}
template<class temp>
BST<temp>::~BST()
{
	release(this->root);
}

 3. Query function

The query function is also a feature of applying recursive ideas and BST trees. According to the characteristic that any node in the left subtree of BST is smaller than the current node and any node in the right subtree is larger than the current node, two parameters are passed in, one is the location to start accessing, and the other is the data to be queried.

If the current location does not exist, return a null pointer;

If the weight of the current location is exactly equal to the data to be queried, return a pointer to this location;

If the data is less than the weight of the access location, call this function recursively to query the left subtree of the access location;

If the query data is greater than the weight of the access position, call this function recursively to query the right subtree of the access position.

code part:

template<class temp>
binnode<temp>* BST<temp>::search
(binnode<temp>*& r, temp k)
{
	if (r == NULL)
		return NULL;
	if (k == r->data)
		return r;
	else if (k < r->data)
		return search(r->leftchild, k);
	else
		return search(r->rightchild, k);
}

4. Delete operation (emphasis)

The core algorithm is to delete the node where the keyword is located.

It is really not easy to delete a node in an ordered binary tree. We not only need to consider how to delete a node, but also how to reconnect the subtree of this node to the original BST tree after the node is deleted.

There are three situations to delete a node, from easy to difficult:

The deleted node is a leaf node;

The deleted node has only left subtree or only right subtree;

Both the left and right subtrees of the deleted node exist.

First case:

Just delete it directly;

Second case:

The deleted node has only left subtree or only right subtree:

Now assume that the node to be deleted is Xiaoming. Xiao Ming only has left children or only right children.

If Xiaoming is his father's left child, then Xiaoming's children are all less weighted than Xiaoming's father, then after Xiaoming is deleted, Xiaoming's children are connected to Xiaoming's father's left child; if Xiaoming is his father's right child , then Xiaoming's children are all more powerful than Xiaoming's father, then after Xiaoming is deleted, Xiaoming's children are all connected to Xiaoming's father's right child position.

The third case:

The third case is also the most complicated one: if the node to be deleted has both left and right children:

When the old emperor dies, a qualified heir must be selected from the royal family to inherit the throne. The old emperor left two branches, on the left are the sons waiting to succeed, and on the right are important officials of the court. The selected son must be the eldest son, that is, older than all the sons to be succeeded, and younger than the officials.

After finding it, the new emperor ascended the throne, and the palace where it was originally located was demolished.

code part:

template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
	binnode<temp>* q, * s;
	if (r->leftchild == NULL)
	{
		q = r;
		r = r->rightchild;
		delete q;
	}
	else if (r->rightchild == NULL)
	{
		q = r;
		r = r->leftchild;
		delete q;
	}
	else
	{
		q = r;
		s = r->leftchild;
		while (s->rightchild != NULL)
		{
			q = s;
			s = s->rightchild;
		}
		r->data = s->data;
		if (q != r)
			q->rightchild = s->leftchild;
		else
			r->leftchild = s->leftchild;
		delete s;
	}
}

Explain the third case in detail with examples

BST tree:

                                                                                 

1. Delete 30:

 2. Delete 20:

The overall code of the delete operation:

template<class temp>
bool BST<temp>::delete_key(binnode<temp>*&r,temp k)
{
	if (r == NULL)
		return false;
	else
	{
		if (k == r->data)
		{
			delete_node(r);
			return true;
		}
		else if (k < r->data)
			return delete_key(r->leftchild, k);
		else
			return delete_key(r->rightchild, k);

	}
}
template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
	binnode<temp>* q, * s;
	if (r->leftchild == NULL)
	{
		q = r;
		r = r->rightchild;
		delete q;
	}
	else if (r->rightchild == NULL)
	{
		q = r;
		r = r->leftchild;
		delete q;
	}
	else
	{
		q = r;
		s = r->leftchild;
		while (s->rightchild != NULL)
		{
			q = s;
			s = s->rightchild;
		}
		r->data = s->data;
		if (q != r)
			q->rightchild = s->leftchild;
		else
			r->leftchild = s->leftchild;
		delete s;
	}
}

code part

Renderings:

 code:

#include<iostream>
using namespace std;
class student
{
private:
	int ID;
	string name;
public:
	int existence;
	student()
	{
		this->ID = 0;
		this->name = "unknown name";
		this->existence = 0;
	}
	student(int ID, string name)
	{
		this->ID = ID;
		this->name = name;
		this->existence = 1;
	}
	friend ostream& operator<<(ostream& output, student& s)
	{
		output << s.ID << " " << s.name << endl;
		return output;
	}
	void print()
	{
		cout << this->name << " " << this->ID << endl;
	}
	bool operator <(student& s)
	{
		return (this->ID < s.ID) ? true : false;
	}
	bool operator>(student& s)
	{
		return (this->ID > s.ID) ? true : false;
	}
	bool operator==(student& s)
	{
		return (this->ID == s.ID) 
			&& (this->name == s.name) ? true : false;
	}
	bool operator !=(student& s)
	{
		return (this->ID != s.ID)
			|| (this->name != s.name) ? true : false;
	}
};

template<class temp>
struct binnode
{
	temp data;
	binnode<temp>* leftchild;
	binnode<temp>* rightchild;
};

template<class temp>
class BST
{
public:
	BST(temp r[], int n);
	void insert_bst(binnode<temp>*& r, binnode<temp>* s);
	//调用顺序:构造函数调用insert函数。

	binnode<temp>* search(binnode<temp>*& r, temp key);
	void is_found(binnode<temp>*& r, temp k)
	{
		binnode<temp>* p = search(r, k);
		if (p != NULL)
			cout << "is_found:" << p->data;
		else
			cout << "un_found";
	}

	binnode<temp>* get_root()
	{
		return this->root;
	}

	void release(binnode<temp>* r);
	~BST();
	//调用顺序:析构函数调用release函数。

	void delete_node(binnode<temp>*& r);
	bool delete_key(binnode<temp>*& r, temp key);
	//调用顺序:delete_key函数调用delete_node函数。

	void inorder_print(binnode<temp>*p);
private:
	binnode<temp>* root;
};

template<class temp>
BST<temp>::BST(temp r[], int n)
{
	this->root = NULL;
	for (int i = 0; i < n; i++)
	{
		binnode<temp>* s = new binnode<temp>;
		s->data = r[i];
		s->leftchild = s->rightchild = NULL;
		insert_bst(this->root, s);
	}
}
template<class temp>
void BST<temp>::insert_bst(binnode<temp>*& r, binnode<temp>* s)
{
	if (r == NULL)
		r = s;
	else if (s->data < r->data)
		insert_bst(r->leftchild, s);
	else
		insert_bst(r->rightchild, s);
}

template<class temp>
binnode<temp>* BST<temp>::search
(binnode<temp>*& r, temp k)
{
	if (r == NULL)
		return NULL;
	if (k == r->data)
		return r;
	else if (k < r->data)
		return search(r->leftchild, k);
	else
		return search(r->rightchild, k);
}


template<class temp>
void BST<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}
template<class temp>
BST<temp>::~BST()
{
	release(this->root);
}


template<class temp>
bool BST<temp>::delete_key(binnode<temp>*&r,temp k)
{
	if (r == NULL)
		return false;
	else
	{
		if (k == r->data)
		{
			delete_node(r);
			return true;
		}
		else if (k < r->data)
			return delete_key(r->leftchild, k);
		else
			return delete_key(r->rightchild, k);

	}
}
template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
	binnode<temp>* q, * s;
	if (r->leftchild == NULL)
	{
		q = r;
		r = r->rightchild;
		delete q;
	}
	else if (r->rightchild == NULL)
	{
		q = r;
		r = r->leftchild;
		delete q;
	}
	else
	{
		q = r;
		s = r->leftchild;
		while (s->rightchild != NULL)
		{
			q = s;
			s = s->rightchild;
		}
		r->data = s->data;
		if (q != r)
			q->rightchild = s->leftchild;
		else
			r->leftchild = s->leftchild;
		delete s;
	}
}


template<class temp>
void BST<temp>::inorder_print(binnode<temp>* p)
{
	if(p != NULL)
	{
		inorder_print(p->leftchild);
		cout << p->data;
		inorder_print(p->rightchild);
	}
}

int main()
{
	system("color 0A");
	student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
	BST<student>bst(stu, 5);
	binnode<student>* p = bst.get_root();
	bst.inorder_print(p);

	student s(2, "wang");

	bst.is_found(p, s);

	bst.delete_key(p, s);
	bst.inorder_print(p);

	bst.is_found(p, s);

	return 0;
}

operation result:

Guess you like

Origin blog.csdn.net/bc202205/article/details/131140768