binary search tree

Give the definition of a binary search tree:

typedef char SearchTreeType;

typedef struct SearchTreeNode
{
	SearchTreeType key; // key code
	struct SearchTreeNode* lchild;
	struct SearchTreeNode* rchild;
}SearchTreeNode;

Put the function declaration in the head.h header file:

#pragma once

#include <stdio.h>
#include <windows.h>

typedef char SearchTreeType;

typedef struct SearchTreeNode
{
	SearchTreeType key; // key code
	struct SearchTreeNode* lchild;
	struct SearchTreeNode* rchild;
}SearchTreeNode;


// initialize
void SearchTreeInit(SearchTreeNode** root);

// create new node
SearchTreeNode* CreateSearchTreeNode(SearchTreeType key);

//non-recursive
// insert
void SearchTreeInsert_P(SearchTreeNode** root, SearchTreeType key);

// find
SearchTreeNode* SearchTreeFind_P(SearchTreeNode* root, SearchTreeType to_find);

// delete
void SearchTreeRemove_P(SearchTreeNode** root, SearchTreeType key);

void PreOrder(SearchTreeNode* root);
void InOrder(SearchTreeNode* root);

void DestroySearchTreeNode(SearchTreeNode* node);


//recursive
// insert
void SearchTreeInsert(SearchTreeNode** root, SearchTreeType key);

// find
SearchTreeNode* SearchTreeFind(SearchTreeNode* root, SearchTreeType to_find);

// delete
void SearchTreeRemove(SearchTreeNode** root, SearchTreeType key);

Definition of the function (specific implementation):

#include "SearchTree.h"

void SearchTreeInit(SearchTreeNode** root)
{
	if (root == NULL)
	{
		return;
	}
	*root = NULL;
}

void DestroySearchTreeNode(SearchTreeNode* node)
{
	free(node);
}

SearchTreeNode* CreateSearchTreeNode(SearchTreeType key)
{
	SearchTreeNode* new_node = (SearchTreeNode*)malloc(sizeof(SearchTreeNode));
	new_node->key = key;
	new_node->lchild = NULL;
	new_node->rchild = NULL;
	return new_node;
}

void SearchTreeInsert_P(SearchTreeNode** root, SearchTreeType key)
{
	if (root == NULL)
	{
		return;
	}

	// 1. If the tree is empty
	if (*root == NULL)
	{
		*root = CreateSearchTreeNode(key);
		return;
	}

	// 2. If the tree is non-empty:
	// a) Find a suitable insertion position first
	SearchTreeNode* cur = *root;
	SearchTreeNode* parent = NULL;
	while (1)
	{
		if (cur == NULL)
		{
			// suitable location has been found
			break;
		}

		if (key < cur->key)
		{
			parent = cur;
			cur = cur->lchild;
		}
		else if (key > cur->key)
		{
			parent = cur;
			cur = cur->rchild;
		}
		else
		{
			// It is found that the current element is the same as the value to be inserted, here we agree to let its insertion fail
			return;
		}
	}
	// b) Create a node at the corresponding position
	SearchTreeNode* new_node = CreateSearchTreeNode(key);
	if (key < parent->key)
	{
		parent->lchild = new_node;
	}
	else
	{
		parent->rchild = new_node;
	}
}

SearchTreeNode* SearchTreeFind_P(SearchTreeNode* root, SearchTreeType to_find)
{

	if (root == NULL)
	{
		return;
	}
	SearchTreeNode* cur = root;
	while (cur)
	{
		if (to_find < cur->key)
		{
			cur = cur->lchild;
		}
		else if (to_find < cur->key)
		{
			cur = cur->rchild;
		}
		else
		{
			break;
		}
	}
	return cur;
}

void SearchTreeRemove_P(SearchTreeNode** root, SearchTreeType key)
{
	if (root == NULL)
	{
		return;
	}

	// 1. Handle the case of an empty tree and return directly
	if (*root == NULL)
	{
		return NULL;
	}

	// 2. Find the location of the node to be deleted, and the parent node of the node to be deleted
	SearchTreeNode* to_remove = *root;
	SearchTreeNode* parent = NULL;
	while (to_remove)
	{
		if (key < to_remove->key)
		{
			parent = to_remove;
			to_remove = to_remove->lchild;
		}
		else if (key > to_remove->key)
		{
			parent = to_remove;
			to_remove = to_remove->rchild;
		}
		else
		{
			// found it
			break;
		}
	}

	// 3. If the element you are looking for is not found in the tree, return directly
	if (to_remove == NULL)
	{
		return;
	}

	// 4. If the node to be deleted exists, it needs to be discussed according to the situation:
	// a) The node to be deleted has no subtree, delete the node directly, and leave the parent node empty
	if (to_remove->lchild == NULL && to_remove->rchild == NULL)
	{
		if (to_remove == *root)
		{
			// If the element to be deleted is the root node, then process it directly
			*root = NULL;
		}
		else
		{
			// If the element to be deleted is not the root node, it is determined by the following logic
			if (parent->lchild == to_remove)
			{
				parent->lchild = NULL;
			}
			else
			{
				parent->lchild = NULL;
			}
		}
		DestroySearchTreeNode(to_remove);
		return;
	}

	// b) The node to be deleted has only the left subtree. At the same time when the node is deleted, the left subtree of the node is attached to the parent node
	else if (to_remove->lchild != NULL && to_remove->rchild == NULL)
	{
		if (to_remove == *root)
		{
			// if the element to delete is the root node
			*root = to_remove->lchild;
		}
		else
		{
			// If the element to be deleted is not the root node, it is determined by the following logic
			if (to_remove == parent->lchild)
			{
				parent->lchild = to_remove->lchild;
			}
			else
			{
				parent->rchild = to_remove->lchild;
			}
		}
		DestroySearchTreeNode(to_remove);
		return;
	}

	// c) The node to be deleted has only the right subtree. At the same time when the node is deleted, the right subtree of the node is attached to the parent node
	else if (to_remove->lchild == NULL && to_remove->rchild != NULL)
	{
		if (to_remove == *root)
		{
			// if the element to delete is the root node
			*root = to_remove->rchild;
		}
		else
		{
			// If the element to be deleted is not the root node, it is determined by the following logic
			if (to_remove == parent->lchild)
			{
				parent->lchild = to_remove->rchild;
			}
			else
			{
				parent->rchild = to_remove->rchild;
			}
		}
		DestroySearchTreeNode(to_remove);
		return;
	}

	// d) The node to be deleted has left and right subtrees at the same time, find the minimum value in the right subtree, and then assign the minimum value to the position to be deleted,
	// Then delete the minimum node in the right subtree, so that a node has at most one right subtree, which is converted into case c)
	else
	{
		SearchTreeNode* min = to_remove->rchild;
		SearchTreeNode* min_parent = to_remove;
		while (min->lchild != NULL)
		{
			min_parent = min;
			min = min->lchild;
		}

		// When the code is executed here, min already points to the minimum value of the right subtree of to_remove
		to_remove->key = min->key;
		if (min_parent->lchild == min)
		{
			min_parent->lchild = min->rchild;
		}
		else
		{
			min_parent->rchild = min->rchild;
		}
		DestroySearchTreeNode(min);
		return;
	}
}

void PreOrder(SearchTreeNode* root)
{
	if (root)
	{
		printf("%c  ", root->key);
		PreOrder(root->lchild);
		PreOrder(root->rchild);
	}
}
void InOrder(SearchTreeNode* root)
{
	if (root)
	{
		InOrder(root->lchild);
		printf("%c  ", root->key);
		InOrder(root->rchild);
	}
}

void SearchTreeInsert(SearchTreeNode** root, SearchTreeType key)
{
	if (root == NULL)
	{
		// illegal input
		return;
	}
	
	if (*root == NULL) // key code // 2. Create a new node and hang it at the corresponding position
	{
		*root = CreateSearchTreeNode(key);
		return;
	}

	// 1. First find where to insert
	if (key < (*root)->key)
	{
		SearchTreeInsert(&(*root)->lchild, key);
	}
	else if (key > (*root)->key)
	{
		SearchTreeInsert(&(*root)->rchild, key);
	}
	else
	{
		// It is found that the current element is the same as the value to be inserted, here we agree to let its insertion fail
		return;
	}
}

SearchTreeNode* SearchTreeFind(SearchTreeNode* root, SearchTreeType to_find)
{
	if (root == NULL)
	{
		// empty tree
		return;
	}
	if (to_find < root->key)
	{
		return SearchTreeFind(root->lchild, to_find);
	}
	else if (to_find > root->key)
	{
		return SearchTreeFind(root->rchild, to_find);
	}
	else
	{
		// turn up
		return root;
	}
}

void SearchTreeRemove(SearchTreeNode** root, SearchTreeType key)
{
	if (root == NULL)
	{
		// illegal input
		return;
	}
	
	// 1. Find the position in the tree of the element to delete
	// 2. If not found, no delete operation is required
	if (*root == NULL)
	{
		// empty tree
		return;
	}

	if (key < (*root)->key)
	{
		SearchTreeRemove(&(*root)->lchild, key);
	}
	else if (key > (*root)->key)
	{
		SearchTreeRemove(&(*root)->rchild, key);
	}

	// 3. If found, discuss by situation
	else
	{
		SearchTreeNode* to_remove = *root;

		// a) To delete an element without a subtree, just delete the node directly
		if (to_remove->lchild == NULL && to_remove->rchild == NULL)
		{
			*root = NULL;
			DestroySearchTreeNode(to_remove);
		}

		// b) To delete elements only the left subtree, first hang the left subtree on the parent node, and then delete the current node
		else if (to_remove->lchild != NULL && to_remove->rchild == NULL)
		{
			*root = to_remove->lchild;
			DestroySearchTreeNode(to_remove);
		}

		// c) To delete elements only the right subtree, first hang the right subtree on the parent node, and then delete the current node
		else if (to_remove->lchild == NULL && to_remove->rchild != NULL)
		{
			*root = to_remove->rchild;
			DestroySearchTreeNode(to_remove);
		}

		// d) To delete an element that has left and right subtrees at the same time, first find the smallest element in the right subtree of the current element,
		// Assign this minimum element to the element to be deleted, then delete the minimum element just now, and then convert the problem into b) or c)
		else
		{
			SearchTreeNode* min = to_remove->rchild;
			while (min->lchild != NULL)
			{
				min = min->lchild;
			}
			// The code is executed here, which means that min has pointed to the smallest element in the right subtree of to_remove

			to_remove->key = min->key;
			SearchTreeRemove(&to_remove->rchild, min->key);
		} // to_remove left and right subtrees exist
	} // key == to_remove->key
}

Test code:

#include "SearchTree.h"

void TestSearchTree()
{
	SearchTreeNode* root;
	SearchTreeInit(&root);
	printf("root expect NULL, actual %p\n", root);

	SearchTreeInsert_P(&root, 'B');
	SearchTreeInsert_P(&root, 'A');
	SearchTreeInsert_P(&root, 'G');
	SearchTreeInsert_P(&root, 'D');
	SearchTreeInsert_P(&root, 'E');
	SearchTreeInsert_P(&root, 'F');

	printf("Preorder traversal: ");
	PreOrder(root);
	printf("\n");

	printf("Inorder traversal: ");
	InOrder(root);
	printf("\n");

	SearchTreeNode* result = SearchTreeFind(root, 'E');
	printf("result expect %p, actual %p \n", root->rchild->lchild->rchild, result);
}

intmain()
{
	TestSearchTree();
	system("pause");
	return 0;
}

The result is as follows:


Guess you like

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