2022-1-2 data structure tree down (c language code)

Posted by tom_b on Wed, 05 Jan 2022 03:58:22 +0100

1. Binary search tree

1. definition
Binary search tree (BST) is also called binary sort tree or binary lookup tree
Binary search tree: a binary tree, which can be empty;
If it is not empty, the following properties are met:
• All key values of non empty left subtree are less than those of its root node
• All key values of non empty right subtree are greater than those of its root node
• Both the left and right subtrees are binary search trees 2. Abstract data

2.1 special functions

#include<iostream>
#include<malloc.h>
using namespace std;
typedef int ElementType;
typedef struct TreeNode *BinTree;
struct TreeNode{
ElementType Data;
BinTree Left;
BinTree Right;
};

BinTree Find(ElementType X,BinTree BST): From binary search tree BST Find elements in X，Returns the address of the node where it is located
BinTree FindMin(BinTree BST): From binary search tree BST Find and return the address of the node where the smallest element is located
BinTree FindMax(BinTree BST): From binary search tree BST Finds and returns the address of the node where the largest element is located
BinTree Insert(ElementType X,BinTree BST): Insert an element BST
BinTree Delete(ElementType X,BinTree BST): from BST Delete an element from

2.2 search

1. The search starts from the root node. If the tree is empty, NULL is returned
2. If the search tree is not empty, the key value of the root node is compared with X and processed differently:
*If X is less than the key value of the root node, continue to search in the left subtree
*If X is greater than the key value of the root node, continue to search in the right subtree
*If X is equal to the key value of the root node, the search ends and a pointer to this node is returned
3. Find maximum and minimum elements
*The largest element must be on the end node of the rightmost branch of the tree
*The smallest element must be on the end node of the leftmost branch of the tree 2.2.1 search recursive implementation // Find recursive implementation
BinTree Find(ElementType X,BinTree BST){
if(!BST)  // If the root node is empty, NULL is returned
return NULL;
if(X < BST->Data) // Smaller than the root node, go to the left subtree to find
return Find(X,BST->Left);
else if(BST->Data < X)  // Larger than the root node, go to the right subtree to find
return Find(X,BST->Right);
else if(BST->Data == X) // eureka
return BST;
}
• Recursive implementation of finding minimum value // Recursive implementation of finding minimum value
BinTree FindMin(BinTree BST){
if(!BST)    // If it is empty, NULL is returned
return NULL;
else if(BST->Left)   // There is also a left subtree. Continue to find along the left branch
return FindMin(BST->Left);
else  // eureka
return BST;
}

2.2.2 find non recursive implementation

// Find non recursive implementation
BinTree IterFind(ElementType X,BinTree BST){
while(BST){
if(X < BST->Data)
BST = BST->Left;
else if(BST->Data < X)  // Larger than the root node, go to the right subtree to find
BST = BST->Right;
else if(BST->Data == X) // eureka
return BST;
}
return NULL;
}
• Non recursive implementation of finding maximum
// Non recursive implementation of finding maximum
BinTree FindMax(BinTree BST){
if(BST)  // If not empty
while(BST->Right)   // As long as the right subtree still exists
BST = BST->Right;
return BST;
}

2.3 deletion

• Three cases of deletion:
1. The leaf node to be deleted: delete it directly and set its parent node pointer to NULL
2. The node to be deleted has only one child node: point the pointer of its parent node to the child node to be deleted
3. The node to be deleted has left and right subtrees: replace the deleted node with the smallest element of the right subtree or the largest element of the left subtree  // delete
BinTree Delete(ElementType X,BinTree BST){
BinTree tmp;
if(!BST)  //Recursive end flag!!!!!
else if(X < BST->Data)   // X is smaller than the current node value. Continue to search and delete in the left subtree
BST->Left = Delete(X,BST->Left);
else if(BST->Data < X)   // X is larger than the current node value. Continue to search and delete in the right subtree
BST->Right = Delete(X,BST->Right);
else{  //  Find the deleted node
if(BST->Left && BST->Right){  // The deleted node has two children
tmp = FindMin(BST->Right);   // Find the lowest value in the right subtree
BST->Data = tmp->Data;     // Overwrite the current node with the found value
BST->Right = Delete(tmp->Data,BST->Right);    // Delete the minimum node of the right subtree found earlier
}else{  // The deleted node has only one child node or no child node
tmp = BST;
if(!BST->Left && !BST->Right)  // No child nodes
BST = NULL;
else if(BST->Left && !BST->Right)  // Only left child nodes
BST = BST->Left;
else if(!BST->Left && BST->Right)  // Only right child nodes
BST = BST->Right;
free(tmp);
}
}
return BST;
}

2.4 insertion

// insert
BinTree Insert(ElementType X,BinTree BST){
if(!BST){  // If it is empty, initialize the node and the end flag!!!!!!!!!!!
BST = (BinTree)malloc(sizeof(struct TreeNode));
BST->Data = X;
BST->Left = NULL;
BST->Right = NULL;
}else{ // Not empty
if(X < BST->Data)  // If it's small, hang it on the left
BST->Left = Insert(X,BST->Left);
else if(BST->Data < X)  // If it's big, hang it on the right
BST->Right = Insert(X,BST->Right);
// If it's equal, you don't have to do anything
}
return BST;
}

2.5 middle order traversal

// Medium order traversal
void  InOrderTraversal(BinTree BT){
if(BT){
InOrderTraversal(BT->Left);  // Enter left subtree
cout<<BT->Data;  // Print root
InOrderTraversal(BT->Right);  // Enter right subtree
}
}

2.6 testing

int main(){
BinTree BST = NULL;
BST = Insert(5,BST);
BST = Insert(7,BST);
BST = Insert(3,BST);
BST = Insert(1,BST);
BST = Insert(2,BST);
BST = Insert(4,BST);
BST = Insert(6,BST);
BST = Insert(8,BST);
BST = Insert(9,BST);
/*
5
/\
3  7
/\	 /\
1 4 6  8
\      \
2      9
*/
cout<<"The result of medium order traversal is:";
InOrderTraversal(BST);
cout<<endl;
cout<<"The minimum value to find is:"<<FindMin(BST)->Data<<endl;
cout<<"The maximum search value is:"<<FindMax(BST)->Data<<endl;
cout<<"Find the left subtree of the node with the value of 3. The node value is:"<<Find(3,BST)->Left->Data<<endl;
cout<<"The node value of the right subtree of the node with the lookup value of 7 is:"<<IterFind(7,BST)->Right->Data<<endl;
cout<<"Delete node with value of 5"<<endl;
Delete(5,BST);
/*
6
/\
3  7
/\	  \
1 4    8
\      \
2      9
*/
cout<<"The result of medium order traversal is:";
InOrderTraversal(BST);
cout<<endl;
return 0;
}

3. Balanced binary tree

The search efficiency of the binary search tree is related to the depth of the tree, and the composition of the binary search tree is related to its insertion sequence. In extreme cases, the binary search tree degenerates into a single chain (for example, the insertion sequence is 1, 2, 3... n), which greatly reduces the search efficiency. In order to avoid this situation, we use the binary balanced tree to adjust the insertion node, Make the depth of the tree as small as possible.
Balance factor: BF (T) = HL HR, which are the height of left and right subtrees respectively
Balanced binary tree (AVL tree): an empty tree, or a tree in which the absolute value of the height difference between the left and right subtrees of any node does not exceed 1, that is, | BF(T) | ≤ 1 4. Adjustment of balanced binary tree

Adjust from the node closest to the insertion node

4.1 RR single spin

When the "insert node" (BR) is the right subtree of the right subtree of the "destroyed balance node" (A), that is, RR insertion, RR rotation adjustment is adopted Vacate the left subtree of B and hang it on the right subtree of A, and return B as the root of the current subtree
C

AVLTree RRRotation(AVLTree A){
AVLTree B = A->right;   // B is the right subtree of A
A->right = B->left;    // The left subtree of B hangs on the right subtree of A
B->left = A;   //  A hangs on the left subtree of B
return B;  // At this point, B is the root node
}

4.2 LL single rotation

When the "insertion node" (BL) is the left subtree of the left subtree of the "destroyed balance node" (A), that is, LL insertion, RR rotation adjustment is adopted The left subtree is the root of the current subtree B, and the vacated subtree B is returned to the left subtree
c

AVLTree LLRotation(AVLTree A){
// At this time, the root node is A
AVLTree B = A->left;  // B is the left subtree of A
A->left = B->right;   // The right subtree of B hangs on the left subtree of A
B->right = A;     //  A hangs on the right subtree of B
return B;  // At this point, B is the root node
}

4.3 LR double rotation

When the "insertion node" (CL or CR) is the right subtree of the left subtree of the "destroyed balance node" (A), that is, LR insertion, LR rotation adjustment is adopted AVLTree LRRotation(AVLTree A){
// First RR single rotation
A->left = RRRotation(A->left);
// Re single rotation
return LLRotation(A);
} Conclusion: LR double rotation is viewed from top to bottom, while RR single rotation and LL single rotation are actually viewed from bottom to top

4.4 RL double rotation

When the "insert node" (CL or CR) is the left subtree of the right subtree of the "destroyed balance node" (A), that is, RL insertion, RL rotation adjustment is adopted The basic idea is to convert LL single rotation into RR insertion with B as the root node, and then RR single rotation with A as the root node (LL and RR first)

AVLTree RLRotation(AVLTree A){
// First LL single rotation
A->right = LLRotation(A->right);
// Re RR single rotation
return RRRotation(A);
}

Conclusion: RL double rotation is from top to bottom, while the actual first LL single rotation and then RR single rotation is from bottom to top

Topics: C data structure