Implementation of "Binary Sort Tree and Balanced Binary Tree" of Data Structure

Binary sort tree and balanced binary tree

Binary Sort Tree

definition:

The binary sort tree is either an empty tree, or a binary tree that satisfies the following conditions:

  1. If the left subtree of the binary sort is not empty, the values ​​of all vertices of the left subtree are less than the root node of the binary sort tree; the left subtree is also a binary sort tree.
  2. If the right subtree of the binary sort is not empty, the values ​​of all vertices of the right subtree are greater than the root node of the binary sort tree; the right subtree is also a binary sort tree.

as the picture shows:

Binary sort tree example

It can be found from the above figure that 6 in Figure b is larger than the root node 5 , which does not meet the conditions of the binary sorting tree, so it is not a binary sorting tree.

  Binary sort tree can be used in the optimization of search algorithms. Except for hash tables, the fastest time complexity of other search algorithms is basically O(lgn). The use of binary sort for search is also in some cases This time complexity can be reached, and the process of searching by a binary sort tree is explained below.

There is already a binary sort tree as shown in a in the above figure. You need to find whether the number 7 (denoted as x) is in the binary tree:

  1. Compare x with the root node, if they are equal, the array is in the binary tree, and the search is successful;
  2. If x is less than the value of the root node, search the left subtree and continue the comparison;
  3. If x is greater than the value of the root node, look for the right subtree and continue to compare, 7> 5, so look in the direction of the right subtree.
  4. Repeat the above process, if the leaf node is found and the value is still not found, the data can be added to the binary sorting tree as the child node of the leaf node. Whether the left child or the right child should satisfy the binary sorting tree The requirement is greater than the value of the leaf node to be inserted into the right child. The value less than the leaf node is inserted into the left child.

The code is implemented as follows:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef struct _node{
    int key;
    struct _node *lchild, *rchild;
}*Tree, Node;
Node* binarySearch(Tree &root, int key) {
    if (root == NULL) {	//为空插入该二叉排序树中
        root = (Node *)malloc(sizeof(Node));
        root->key = key;
        root->lchild = NULL;
        root->rchild = NULL;
        return NULL;
    }
    Node *temp = root;
    if (temp->key == key) {
        return temp;
    } else if (temp->key < key) {	//查找的数值比较大,遍历右子树
        return binarySearch(temp->rchild, key);
    } else {		//查找的数值比较小,遍历左子树
        return binarySearch(temp->lchild, key);
    }
}

/**
 *	中序遍历二叉树
 */
void dfs(Tree root) {
	if (root->lchild) {
		dfs(root->lchild);
	}
	printf("%d\t", root->key);
	if (root->rchild) {
		dfs(root->rchild);
	}
}

int main() {
    
    Tree root = (Node*)malloc(sizeof(Node));
    root->lchild = NULL;
    root->rchild = NULL;
	cin >> root->key;
	int key;
	for (int i = 1; i < 5; i++) {
		cin >> key;
		binarySearch(root, key);		//这里并没有接收返回值
	} 
	dfs(root);
    
    return 0;
}

Note: The above code uses the idea of ​​a binary sort tree to create a binary sort tree, and does not display the search operation. If you use the in-order traversal method for the binary sort tree, you will get a non-decreasing The ordered sequence.

Test case

输入:5
4 6 3 2
输出:2 3 4 5 6

Performance analysis

Now let's calculate the average search length (ASL) of the binary sort tree, for example:

Binary sort tree example

  As shown in the figure above, the search performance of binary sort trees of different shapes is very different, the best is O(lgn), the worst is O(n), and in the case of random, there is proof to The search performance of a binary sort tree is of the order of O(lgn), but at the same time, a proof is given that there is a 46.5% probability (the data is obtained from the book "Data Structure"). Only by "balancing" can we get this magnitude of time complexity. There are many algorithms to "balance", one of which is relatively simple to understand is the balanced binary tree .
  

Balanced binary tree

  Balanced binary tree, namely AVL tree, the so-called balance means that the depth difference between the left and right subtrees of the root node of the balanced binary tree does not exceed 1, which can make the binary tree as full as possible (as close as possible to the complete Binary tree).

Related concepts:

Balance factor

The height difference between the left subtree and the right subtree of the node . Possible values ​​are -1, 0, 1 to indicate

-1: Indicates that the height of the right subtree is 1 greater than the height of the left subtree

0: Indicates that the heights of the left and right subtrees are equal

1: Indicates that the height of the left subtree is 1 greater than the height of the right subtree

  When the absolute value of the balance factor is greater than 1, the binary tree is out of balance . At this time, some operations must be used to adjust so that the absolute value of the balance factor of the nodes in the binary tree is not greater than 1. As a result, the height of the binary tree can be adjusted to be maintained at the O(lgn) level, so that the time complexity of its search is also at the O(lgn) level;

  When a node is inserted into a binary tree, the balance is lost. At this time, the balanced binary tree must be re-adjusted to restore balance. This process is called balance rotation . Generally can be divided into LL balance rotation , RR balance rotation , LR balance rotation, LR balance rotation . (L refers to the left subtree, and R refers to the right subtree. For example, LL means that the node has only the left child, and the left child has only the left child)

  1. LL balance rotation

LL balance rotation

That is, take the parent node of the inserted node as the rotation axis , and rotate its ancestor node.

2.RR balance rotation

RR balance rotation

That is, take the parent node of the inserted node as the rotation axis , and rotate its ancestor node inversely.

3.LR balance rotation

LR balance rotation

That is, with the inserted node as the axis of rotation, it is necessary to rotate its parent node counterclockwise and its ancestor node clockwise.

  1. RL balance rotation

RL balance rotation

That is, taking the inserted node as the axis of rotation , it is necessary to rotate its parent node clockwise and its ancestor node counterclockwise.

The code is implemented as follows

typedef struct _bstNode{
	int data;	//数据域 
	int bf;		//balance factor 平衡因子 0:高度差一致,1:左高,-1:右高
	struct _bstNode *lchild, *rchild; 
}BSTNode, *BSTree; 

/**
 * 右旋操作 
 * 将根节点root旋转到其左子树的右孩子节点上 
 * 如果左子树的右孩子有内容,则要将其作为根节点的左子树,因为其值是要比根节点的值要小的 
 */ 
void R_rotate(BSTree &root) {
	BSTNode *temp = root->lchild;	//根节点的左子树 
	root->lchild = temp->rchild;	//左孩子的右子树挂在根节点上,便于下面操作时不使树断开 
	temp->rchild = root;	//右旋操作,根节点作为左子树的有孩子 
	root = temp;			//重新设置根 -- 注意这里的参数是引用传递 
}

/**
 * 左旋操作
 * 将根节点root旋转到其右子树的左孩子节点上
 * 如果右子树的左孩子有值,则要将其添加到根节点的右子树上,因为其值要比根节点的值要大的 
*/
void L_rotate(BSTree &root) {
	BSTNode *temp = root->rchild;	//根节点的右子树 
	root->rchild = temp->lchild;	//右孩子的左子树挂在根节点上,下面操作会使树断开 
	temp->lchild = root;
	root = temp; 
} 

/**
 * 左平衡 -- 用在LR平衡旋转和LL平衡旋转中 
*/
void leftBalance(BSTree &T) {
	BSTNode *lchild = T->lchild;
	switch(lchild->bf) {
		case 1:	//LL平衡旋转
			lchild->bf = 0;
			t->bf = 0;
			R_rotate(T);	//对根节点T右旋即可
			break;	
		case -1:	//LR平衡旋转
			BSTNode *L_rchild = lchild->rchild;
			switch(L_rchild->bf) {
				case 1:
					T->bf = -1;
					lchild->bf = 0;
					break;
					
				case 0:
					T->bf = lchild->bf = 0;
					break;
					
				case -1:
					T->bf = 0;
					lchild->bf = 1;
					break;
			}
			L_rchild->bf = 0;
			L_rotate(T->lchild); 	//先对根节点的左孩子左旋
			R_rotate(T);	//再对根节点右旋 -- 可以按照上图过程来看
			break;
	}
} 


/**
 * 右平衡操作 -- 用在RL平衡旋转和RR平衡旋转中 
*/
void rightBalance(BSTree &T) {
	BSTNode * rchild = T->rchild;
	switch(rchild->bf) {
		case -1:	//RR平衡旋转
			rchild->bf = 0;
			T->bf = 0;
			L_rotate(T);	//对根节点进行左旋即可
			break;
			
		case 1:	//RL平衡旋转
			BSTNode *R_lchild = rchild->lchild;
			switch(R_lchild->bf) {
				case 0:
                      T->bf = rchild->bf = 0;
					break;
				case 1:
                      T->bf = 0;
                      rchild->bf = -1;
					break;
				case -1:
                      rchild->bf = 0;
                      T->bf = 1;
					break;
			}
			R_lchild->bf = 0;
			R_rotate(T->rchild);	//先对根节点的T右孩子右旋
			L_rotate(T);			//再对根节点进行左旋 -- 按照上图来看
			break;
	} 
	
} 

The above only gives the operation of modifying the node during rotation to help understand the process. After all, when you use it, you generally don’t manually implement this kind of balancing algorithm. Instead, you often use the collection framework packaged by others, such as the collection framework in Java. STL.

Reference: Know almost-what is a balanced binary tree AVL

Guess you like

Origin blog.csdn.net/weixin_44184990/article/details/108701163