Tree, binary tree, binary search tree, binary balanced tree, Huffman tree

Basic concepts:

A tree is a finite set of n (n > 0) nodes. When n =O, it is called an empty tree, which is a special case. In any non empty tree, it should meet the following requirements:
1) There is and only one specific node called root.
2) When n > 1, the other nodes can be divided into m (M > 0) disjoint finite sets T1, T2... Tm, in which each set itself is a tree and is called the subtree of the root node.

Properties:

Node level (depth) - count from top to bottom
Height of node - from bottom to top
Height (depth) of the tree - how many layers in total
Degree of node -- how many children (branches)
Degree of tree -- the maximum degree of each node

forest. Forest is a collection of M (m ≥ 0) disjoint trees

Binary tree

A binary tree is a finite set of n (n ≥ 0) nodes: 1 or an empty binary tree, that is, n = 0.
2 or consists of a root node and two disjoint left and right subtrees called roots. The left subtree and the right subtree are a binary tree respectively.

realization

Tree.h
#ifndef _TREE_H_
#define _TREE_H_
#define Maxszie 100
//Sequential storage

template<class T>
class STreeNode
{
public:
    STreeNode()
    {
        isEmpty = 1;
    }
    ~STreeNode()
    {
        isEmpty = 1;
    }
    T value;
    bool isEmpty;
};

template<class T>
class STree : public STreeNode<T>
{
public:
    void inTree(int n);
    void PreOrder(const int now);
    void InOrder(const int now);
    void PosOrder(const int now);
    void LevelOrder(const int now);
    void Print();

private:
    STreeNode<T> t[Maxszie];
    int size;
};


// Chain type

template<class T>
class LTreeNode
{
public:
    LTreeNode(const T &x, LTreeNode<T> *l = NULL, LTreeNode<T> *r = NULL) : value(x), lchild(l), rchild(r){};

public:
    T &getValue() {return this->value};
    LTreeNode<T> *getLeft() {return this->lchild};
    LTreeNode<T> *getRight() {return this->rchild};
    void setLeft(LTreeNode<T> *l) {this->lchild = l};
    void setRight(LTreeNode<T> *r) {this->rchild = r};
    void setValue(const T &x) {this->value = x};

private:
    T value;
    LTreeNode<T> *lchild, *rchild;
};

template<class T>
class LTree
{
public:
    LTree(LTreeNode<T> *t) : root(t){};
    ~LTree() { del(root); };

public:
    //Search the parent node of node p in the subtree with node t as the root node
	LTreeNode<T> * getFather(LTreeNode<T> *t, LTreeNode<T> *p);
	//Find the node whose data field is item in the subtree with node t as the root node
	LTreeNode<T> * find(LTreeNode<T> *t, const T &item);
	//Delete node t and its left and right subtrees from the tree (including some column update operations after deletion)
	void delSubTree(LTreeNode<T> *t);
	//Delete node t and its left and right subtrees
	void del(LTreeNode<T> *t);
	//First, traverse the root and output the subtree with node t as the root node
	void preOrder(LTreeNode<T> *t);
	//Traverse and output the subtree with node t as the root node
	void InOrder(LTreeNode<T> *t);
	//The latter root traverses and outputs the subtree with node t as the root node
	void PostOrder(LTreeNode<T> *t);
	//The hierarchy traverses and outputs the subtree with node t as the root node
	void levelOrder(LTreeNode<T> *t);
	//Create binary tree
	void createBinTree(T stop);
	//Create a binary tree and return the root node of the binary tree
	LTreeNode<T> * create();
	LTreeNode<T> * getRoot() { return root; }
	void setRoot(LTreeNode<T> * t) { root = t; }
	T getStop() { return stop; }
	void setStop(const T& stop) { this->stop = stop; }
	bool isEmpty() { return root == NULL ? true : false; }

private:
    LTreeNode<T> *root;
    T stop; // Enter stop to stop
};


#endif //_TREE_H_
Tree.cpp
#include "Tree.h"
#include <iostream>
#include <queue>

template<class T>
void STree<T>::inTree(int n)
{
    if(n >= Maxszie)
    {
        std::cout << "can't in\n";
        return ;
    }
    for(int i = 1; i <= n; ++ i)
    {
        std::cin >> t[i].value;
        t[i].isEmpty = 0;
    }
    size = n;
}

template<class T>
void STree<T>::Print()
{
    for(int i = 1; i <= size; ++ i)
    {
        std::cout << t[i].value << " ";
    }
    std::cout << std::endl;
}

template<class T>
void STree<T>::PreOrder(const int now)
{
    if(t[now].isEmpty == 0)
    {
        std::cout << t[now].value << " ";
        PreOrder(now*2);
        PreOrder(now*2+1);
    }
}

template<class T>
void STree<T>::InOrder(const int now)
{
    if(t[now].isEmpty == 0)
    {       
        InOrder(now*2);
        std::cout << t[now].value << " ";
        InOrder(now*2+1);
    }
}

template<class T>
void STree<T>::PosOrder(const int now)
{
    if(t[now].isEmpty == 0)
    {
        PosOrder(now*2);
        PosOrder(now*2+1);
        std::cout << t[now].value << " ";
    }
}

template<class T>
void STree<T>::LevelOrder(const int now)
{
    std::queue<int> q;
    q.push(now);
    while(!q.empty())
    {
        int i = q.front();
        q.pop();
        int l = i*2;
        int r = i*2+1;
        if(t[l].isEmpty == 0)
        {
            q.push(l);
        }
        if(t[r].isEmpty == 0)
        {
            q.push(r);
        }
        std::cout << t[i].value << " ";
    }
    std::cout << std::endl;
}

/*
                       .::::.
                     .::::::::.
                    :::::::::::  FUCK YOU
                ..:::::::::::'
              '::::::::::::'
                .::::::::::
           '::::::::::::::..
                ..::::::::::::.
              ``::::::::::::::::
               ::::``:::::::::'        .:::.
              ::::'   ':::::'       .::::::::.
            .::::'      ::::     .:::::::'::::.
           .:::'       :::::  .:::::::::' ':::::.
          .::'        :::::.:::::::::'      ':::::.
         .::'         ::::::::::::::'         ``::::.
     ...:::           ::::::::::::'              ``::.
    ````':.          ':::::::::'                  ::::..
                       '.:::::'                    ':'````..
*/

template<class T>
LTreeNode<T> *LTree<T>::getFather(LTreeNode<T> *t, LTreeNode<T> *p)
{
    LTreeNode<T> *father;
    if(t == NULL || p == NULL)
    {
        return NULL;
    }
    if(t->getLeft() == p || t->getRight() == p)
        return t;
    if((father = getFather(t->getLeft(), p)) != NULL)
        return father;
    else 
        return getFather(t->getRight(), p);
}

template<class T>
LTreeNode<T> *LTree<T>::find(LTreeNode<T> *t, const T &item)
{
    LTreeNode<T> *target;
    if(t == NULL)
        return NULL;
    if(t->getValue() == T)
        return t;
    if((target = find(t->getLeft(), item)) != NULL)
        return target;
    else 
        return find(t->getRight(), item);
}

template<class T>
void LTree<T>::delSubTree(LTreeNode<T> *t)
{
    if(t == NULL)
        return ;
    if(t == root)
    {
        del(t);
        root = NULL;
        return ;
    }
    LTreeNode<T> *p = t, *q;
    q = getFather(root, t);
    if(q)
    {
        if(q->getLeft() == t)
            q->setLeft(NULL);
        if(q->getRight() == t)
            q->setRight(NULL);
    }
    del(p);
}

template<class T>
void LTree<T>::del(LTreeNode<T> *t)
{
    if(t != NULL)
    {
        del(t->getLeft());
        del(t->getRight());
        delete t;
    }
}

template<class T>
void LTree<T>::preOrder(LTreeNode<T> *t)
{
    if(t != NULL)
    {
        std::cout << t->getValue() << " ";
        preOrder(t->getLeft());
        preOrder(t->getRight());
    }
}

template<class T>
void LTree<T>::InOrder(LTreeNode<T> *t)
{
    if(t != NULL)
    {
        InOrder(t->getLeft());
        std::cout << t->getValue() << " ";
        InOrder(t->getRight());
    }
}

template<class T>
void LTree<T>::PostOrder(LTreeNode<T> *t)
{
    if(t != NULL)
    {
        PostOrder(t->getLeft());
        PostOrder(t->getRight());
        std::cout << t->getValue() << " ";
    }
}

template<class T>
void LTree<T>::levelOrder(LTreeNode<T> *t)
{
    if(t == NULL)
        return ;
    LTreeNode<T> *cur;
    std::queue<LTreeNode<T>* > q;
    q.push(t);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        std::cout << cur->getValue() << " ";
        if(cur->getLeft() != NULL)
            q.push(cur->getLeft());
        if(cur->getRight() != NULL)
            q.push(cur->getRight());
    }
    std::cout << std::endl;
}

template<class T>
void LTree<T>::createBinTree(T stop)
{
    setStop(stop);
    root = create();
}

template<class T>
LTreeNode<T> *LTree<T>::create()
{
    LTreeNode<T> *t, *t1, *t2;
	T item;
	std::cin >> item;
	if (item == stop) {
		t = NULL;
		return t;
	}
	else {
		if (!(t = new LTreeNode<T>(item, NULL, NULL)))
			return NULL;
		t1=create();
		t->setLeft(t1);
		t2 = create();
		t->setRight(t2);
		return t;
	}
}

Binary search tree BST(Binary Search Tree)

definition

  1. If the left subtree of any node is not empty, the values of all nodes on the left subtree are less than those of its root node;
  2. If the right subtree of any node is not empty, the values of all nodes on the right subtree are greater than those of its root node;
  3. The left and right subtrees of any node are also binary search trees.
  4. There are no nodes with equal key values.

realization

statement

//Binary search tree
template<class T>
class BSTNode
{
public:
    BSTNode(const T &x) : data(x), lchild(NULL), rchild(NULL), parent(NULL){};
    ~BSTNode(){};

public:
    void setData(const T &x) { this->data = x; };
    void setLchild(BSTNode<T> *l) { this->lchild = l; };
    void setRchild(BSTNode<T> *r) { this->rchild = r; };
    void setParent(BSTNode<T> *p) { this->parent = p; };
    BSTNode<T> *getLchild() { return this->lchild; };
    BSTNode<T> *getRchild() { return this->rchild; };
    BSTNode<T> *getParent() { return this->parent; };
    T getData() { return this->data; };

private:
    T data;
    BSTNode<T> *lchild, *rchild, *parent;
};

template<class T>
class BST
{
public:
    BST(const int &s) : root(NULL), size(s){};
    ~BST(){ del(root); std::cout << "Deconstruction" << std::endl; };

public:
    void create_BST();
    BSTNode<T> *getroot();
    void InOrder(BSTNode<T> *t);
    void Insert(BSTNode<T> *t);
    void PreOrder(BSTNode<T> *t);
    void PosOrder(BSTNode<T> *t);
    void LevelOrder(BSTNode<T> *t);
    void del(BSTNode<T> *t);
    BSTNode<T> *search(const T &x);
    T max();
    T min();
    void visit(BSTNode<T> *t);

private:
    BSTNode<T> *root;
    int size = 0;
};

realization

// BST
template<class T>
BSTNode<T> *BST<T>::getroot()
{
    return this->root;
}

template<class T>
void BST<T>::visit(BSTNode<T> *t)
{
    std::cout << t->getData() << " ";
}

template<class T>
void BST<T>::Insert(BSTNode<T> *t)
{
    BSTNode<T> *q = root, *p = NULL;
    while(q != NULL)
    {
        p = q;
        if(t->getData() < q->getData())
            q = q->getLchild();
        else 
            q = q->getRchild();
    }
    t->setParent(p);
    if(p == NULL)
        root = t;
    else if(t->getData() < p->getData())
        p->setLchild(t);
    else 
        p->setRchild(t);
}

template<class T>
void BST<T>::create_BST()
{
    std::cout << "Input your data: ";
    for(int i = 0; i < size; ++ i)
    {
        T d;
        std::cin >> d;
        BSTNode<T> *node = new BSTNode<T>(d);
        Insert(node);
    }
}

template<class T>
void BST<T>::PreOrder(BSTNode<T> *t)
{
    if(t != NULL)
    {
        visit(t);
        PreOrder(t->getLchild());
        PreOrder(t->getRchild());
    }
}

template<class T>
void BST<T>::InOrder(BSTNode<T> *t)
{
    if(t != NULL)
    {
        InOrder(t->getLchild());
        visit(t);
        InOrder(t->getRchild());
    }
}

template<class T>
void BST<T>::PosOrder(BSTNode<T> *t)
{
    if(t != NULL)
    {
        PosOrder(t->getLchild());
        PosOrder(t->getRchild());
        visit(t);
    }
}

template<class T>
void BST<T>::LevelOrder(BSTNode<T> *t)
{
    std::queue<BSTNode<T> *> q;
    q.push(t);
    while(!q.empty())
    {
        BSTNode<T> *p = q.front();
        visit(p);
        if(p->getLchild() != NULL)
            q.push(p->getLchild());
        if(p->getRchild() != NULL)
            q.push(p->getRchild());
        
        q.pop();
    }
}

template<class T>
BSTNode<T> *BST<T>::search(const T &x)
{
    if(root == NULL)
        return NULL;
    
    BSTNode<T> *t = root;
    while(t != NULL && (t->getData() != x))
    {
        if(x < t->getData())
        {
            t = t->getLchild();
        }
        else t = t->getRchild();
    }
    return t;
}

template<class T>
T BST<T>::max()
{
    BSTNode<T> *t = root;
    while(t->getRchild() != NULL)
    {
        t = t->getRchild();
    }
    return t->getData();
}

template<class T>
T BST<T>::min()
{
    BSTNode<T> *t = root;
    while(t->getLchild() != NULL)
    {
        t = t->getLchild();
    }
    return t->getData();
}

template<class T>
void BST<T>::del(BSTNode<T> *t)
{
    if(t != NULL)
    {
        del(t->getLchild());
        del(t->getRchild());
        delete t;
    }
}

Balanced binary tree AVL

Balanced binary tree (AVL tree for short) - the height difference between the left and right subtrees of any node of the tree shall not exceed 1.
Node balance factor = left subtree height - right subtree height.
The absolute value of balance factor of balanced binary tree shall not be greater than 1

Adjust minimum unbalanced subtree

  1. Insert the left subtree of the left son of a once
  2. Insert LR into the right subtree of the left son of a once
  3. Insert the left subtree of the right son of a once
  4. Insert the right subtree of the right son of a once

LL

1)LL balanced rotation (right single rotation). Because A new node is inserted into the left subtree (L) of the left child (L) of node A, the balance factor of A increases from 1 to 2, resulting in the loss of balance of the subtree with A as the root, requiring A right rotation operation. Rotate the left child B of A to the right to replace A as the root node, rotate node A to the right and down to become the root node of the right subtree of B, and the original right subtree of B is the left subtree of node A.

RR

2) RR balanced rotation (left single rotation). Due to the right subtree of the right child (R) at node a ® A new node is inserted on the, and the balance factor of a is reduced from - 1 to - 2, resulting in the imbalance of the subtree with a as the root, which requires a left rotation operation. Rotate the right child B of a to the left to replace a as the root node, rotate node a to the left and down to become the root node of the left subtree of B, and the original left subtree of B is the right subtree of node a

LR

3)LR balanced rotation (double rotation from left to right). Since a new node is inserted into the right subtree (R) of a's left child (L), the balance factor of a increases from 1 to 2, resulting in the loss of balance of the subtree with a as the root. Two rotation operations are required, first left rotation and then right rotation. First, rotate the root node c of the left child of node A and the right subtree of node B to the left, and then rotate the c node to the right to the position of node a

RL

4) RL balanced rotation (double rotation from right to left). Since a new node is inserted into the left subtree (L) of the right child (R) of a, the balance factor of a is reduced from - 1 to - 2, resulting in the loss of balance of the subtree with a as the root. Two rotation operations are required, first right rotation and then left rotation. First, rotate the root node c of the right child of node A and the left subtree of node B upward to the right to the position of node B, and then rotate the c node upward to the left to the position of node a

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-dfv0TgfT-1630811348339)(./images/1.jpg)]

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-wdu427xb-1630811341) (. / images / 2. JPG)]

AVL.h

//Binary balanced tree
template<class T>
class AVLNode
{
public:
    AVLNode(const T &x) : data(x), lchild(NULL), rchild(NULL) {};
    ~AVLNode(){};

public:
    void setData(const T &x) { this->data = x; };
    void setLchild(AVLNode<T> *l) { this->lchild = l; };
    void setRchild(AVLNode<T> *r) { this->rchild = r; };
    AVLNode<T> *getLchild() { return this->lchild; };
    AVLNode<T> *getRchild() { return this->rchild; };
    T getData() { return this->data; };

private:
    T data;
    AVLNode<T> *lchild, *rchild;
};

template<class T>
class AVL
{
    typedef AVLNode<T> AVLnode;
public:
    AVL(){ avlroot = NULL; };
    ~AVL() { __deleteTree(avlroot); };
    AVL(const T *arr, int len);
    AVL(const std::vector<T> &);
    AVLnode *getAvlroot() { return this->avlroot; };
    void setAvlroot(AVLnode *avl) { this->avlroot = avl; };

public:
    void InorderTraversal(); //Traversing external interfaces in middle order
    void InorderTraversal(std::vector<T> &); //Medium order traversal external interface overload 2
    bool Delete(const T &x); //Delete external interface of node
    bool Insert(const T &x); //Insert the external interface of the node
    bool IsEmpty(){ return avlroot == NULL; } //Tree empty?
    bool search(const T &x); //Query external interface

private:
    int __height(AVLnode *root);//Find the height of the tree
    int __diff(AVLnode *root);//Height difference (balance factor)
    //Single rotation
    AVLnode *__ll_Rotation(AVLnode *root);//left-left rotation
    AVLnode *__rr_Rotation(AVLnode *root);//right-right rotation
    //Double rotation
    AVLnode *__lr_Rotation(AVLnode *root);//left-right rotation
    AVLnode *__rl_Rotation(AVLnode *root);//right-left rotation
    AVLnode *__Balance(AVLnode *root);//Balance operation
    AVLnode *__Insert(AVLnode *root);//Internal implementation of insert
    //Two overloads of middle order traversal
    void __InorderTraversal(AVLnode *root);//output
    void __InorderTraversal(AVLnode *root, std::vector<T> &vec);//Result saving
    bool __isLeaf(AVLnode* const &);//Determine whether it is a leaf node
    bool __isNodeWithTwoChild(AVLnode * const &);//Determine whether there are two children
    AVLnode *__search(AVLnode *const root, const T &x);//Internal implementation of lookup
    void __deleteTree(AVLnode *root);//Delete all nodes of the tree
    AVLnode *__Delete(AVLnode *root, const T &x);//Delete node
    AVLnode *__treeMin(AVLnode *root);//Find the minimum of the current root node (all the way to the left)
    AVLnode *__treeMax(AVLnode *root);//Find the maximum of the current root node (all the way to the right)

private:
    AVLnode *avlroot;
};

AVL.cpp

// AVL
template<class T>
AVL<T>::AVL(const T *arr, int len)
{
    avlroot = NULL;
    for(int i = 0; i < len; ++ i)
        Insert(*(arr+i));
}

template<class T>
AVL<T>::AVL(const std::vector<T> &vec)
{
    avlroot = NULL;
    for(int i = 0; i < (int)vec.size(); ++ i)
        Insert(vec[i]);
}

template<class T>
void AVL<T>::__deleteTree(AVLnode *root)
{
    if(root == NULL)
        return ;
    __deleteTree(root->getLchild());
    __deleteTree(root->getRchild());
    delete root;
    root = NULL;
    return ;
}

template<class T>
AVLNode<T> *AVL<T>::__Insert(AVLnode *root)
{
    // if(root == NULL)
    // {
    //     if(root == avlroot)
    //         std::cout << "hello\n";
    //     // if(avlroot == NULL)
    //     // {
    //     //     AVLNode<T> *newnode = new AVLNode<T>(x);
    //     //     avlroot = newnode;
    //     //     return avlroot;
    //     // }
    //     AVLNode<T> *newnode = new AVLNode<T>(x);
    //     root = newnode;
    //     if(root == avlroot)
    //         std::cout << "hello\n";
    //     return root;
    // }
    // else if(x < root->getData())
    // {
    //     AVLnode *p = root->getLchild();
    //     root->setLchild( __Insert(p, x) );
    //     root = __Balance(root);
    // }
    // else if(x > root->getData())
    // {
    //     AVLnode *p = root->getRchild();
    //     root->setRchild( __Insert(p, x) );
    //     root = __Balance(root);
    // }
    // return root;
    AVLnode *q = avlroot, *p = NULL;
    while(q != NULL)
    {
        p = q;
        if(root->getData() < q->getData())
            q = q->getLchild();
        else if(root->getData() > q->getData())
            q = q->getRchild();
        else 
            return NULL;
    }
    if(p == NULL)
    {    
        avlroot = root;
        return root;
    }    
    else if(root->getData() < p->getData())
        p->setLchild(root);
    else if(root->getData() > p->getData())
        p->setRchild(root);


    q = avlroot;
    AVLnode *t;

    while(q != NULL)
    {
        t = q;
        if(q == p)
        {
            break;
        }
        if(root->getData() < q->getData())
        {
            q = q->getLchild();
            if(q == p)
            {
                break;
            }
        }
        else
        {
            q = q->getRchild();
            if(q == p)
            {
                break;
            }
        }
    }
    __Balance(t);
    return root;
}

template<class T>
bool AVL<T>::Insert(const T &x)
{
    AVLnode *t = new AVLNode<T>(x);
    return __Insert(t) == NULL? false : true;
}

template<class T>
int AVL<T>::__height(AVLnode *root)
{
    if(root == NULL)
        return 0;
    return std::max(__height(root->getLchild()), __height(root->getRchild()))+1;
}

template<class T>
int AVL<T>::__diff(AVLnode *root)
{
    int fctor = __height(root->getLchild()) - __height(root->getRchild());
    return fctor;
}

template<class T>
AVLNode<T> *AVL<T>::__Balance(AVLnode *root)
{
    int fctor = __diff(root);
    if(fctor > 1) //left higer than right
    {
        if(__diff(root->getLchild()) > 0)
            root = __ll_Rotation(root);
        else
            root = __lr_Rotation(root);
    }
    else if(fctor < -1) //right higer than left
    {
        if(__diff(root->getRchild()) > 0)
            root = __rl_Rotation(root);
        else 
            root = __rr_Rotation(root);
    }
    return root;
}

template<class T>
AVLNode<T> *AVL<T>::__ll_Rotation(AVLnode *root)
{
    AVLnode *tmp;
    tmp = root->getLchild();
    root->setLchild(tmp->getRchild());
    tmp->setRchild(root);
    if(root == avlroot)
        avlroot = tmp;
    return tmp;
}

template<class T>
AVLNode<T> *AVL<T>::__rr_Rotation(AVLnode *root)
{
    AVLnode *tmp;
    tmp = root->getRchild();
    root->setRchild(tmp->getLchild());
    tmp->setLchild(root);
    if(root == avlroot)
        avlroot = tmp;
    return tmp;
}

template<class T>
AVLNode<T> *AVL<T>::__lr_Rotation(AVLnode *root)
{
    AVLnode *tmp;
    tmp = root->getLchild();
    root->setLchild(__rr_Rotation(tmp));
    return __ll_Rotation(root);
}

template<class T>
AVLNode<T> *AVL<T>::__rl_Rotation(AVLnode *root)
{
    AVLnode *tmp;
    tmp = root->getRchild();
    root->setRchild(__ll_Rotation(tmp));
    return __rr_Rotation(root);
}

template<class T>
AVLNode<T> *AVL<T>::__Delete(AVLnode *root, const T &x)
{
    if(root == NULL)
        return NULL;
    if(!search(x))
    {
        std::cerr << "Delete error, key not find" << std::endl;
        return root;
    }

    if(x == root->getData())
    {
        if(__isNodeWithTwoChild(root)) //There are two children
        {
            if(__diff(root) > 0)
            {
                root->setData(__treeMax(root->getLchild())->getData());
                root->setLchild(__Delete(root->getLchild(), root->getData()));
            }
            else
            {
                root->setData(__treeMin(root->getRchild())->getData());
                root->setRchild(__Delete(root->getRchild(), root->getData()));
            }
        }
        else //Have a child, merge with leaves
        {
            AVLnode *tmp = root;
            root = (root->getLchild()) ? (root->getLchild()) : (root->getRchild());
            delete tmp;
            tmp = NULL;
        }
    }
    else if(x < root->getData()) //Delete left
    {
        root->setLchild(__Delete(root->getLchild(), x));
        if(__diff(root) < -1)
        {
            if(__diff(root->getLchild()) > 0)
                root = __rl_Rotation(root);
            else 
                root = __rr_Rotation(root);
        }
    }
    else
    {
        root->setRchild(__Delete(root->getRchild(), x));
        if(__diff(root) > 1)
        {
            if(__diff(root->getLchild()) > 0)
                root = __lr_Rotation(root);
            else 
                root = __ll_Rotation(root);
        }
    }
    return root;
}

template<class T>
bool AVL<T>::Delete(const T &x)
{
    return __Delete(avlroot, x) == NULL? false : true;
}

template<class T>
AVLNode<T> *AVL<T>::__search(AVLnode *root, const T &x)
{
    if(root == NULL)
        return NULL;
    if(x == root->getData())
        return root;
    else if(x < root->getData())
        return __search(root->getLchild(), x);
    else
        return __search(root->getRchild(), x);
}

template<class T>
bool AVL<T>::search(const T &x)
{
    return __search(avlroot, x) == NULL? false:true;
}

template<class T>
void AVL<T>::__InorderTraversal(AVLnode *root)
{
    if(root == NULL)
        return ;
    __InorderTraversal(root->getLchild());
    std::cout << root->getData() << " ";
    __InorderTraversal(root->getRchild());
}

template<class T>
void AVL<T>::__InorderTraversal(AVLnode *root, std::vector<T> &vec)
{
    if(root == NULL)
        return ;
    __InorderTraversal(root->getLchild(), vec);
    vec.push_back(root->getData());
    __InorderTraversal(root->getRchild(), vec);
}

template<class T>
void AVL<T>::InorderTraversal()
{
    __InorderTraversal(avlroot);
}

template<class T>
void AVL<T>::InorderTraversal(std::vector<T> &vec)
{
    __InorderTraversal(avlroot, vec);
}

template<class T>
bool AVL<T>::__isLeaf(AVLnode *const &root)
{
    if(root->getLchild() == NULL && root->getRchild() == NULL)
        return true;
    return false;
}

template<class T>
bool AVL<T>::__isNodeWithTwoChild(AVLnode *const &root)
{
    if(root->getLchild() != NULL && root->getRchild() != NULL)
        return true;
    return false;
}

template<class T>
AVLNode<T> *AVL<T>::__treeMax(AVLnode *root)
{
    while(root->getRchild() != NULL)
        root = root->getRchild();
    return root;
}

template<class T>
AVLNode<T> *AVL<T>::__treeMin(AVLnode *root)
{
    while(root->getLchild() != NULL)
        root = root->getLchild();
    return root;
}

Huffman tree

Node weight: a value with some practical meaning (e.g. indicating the importance of nodes, etc.)
Weighted path length of a node: the product of the path length (number of sides) from the root of the tree to the node and the weight of the node
Weighted path length of tree: the sum of weighted path lengths of all leaf nodes in the tree (WPL, Weighted Path Length)

Among the binary trees with n weighted leaf nodes, the binary tree with the smallest weighted path length (WPL) is called Huffman tree, also known as optimal binary tree

HUFFMAN.h

//Huffman tree 
template<class T>   
class HfNode
{
public:
    HfNode() : lchild(NULL), rchild(NULL){};
    HfNode(const int &w) : weight(w), lchild(NULL), rchild(NULL){};
    HfNode(const HfNode<T> &h);
    bool operator<(const HfNode<T> &h) const;

public:
    int weight, idx;
    HfNode<T> *lchild, *rchild;
};

template<class T>
class Huffman
{
public:
    Huffman(const T &sa);
    ~Huffman(){ __del(hfroot); }

public:
    bool IsLeaf(HfNode<T>* t); //Judge whether the node is a leaf node
	void GetFreq(std::vector<int> &des);//Gets the current weight array
	void BuildTree();//Build a Huffman tree
	void BuildCode();//The coding table is constructed according to Huffman tree
	void GetCodeList();//Traverse the code table and the code corresponding to the code table
 
	//Preorder traversal and inorder traversal are to determine whether the shape of Huffman tree is correct
	void PreOrder();
	void InOrder();
 
	std::string Expend(const std::string &des);//decompression 
	std::string Compress(const std::string &des);//compress

private:
    void __del(HfNode<T> *t);
    void __build(HfNode<T> *t, T x);
    void __PreOrder(HfNode<T> *t);
    void __InOrder(HfNode<T> *t);

private:
    HfNode<T> *hfroot;
    std::vector<int> freq; //Weight array
    std::vector<T> st; //Coding table
    std::unordered_map<T, std::string> m; //key is the character of the code table
};

HUFFMAN.cpp

template<class T>
HfNode<T>::HfNode(const HfNode<T> &h)
{
    this->idx = h.idx;
    this->weight = h.weight;
    if(h.lchild != NULL)
    {
        this->lchild = new HfNode<T>();
        *this->lchild = *(h.lchild);
    }
    else 
        this->lchild = NULL;
    if(h.rchild != NULL)
    {
        this->rchild = new HfNode<T>();
        *this->rchild = *(h.rchild);
    }
    else 
        this->rchild = NULL;
}

template<class T>
bool HfNode<T>::operator<(const HfNode<T> &h) const
{
    return this->weight < h.weight;
}

template<class T>
Huffman<T>::Huffman(const T &sa)
{
    int len = sa.size();
    if(len == 0)
    {
        std::cout << "please input again" << std::endl;
        exit(-1);
    }
    std::unordered_map<T, int> mymap;
    for(int i = 0; i < len; ++ i)
    {
        if(mymap.find(sa[i]) == mymap.end())
            mymap[sa[i]] = 1;
        else 
            mymap[sa[i]] += 1;
    }

    for(const auto& t : mymap)
    {
        st.push_back(t.first);
        freq.push_back(t.second);
    }
}

template<class T>
bool Huffman<T>::IsLeaf(HfNode<T>* t)
{
    if(t == NULL)
        return false;
    if(t->lchild == NULL && t->rchild == NULL)
        return true;
    else 
        return false;
}

template<class T>
void Huffman<T>::GetFreq(std::vector<int> &des)
{
    for(int i = 0; i < freq.size(); ++ i)
        des.push_back(freq[i]);
}

template<class T>
void Huffman<T>::BuildTree()
{
    std::priority_queue<HfNode<T> > myqueue;
    for(int i = 0; i < freq.size(); ++ i)
    {
        HfNode<T> *tmp = new HfNode<T>(freq[i]);
        tmp->idx = i;
        myqueue.push(*tmp);
    }
    while(myqueue.size() > 1)
    {
        HfNode<T> left = myqueue.top();
		myqueue.pop();
		HfNode<T> right = myqueue.top();
		myqueue.pop();
		HfNode<T>* parent = new HfNode<T>(left.weight + right.weight);
		parent->idx = -1;
		parent->lchild = &left;
		parent->rchild = &right;
		myqueue.push(*parent);
    }
    hfroot = new HfNode<T>();
    *hfroot = myqueue.top();
    myqueue.pop();
}

template<class T>
void Huffman<T>::BuildCode()
{
    if(hfroot == NULL)
        return ;
    T tmp;
    tmp.clear();
    __build(hfroot, tmp);
}

template<class T>
void Huffman<T>::GetCodeList()
{
    for(const auto& t : m)
    {
        std::cout << t.first << " " << t.second << "\n";
    }
}

template<class T>
void Huffman<T>::PreOrder()
{
    if(hfroot == NULL)
        return ;
    __PreOrder(hfroot);
}

template<class T>
void Huffman<T>::InOrder()
{
    if(hfroot == NULL)
        return ;
    __InOrder(hfroot);
}

template<class T>
std::string Huffman<T>::Expend(const std::string &des)
{
    std::string res;
	int i(0), n(des.size());
	HfNode<T>* temp = new HfNode<T>();
	temp = hfroot;
	while (i < n) {	
		if (des[i]=='0')
		{
			temp = temp->lchild;
			i++;
			if (IsLeaf(temp)) {
				res += st[temp->idx];
				temp = hfroot;
				continue;
			}
		}
		if (des[i] == '1')
		{
			temp = temp->rchild;
			i++;
			if (IsLeaf(temp)) {
				res += st[temp->idx];
				temp = hfroot;
				continue;
			}
		}
	}
	return res;
}

template<class T>

std::string Huffman<T>::Compress(const std::string& des)
{
	std::string res;
	for (int i = 0; i < des.length(); ++i) {
		if (des[i] == '\n' || des[i]==' ')
			continue;
		res += m[des[i]];
	}	
	return res;
}

template<class T>
void Huffman<T>::__PreOrder(HfNode<T>* t)
{
	if (t == NULL) return;
	std::cout << t->idx << " : " << t->weight << std::endl;
	_PreOrder(t->lchild);
	_PreOrder(t->rchild);
}
 
template<class T>
void Huffman<T>::__InOrder(HfNode<T>* t)
{
	if (t == NULL) return;
	_InOrder(t->lchild);
	std::cout << t->idx << " : " << t->weight << std::endl;
	_InOrder(t->rchild);
}
 
template<class T>
void Huffman<T>::__del(HfNode<T>* t)
{
	if (t == nullptr) 
		return;
	if (t->lchild) 
		__del(t->lchild);
	if (t->rchild) 
		__del(t->rchild);
}

template<class T>
void Huffman<T>::__build(HfNode<T> *t, T x)
{
    if (IsLeaf(t) && t->idx >= 0) 
    {
		std::cout << x << "    ";
		m[st[t->idx]] = x;
		return;
	}
	if(t->lchild) __build(t->lchild, x + '0');
	if(t->rchild) __build(t->rchild, x + '1');
}

Keywords: data structure

Added by x_maras on Thu, 16 Dec 2021 07:42:14 +0200