C language implementation of the binary tree of data structure

Source: Internet
Author: User
all source code in this blog: GitHub managed Project Address introduction of two fork tree

1, ordinary two-fork tree, complete binary tree, full two fork tree

Binary tree: Up to two Shang trees are called binary trees

Full two fork tree: two fork in the tree all non-leaf nodes are 2 degrees, and leaf nodes are at the same level

Complete binary tree: If a binary tree has the same structure as the M node before the two-fork tree, such a two-fork tree is called a complete binary tree

That is to say, if you remove a number of nodes from right to left, from bottom to top, the remaining structure will constitute a complete binary tree.


In order to store the complete binary tree, can be based on the location of any node to calculate its parent node, child node in the array position (subscript), if the parent node and child nodes exist.

This also shows that a complete binary tree is suitable for using sequential table storage



2, clue two fork Tree

The two-fork list of n nodes contains n+1 (2n-(n-1) =n+1) null pointer field. Using the null pointer field in a binary list, a pointer to a predecessor and subsequent node of a node in some sort of traversal order is stored (this additional pointer is called a "clue").



3, Huffman tree (the best two-fork tree)

Given n weights as n leaf nodes, a binary tree is constructed, and if the length of the weighted path is minimized, the two-fork tree is called the optimal binary tree, also known as Huffman Tree (Huffman). Huffman tree is a tree with the shortest length of weighted path, and the node with larger weights is nearer to the root.



4, binary search (Find, sort) tree

When traversing a two-fork tree, its output is an ordered array

According to the definition of binary sort tree, it is found that the search process has the characteristics of duality and high efficiency.

Disadvantage: The final form of the two-fork sort tree is related to the order of the input data,

For example, the input data [1,2,3,4,5,6,7,8,9], the final form of the two-fork sort tree as shown below


At this point, the binary tree degenerated into a single linked list, search efficiency greatly reduced



5. Balance the two fork tree

In order to overcome the shortcomings of the binary sort tree, people come up with a way to make the left and right subtree of a tree roughly the same height

The famous Soviet scientist G.m Adelson-velsky and E.M Landis in 1962, was named the AVL tree, and the red-black tree



6, AVL tree

The left subtree depth of any node and the depth of the right subtree are not more than 1, and we measure the difference with the balance factor

Equilibrium factor balance of any node (p) = Heigth (P's Zuozi)-height (right subtree of p)

When an AVL tree is inserted and deleted, when the balance factor is =2, it is necessary to adjust the position of the node so that it satisfies the definition of the AVL tree.

On the INSERT, delete operation of the AVL tree, which is then recorded



Summary: We know, in practical applications, we often use the search and sorting operations, which in our various management systems, database systems, operating systems, etc., are very commonly used.

The array's subscript addressing is very rapid, but the computer's memory is limited, so the length of the array is also limited, the actual application of the data is often very large

And finding the worst case of unordered arrays requires traversing the entire array

Later, people put forward a two-point lookup, the binary lookup requires the structure of the array must be orderly. The method of binary search solves the problem of high complexity of common array lookup

The problem with either and an array is that insertions and deletions are more complex, so in a data structure that is more frequent than the deletion and deletions, the array is not considered a priority

The common list is proved unsuitable for searching because of its structural features.

Binary lookup tree is also unsuitable for searching because it may degenerate into a linked list

A hash table is a compromise between an array and a linked list, and its design relies on the design of the hash function, the array cannot be infinitely long, and the linked list is not suitable for searching, so it is also suitable for large-scale search

The process of the AVL tree's rotation is cumbersome, so inserting and deleting it is slow, which is more troublesome to build an AVL tree.

The red-black tree is the tradeoff between the balanced binary tree and the AVL tree, so it is more appropriate. The map and associative arrays in the collection class have high query efficiency, and their underlying implementation is the red-black tree

/*bitree.h*/#ifndef bitree_h #define BITREE_H #include <stdlib.h>/* for node-defined binary tree structure * * typedef struct BITREENODE_ {
        
void *data;/* Storage Data * * * * struct Bitreenode_ *left;/* left child/struct bitreenode_ right child/*right;/*; /* Defines the binary tree structure body/typedef struct BITREE_ {int size;/* storing the number of data */INT (*compare) (const void *key1,const void *key2); * Reserved

An interface/void (*destroy) (void *data),/* encapsulated destructor, which is to release the data space */Bitreenode *root;/* A pointer to the root node * * *}BITREE;
/* Function interface */void Bitree_init (Bitree *tree, Void (*destroy) (void *data));
void Bitree_destroy (Bitree *tree);
int Bitree_ins_left (bitree *tree,bitreenode *node,const void *data);
int Bitree_ins_right (Bitree * tree, Bitreenode * node, const void * data);
void Bitree_rem_left (Bitree *tree,bitreenode *node);
void Bitree_rem_right (Bitree * tree, Bitreenode * node);

int Bitree_merge (bitree *merge,bitree *left,bitree *right,const void *data);
#define BITREE_SIZE (tree)-> size) #define BITREE_ROOT (tree)-> root)/*node identification is the molecular end of the tree/#define BITREE_IS_EOB (node) = NULL)//Determine if the leaf node/#define BITREE_IS_LEAF (node)-> left = null && (node)->right = null) #define BITREE_DATA (node)->data) #define BITREE_LEFT (node)
 ((node)->left) #define BITREE_RIGHT (node)->right) #endif
/*bitree.c*/#include <stdio.h> #include <stdlib.h> #include <string.h> #include "bitree.h"/* Two fork Tree initialization *
    /void Bitree_init (Bitree * tree, void (* destroy) (void * data)) {tree->size = 0;
    Tree->destroy = Destroy;
    Tree->root = NULL;
return;

    }/* Two fork tree destroy/void Bitree_destroy (Bitree *) {/* Remove all nodes from the two fork tree * * bitree_rem_left (trees, NULL);
    memset (tree,0,sizeof (Bitree);
Return /* Insert a node into a two-fork tree and insert it into the left subtree of the parameter-specific node if the node is empty and the tree is empty, the node is set to root * return successfully returned 0, failed-1/int bitree_ins_left (Bitree * tree
    , Bitreenode * node, const void * data) {Bitreenode *new_node,**position; /* To determine the insertion to that node/if (node = = NULL) {/* When Node==null, description is the root node, but if the tree is not empty, then an error returns -1*/if (Bitree_size) > 0
        ) {return-1;
    /* This means position to the root node/position = &tree->root;
        else {*/* to determine whether the left child of node nodes is an empty/if (Bitree_left (node)!= null) {return-1; } position = &node->left;

    /* Request node Space save data*/if (New_node = (Bitreenode *) malloc (sizeof (bitreenode)) = = NULL) return-1;
    * * Insert the node into the two-fork tree/New_node->data = (void *) data;
    New_node->left = NULL;

    New_node->right = NULL;

    Tree->size + +;
return 0; /* Insert a node into a two-fork tree and insert it into the right subtree of the parameter-specific node * If the node is empty and the tree is empty, the node is set to root * return successfully returned 0, failed-1/int bitree_ins_right (Bitree * TR
    EE, Bitreenode * node, const void * data) {Bitreenode *new_node,**position; /* To determine the insertion to that node/if (node = = NULL) {/* When Node==null, description is the root node, but if the tree is not empty, then an error returns -1*/if (Bitree_size) > 0
        ) {return-1;
    /* This means position to the root node/position = &tree->root;
        else {*/* to determine whether the left child of node nodes is an empty/if (Bitree_right (node)!= null) {return-1;

    } position = &node->right; /* Request node Space save data*/if (New_node = (Bitreenode *) malloc (sizeof (bitreenode)) = = NULL) return-1;
    * * Insert the node into the two-fork tree/New_node->data = (void *) data;
    New_node->left = NULL;
    New_node->right = NULL;
    *position = New_node;
    
    Tree->size + +;

return 0; }/* Remove the left child of node nodes if Node=null removes all nodes * No return value/void Bitree_rem_left (Bitree * tree, Bitreenode * node) {Bitreenode
    **position;
    /* When the empty tree Returns/if (bitree_size) = = 0) return;
    /* Decide to delete that node/if (node = NULL) position = &tree->root;
    else Position = &node->left;
        /* Delete this node */if (*position!= NULL) {bitree_rem_left (tree, *position);

        Bitree_rem_right (tree, *position);
    if (Tree->destroy!= NULL) Tree->destroy (*position-> data);
    Free (*position);

    *position = NULL;
    
Tree->size--; /* Remove the right child of the node nodes if Node=null removes all nodes * No return value/void Bitree_rem_right (Bitree * tree, Bitreenode * node) {Bitreenode
    **position; /* Returns */if (BITR) when an empty treeEe_size (tree) = = 0) return;
    /* Decide to delete that node/if (node = NULL) position = &tree->root;
    else Position = &node->right;
        /* Delete this node */if (*position!= NULL) {bitree_rem_left (tree, *position);

        Bitree_rem_right (tree, *position);
    if (Tree->destroy!= NULL) Tree->destroy (*position-> data);
    Free (*position);

    *position = NULL;
    

Tree->size--; /* Merge binary tree */int Bitree_merge (bitree * Merge, Bitree * left, Bitree * right, const void * data) {/* Initialize merger*/BI
    Tree_init (merge, Left->destroy);
        /* How to insert a failure returns -1*/if (Bitree_ins_left (merge, NULL, data)!= 0) {Bitree_destroy (merge);
    return-1;
    } bitree_root (merge)->left = Bitree_root (left);

    Bitree_root (merge)->right = Bitree_root (right);

    Merge->size + + bitree_size (left) + bitree_size (right);
    Left->root = NULL;
    left->size = 0;
  Right->root = NULL;  Right->size = 0;
    
return 0;
 }


Binary Tree header file bistree.h
/*bistree.h*/
#ifndef bistree_h
#define BISTREE_H/

* Defines the balance factor as AVL tree/
#define  avl_lft_heavy               1
#define  avl_balanced                0
#define  avl_rgt_heavy             -1/

* Define AVL tree node/

typedef struct Avlnode_ {
    void *data;
    int hidden;
    int factor;/* Balance factor *
/}avlnode;

/* Defines the binary tree structure body
/typedef struct BISTREE_ {
    int size;/* storing data number *
    /INT (*compare) (const void *key1,const void * Key2);//* Reservation of an interface/
    void (*destroy) (void *data);/* encapsulated destructor, which is to release the data space * * *
    bitreenode *root;/* A pointer to the root node.
} Bistree;

/* Function interface */
void Bistree_init (Bistree *tree, int (*compare) (const void *key1,const void 
                               *key2), Void (*destroy) ( void *data));
void Bistree_destory (Bistree *tree);
int Bistree_insert (bistree *tree,const void *data);
int Bistree_remove (bistree *tree,const void *data);
int Bistree_lookup (Bistree *tree,void **data);
#define  bistree_size (tree)  (->size)


#endif


Binary Tree main file bistree.c (rotate)
/*bistree.c*/#include <stdlib.h> #include <string.h> #include "bistree.h" #include "bitree.h"/* L/Static
    void Rotate_left (Bitreenode **node) {Bitreenode *right, grandchild;

    right = Bitree_right (*node); if ((Avlnode *) Bitree_data (right)->factor = = avl_rgt_heavy) {* * RR/bitree_right (*node) = Bitree_le
        ft (right);
        Bitree_left (right) = *node;
        ((Avlnode *) Bitree_data (*node))->factor = avl_balanced;
        ((Avlnode *) Bitree_data (right))->factor = avl_balanced;
        
    *node = right;
        else {/*rl*/grandchild = Bitree_left (right);
        Bitree_left (right) = Bitree_right (grandchild);
        Bitree_right (grandchild) = right;
        Bitree_right (*node) = Bitree_left (grandchild);

        Bitree_left (grandchild) = *node; Switch ((Avlnode *) Bitree_data (grandchild))->factor) {Case avl_lft_heavy: ((Avlnode *) bit
 Ree_data (*node))->factor = avl_balanced;               ((Avlnode *) Bitree_data (right))->factor = Avl_rgt_heavy;
                
            Break
                Case avl_balanced: ((Avlnode *) Bitree_data (*node))->factor = avl_balanced;
                ((Avlnode *) Bitree_data (right))->factor = avl_balanced;
                
            Break
                Case Avl_rgt_heavy: ((Avlnode *) Bitree_data (*node))->factor = Avl_lft_heavy;
                ((Avlnode *) Bitree_data (right))->factor = avl_balanced;
                
            Break
        Default:break;
        } ((Avlnode *) Bitree_data (grandchild))->factor = avl_balanced;
    *node = grandchild;
} return;
 }
/* Right spin/static void Rotata_right (Bitreenode **node) {    Bitreenode *left, grandchild;     left = Bitr


Ee_left (*node);      if ((Avlnode *) Bitree_data (left)->factor = = Avl_lft_heavy) {        * LL/ 
      Bitree_left (*node) = Bitree_right (left);
        Bitree_right (left) = *node;
        ((Avlnode *) Bitree_data (*node))->factor = avl_balanced;
        ((Avlnode *) Bitree_data (left))->factor = avl_balanced;
        *node = left;             } else {/*lr*/        grandchild = Bitree_right (left
);
        Bitree_right (left) = Bitree_left (grandchild);
        bitree_left (grandchild) = left;
        Bitree_left (*node) = Bitree_right (grandchild);


        bitree_right (grandchild) = *node;         Switch ((Avlnode *) bitree_data (grandchild)->factor) {            Case Avl_lft_heavy:                 (Avlnode *) bitree_data (*node)->factor =
Avl_rgt_heavy;
                ((Avlnode *) Bitree_data (left))->factor = avl_balanced;
                break; 
                             Case avl_balanced:
                ((Avlnode *) Bitree_data (*node))->factor = avl_balanced;
                ((Avlnode *) Bitree_data (left))->factor = avl_balanced;
                break;                              Case Avl_rgt_heavy :                 ((Avlnode *) Bitree_data (*node))->factor = avl_balanced;
                ((Avlnode *) Bitree_data (left))->factor = Avl_lft_heavy;
                break;                              default:   &N Bsp
            break; 
       }         ((Avlnode *) Bitree_data (grandchild))->factor = avl_balanced;
        *node = grandchild;
   }     return;
 }

The code in the book is slightly obscure.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.