可以插入重复数据的AVL树模板实现

@todo

插入重复Key之后的处理还没做, 应该返回一个迭代器.

测试代码

/// @file exam_x_x.cpp
/// @brief exam_2
/**
* 编写表达式2叉树(前序,中序,后序)的非递归实现
提示 : 用栈实现, 模拟的方法: 先用递归实现, 单步跟一遍, 看栈上数据的变化, 再用栈模拟.
*/

#include <iostream>
#include <limits>

#include "LsTree.h"
using namespace std;

#define LINE "----------------------------------------------------------------------"

void clear_cin();
void fnTestAvl(); ///< 自定义插入结点
void fnTestAvlInsert(); ///< 自动插入有序结点
void fnTestAvlRemove(); ///< test case : remove node
void fnTestAvlRemoveRoot();
void fnTestAvlRemoveNoAnyChild();
void fnTestAvlRemoveOneChild();
void fnTestAvlRemoveTwoChild();

bool fnPrintNode_AsCharValue(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt);
bool fnPrintNode_Basic(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt);
bool fnPrintNode_Detail(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt);

int main(int argc, char** argv, char** envp) {
    // fnTestAvlRemove();

    fnTestAvlInsert();

    // fnTestAvl();
    /** run result
    tree.printTree_DLR:
    - + A / * B - C D - E F G
    tree.printTree_DLR_ex:
    - + A / * B - C D - E F G
    tree.printTree_LDR:
    A + B * C - D / E - F - G
    tree.printTree_LDR_ex:
    A + B * C - D / E - F - G
    tree.printTree_LRD:
    A B C D - * E F - / + G -
    tree.printTree_LRD_ex:
    A B C D - * E F - / + G -
    */

    cout << "END, press any key to quit" << endl;
    clear_cin();
    getchar();

    return 0;
}

void fnTestAvlRemove() {
    fnTestAvlRemoveTwoChild();
    // fnTestAvlRemoveOneChild();
    // fnTestAvlRemoveNoAnyChild();
    // fnTestAvlRemoveRoot();
}

void fnTestAvlRemoveTwoChild() {
    CAvl<char> tree;
    
    /// 删除结点 : 2个孩子
    tree.insert(100);
    tree.insert(80);
    tree.insert(90);
    tree.insert(70);
    tree.insert(75);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
    tree.remove(80);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);

    /// 如果中序遍历看到的节点值是有序的, 就是有序二叉树
    /** run result
    ----------------------------------------------------------------------
    [00323EB0][L3:70] [00323E00][00000000][00323F08]
    [00323F08][L4:75] [00323EB0][00000000][00000000]
    [00323E00][L2:80] [00323DA8][00323EB0][00323E58]
    [00323E58][L3:90] [00323E00][00000000][00000000]
    [00323DA8][L1:100] [00000000][00323E00][00000000]
    ----------------------------------------------------------------------
    [00323EB0][L3:70] [00323E58][00000000][00323F08]
    [00323F08][L4:75] [00323EB0][00000000][00000000]
    [00323E58][L2:90] [00323DA8][00323EB0][00000000]
    [00323DA8][L1:100] [00000000][00323E58][00000000]
    */
}

void fnTestAvlRemoveOneChild() {
    CAvl<char> tree;

    /// 删除结点 : 一个孩子
    tree.insert(100);
    tree.insert(80);
    tree.insert(70);
    tree.insert(75);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
    tree.remove(80);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);

    /**
    ----------------------------------------------------------------------
    [00030FD8][L3:70] [00030F80][00000000][00031030]
    [00031030][L4:75] [00030FD8][00000000][00000000]
    [00030F80][L2:80] [00033DA8][00030FD8][00000000]
    [00033DA8][L1:100] [00000000][00030F80][00000000]
    ----------------------------------------------------------------------
    [00030FD8][L3:70] [00033DA8][00000000][00031030]
    [00031030][L4:75] [00030FD8][00000000][00000000]
    [00033DA8][L1:100] [00000000][00030FD8][00000000]
    */
}

void fnTestAvlRemoveNoAnyChild() {
    CAvl<char> tree;

    /// 删除叶子 : 非根结点
    tree.insert(100);
    tree.insert(80);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
    tree.remove(80);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
}

void fnTestAvlRemoveRoot() {
    CAvl<char> tree;
    
    /// 删除叶子 : 根结点
    tree.insert(100);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
    tree.remove(100);
    printf("%s\n", LINE);
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_Detail);
}

void fnTestAvlInsert() {
    int i = 0;
    int iOffset = 0;
    // CAvl tree;
    CAvl<char> tree1;

    //----------------------------------------------------------------------
    // 建立树 
    //----------------------------------------------------------------------
//     for (i = 10; i > 0; i--) {
//         /// 当插入数据时, 可以测试到右旋
//         /// 当tree析构时, 可以测试到左旋, 左双旋
//         tree.insert(i);
//     }

//     for (i = 0; i < 10; i++) {
//         /// 当插入数据时, 可以测试到左旋
//         tree1.insert(i);
//     }

    /// 测试右双旋
    tree1.insert(6);
    tree1.insert(10);
    tree1.insert(8); ///< 测试右双旋
    tree1.insert(12);
    tree1.insert(11);
    tree1.insert(11);
    tree1.insert(11);
    tree1.insert(11);
    tree1.insert(11);
    tree1.insert(11);
    tree1.remove(11); ///< 测试删除一个节点带2个孩子

    //----------------------------------------------------------------------
    // 遍历树 - 中序打印 
    //----------------------------------------------------------------------
//     printf("%s\n", LINE);
//     printf("tree.TraverseLDR:\n");
//     tree.TraverseLDR(tree.getRootNode(), &fnPrintNode_Basic); ///< 非递归实现
//     printf("\n");
}

void fnTestAvl() {
    //----------------------------------------------------------------------
    // 建立树 
    //----------------------------------------------------------------------
    // A + B*(C-D)/(E-F) - G
    CAvl<char> tree;
    CAvlNode<char>* pRootNode = NULL;
    CAvlNode<char>* pNodeCur = NULL;
    CAvlNode<char>* pNodeTmp1 = NULL;
    CAvlNode<char>* pNodeTmp2 = NULL;
    CAvlNode<char>* pNodeTmp3 = NULL;
    CAvlNode<char>* pNodeTmp4 = NULL;
    CAvlNode<char>* pNodeTmp5 = NULL;

    // C-D
    pNodeTmp1 = tree.MakeNewNode('-');
    tree.insertNode(pNodeTmp1, NODE_LEFT, 'C');
    tree.insertNode(pNodeTmp1, NODE_RIGHT, 'D');

    // E-F 
    pNodeTmp2 = tree.MakeNewNode('-');
    tree.insertNode(pNodeTmp2, NODE_LEFT, 'E');
    tree.insertNode(pNodeTmp2, NODE_RIGHT, 'F');

    // B*(C-D)
    pNodeTmp3 = tree.MakeNewNode('*');
    tree.insertNode(pNodeTmp3, NODE_LEFT, 'B');
    tree.insertNode(pNodeTmp3, NODE_RIGHT, pNodeTmp1);

    // B*(C-D)/(E-F)
    pNodeTmp4 = tree.MakeNewNode('/');
    tree.insertNode(pNodeTmp4, NODE_LEFT, pNodeTmp3);
    tree.insertNode(pNodeTmp4, NODE_RIGHT, pNodeTmp2);

    // A + B*(C-D)/(E-F)
    pNodeTmp5 = tree.MakeNewNode('+');
    tree.insertNode(pNodeTmp5, NODE_LEFT, 'A');
    tree.insertNode(pNodeTmp5, NODE_RIGHT, pNodeTmp4);

    // A + B*(C-D)/(E-F) - G
    pRootNode = tree.insertRootNode('-');
    tree.insertNode(pRootNode, NODE_LEFT, pNodeTmp5);
    tree.insertNode(pRootNode, NODE_RIGHT, 'G');

    //----------------------------------------------------------------------
    // 遍历树 - 前序打印 ok
    //----------------------------------------------------------------------
    printf("tree.TraverseDLR:\n");
    tree.TraverseDLR(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现
    printf("\n");

    //----------------------------------------------------------------------
    // 遍历树 - 中序打印 
    //----------------------------------------------------------------------
    // A + B * C - D / E - F - G
    printf("tree.TraverseLDR:\n");
    tree.TraverseLDR(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现
    printf("\n");

    //----------------------------------------------------------------------
    // 遍历树 - 逆序打印 ok
    //----------------------------------------------------------------------
    // A B C D - * E F - / + G -
    printf("tree.TraverseLRD:\n");
    tree.TraverseLRD(tree.getRoot(), &fnPrintNode_AsCharValue); ///< 非递归实现
    printf("\n");

    // A + B*(C-D)/(E-F) - G
    // 后序遍历表达式的模拟计算
    // A B C D - * E F - / + G -
    // A B (C-D) * E F - / + G -
    // A B*(C-D) E F - / + G -
    // A B*(C-D) (E-F) / + G -
    // A B*(C-D)/(E-F) + G -
    // A+B*(C-D)/(E-F) G -
    // A+B*(C-D)/(E-F)-G
}   

bool fnPrintNode_AsCharValue(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) {
    if (NULL != pNodeOpt)
        printf("%c ", (char)pNodeOpt->m_Element);
    else 
        printf("         ");
    
    return true;
}

bool fnPrintNode_Basic(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) {
    if (NULL != pNodeOpt)
        printf("[L%d:%d] ", pNodeOpt->m_BF, pNodeOpt->m_Element);
    else 
        printf("         ");

    return true;
}

bool fnPrintNode_Detail(CAvl<char>* pTree, const CAvlNode<char>*& pNodeOpt) {
    if (NULL != pNodeOpt) {
        // [结点本身地址][层数:节点值] [父节点][左孩子][右孩子]
        printf("[%p][L%d:%d] [%p][%p][%p]\n",
            pNodeOpt,
            pNodeOpt->m_BF,
            pNodeOpt->m_Element,
            pNodeOpt->m_pParent,
            pNodeOpt->m_pChildLeft,
            pNodeOpt->m_pChildRight);
    }
    else 
        printf("         ");

    return true;
}

void clear_cin() {
    cin.clear();
    cin.sync();
}

模板实现

// LsTree.h: interface for the CAvl class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_)
#define AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define NODE_LEFT true
#define NODE_RIGHT false

#include <iostream>
using namespace std;

#include <stddef.h>
#include <assert.h>
#include "LsStack.h"

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

///----------------------------------------------------------------------
/// 模板声明
///----------------------------------------------------------------------

template<typename T>
class CAvlNode {
public:
    CAvlNode()
        : m_Element(0)
        , m_BF(1)
        , m_pParent(NULL)
        , m_pChildLeft(NULL)
        , m_pChildRight(NULL)
        , m_pNextSameKeyIndex(NULL)
        , m_bDeleteNextSameKeyIndex(false) {}

    CAvlNode(T Element)
        : m_Element(Element)
        , m_BF(1)
        , m_pParent(NULL)
        , m_pChildLeft(NULL)
        , m_pChildRight(NULL)
        , m_pNextSameKeyIndex(NULL)
        , m_bDeleteNextSameKeyIndex(false) {}

    ~CAvlNode() {
        CAvlNode<T>* pNodeCur = m_pNextSameKeyIndex;
        CAvlNode<T>* pNodeNext = NULL;
#ifdef _DEBUG
        printf(">> ~CAvlNode() %p\n", this);
#endif
        if (m_bDeleteNextSameKeyIndex)
        {
            while (NULL != pNodeCur)
            {
                pNodeNext = pNodeCur->m_pNextSameKeyIndex;
                pNodeCur->m_bDeleteNextSameKeyIndex = false;
                delete pNodeCur;
                pNodeCur = pNodeNext;
            }
        }
    }

    /// 设置此标记, 防止递归删除CAvlNode层数太多的问题.
    bool m_bDeleteNextSameKeyIndex; ///< 是否删除同样值的链表
    T m_Element; ///< 元素值
    int m_BF;// 树节点的平衡因子(Balance Factor)
    CAvlNode<T>* m_pParent; ///< 父节点
    CAvlNode<T>* m_pChildLeft; ///< 左孩子结点
    CAvlNode<T>* m_pChildRight; ///< 右孩子结点
    CAvlNode<T>* m_pNextSameKeyIndex; ///< 同样的关键字索引, 挂一个链表
};

template<typename T>
class CAvl {
public:
    CAvl() : m_pRoot(NULL), m_nNodeCounter(0) {}
    virtual ~CAvl() {free(m_pRoot);}

    void adjustBf(CAvlNode<T>* pNode); ///< 调整节点的平衡因子
    void adjustBf(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 调整节点的平衡因子

    void rotateL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 左旋
    void rotateR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 右旋
    void rotateLR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 左双旋(先左后右)
    void rotateRL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3); ///< 右双旋(先右后左)

    int BF(CAvlNode<T>* pNode); ///< 取节点的平衡因子

    CAvlNode<T>* insert(T Element); ///< 插入有序结点
    CAvlNode<T>* find(T Element); ///< 在有序树中查找结点

    /// 在pNode的左边找最右边的结点
    CAvlNode<T>* findRightMaxOnNodeLeft(CAvlNode<T>* pNode);

    /// 在pNode的右边找最左边的结点
    CAvlNode<T>* findLeftMinOnNodeRight(CAvlNode<T>* pNode);

    bool remove(T Element); ///< 在有序树中移除结点(by结点值)
    bool remove(CAvlNode<T>* pNodeToDel); ///< 在有序树中移除结点(by结点指针)
private:
    bool removeChildNone(CAvlNode<T>* pNodeToDel);
    bool removeChildOne(CAvlNode<T>* pNodeToDel);
    bool removeChildTwo(CAvlNode<T>* pNodeToDel);
    bool removeChildTwoUseLeft(CAvlNode<T>* pNodeToDel); ///< 用左边最大的替换
    bool removeChildTwoUseRight(CAvlNode<T>* pNodeToDel); ///< 用右边最小的替换

    /// 用找到的节点指针替换并删除旧节点
    bool removeChildTwoUseNew(CAvlNode<T>* pNodeToDel, CAvlNode<T>* pNodeNew);

public:
    CAvlNode<T>* insertRootNode(T Element);
    CAvlNode<T>* MakeNewNode(T Element);
    CAvlNode<T>* insertNode(CAvlNode<T>* pNode, bool isLeft, T Element);
    CAvlNode<T>* insertNode(CAvlNode<T>* pNode, bool isLeft, CAvlNode<T>* pNodeChildExist);

    CAvlNode<T>* getRoot() {return m_pRoot;}

    typedef bool (*PFN_CALLBACK_TRAVERSETREE_TREE)(CAvl<T>* pTree, const CAvlNode<T>*& pNodeOpt);

    /// 用非递归实现遍历, 由回调操作遍历到的节点
    void TraverseDLR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 前序
    void TraverseLDR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 中序
    void TraverseLRD(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb); ///< 后序

    void free(CAvlNode<T>* pTreeNode); ///< 释放资源
private:
    CAvlNode<T>* m_pRoot;
    size_t m_nNodeCounter; ///< 树结点计数器, 代表树节点总数
};

///----------------------------------------------------------------------
/// 模板实现
///----------------------------------------------------------------------
template<typename T>
bool fnDelNode(CAvl<T>* pTree, const CAvlNode<T>*& pNodeOpt) {
    if ((NULL == pTree) || (NULL == pNodeOpt))
        return false;

    return pTree->remove((CAvlNode<T>*)pNodeOpt);
}

template<typename T>
void CAvl<T>::free(CAvlNode<T>* pTreeNode) {
    /// 按照LRD后序释放资源合理
    TraverseLRD(pTreeNode, fnDelNode);
}

template<typename T>
void CAvl<T>::TraverseDLR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) {
    CLsStack<CAvlNode<T>*> stack;
    
    if (NULL != pTreeNode)
        stack.push(pTreeNode);
    
    while (!stack.isEmpty()) {
        pTreeNode = stack.pop();
        if (NULL != pTreeNode) {
            if (NULL != pfnCb)
                pfnCb(this, pTreeNode);

            if (NULL != pTreeNode->m_pChildRight)
                stack.push(pTreeNode->m_pChildRight);
            
            if (NULL != pTreeNode->m_pChildLeft)
                stack.push(pTreeNode->m_pChildLeft);
        }
    }
}

template<typename T>
void CAvl<T>::TraverseLDR(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) {
    CLsStack<CAvlNode<T>*> stack;
    
    while ((NULL != pTreeNode) || !stack.isEmpty()) {
        if (NULL != pTreeNode) {
            stack.push(pTreeNode);
            pTreeNode = pTreeNode->m_pChildLeft;
        }
        else {
            pTreeNode = stack.pop();
            if (NULL != pfnCb)
                (*pfnCb)(this, pTreeNode);
            
            pTreeNode = pTreeNode->m_pChildRight;
        }
    }
}

template<typename T>
void CAvl<T>::TraverseLRD(CAvlNode<T>* pTreeNode, PFN_CALLBACK_TRAVERSETREE_TREE pfnCb) {
    bool isNodeNoAnyChild = false; ///< 是树叶
    bool isNodeNoRightChild = false; ///< 没有右孩子或右孩子已经遍历过

    CLsStack<CAvlNode<T>*> stack;
    CAvlNode<T>* pLastNode = NULL;

    while (1) {
        /// 遍历并压栈当前结点到当前结点的最后一个左孩子
        while (NULL != pTreeNode) {
            stack.push(pTreeNode);
            pTreeNode = pTreeNode->m_pChildLeft;
        }

        if (stack.isEmpty())
            break;

        pTreeNode = stack.pop();
        isNodeNoAnyChild = ((NULL == pTreeNode->m_pChildLeft)
            && (NULL == pTreeNode->m_pChildRight));
    
        isNodeNoRightChild = ((NULL == pTreeNode->m_pChildRight)
            || (pTreeNode->m_pChildRight == pLastNode));

        if (isNodeNoAnyChild || isNodeNoRightChild) {
            /// 符合LRD遍历操作当前结点的条件
            /// 如果是叶子, 执行回调
            /// 如果没有右孩子或右孩子已经遍历过, 执行回调
            if (NULL != pfnCb)
                (*pfnCb)(this, pTreeNode);

            pLastNode = pTreeNode; ///< !
            pTreeNode = NULL; ///< !
        }
        else {
            /// 当前结点入栈, 当前结点变为右孩子
            if (NULL != pTreeNode) {
                stack.push(pTreeNode);
                pTreeNode = pTreeNode->m_pChildRight;
            }
        }
    }
}

template<typename T>
CAvlNode<T>* CAvl<T>::insertRootNode(T Element) {
    if (NULL == m_pRoot) {
        m_pRoot = new CAvlNode<T>(Element);
    }

    return m_pRoot;
}

template<typename T>
bool CAvl<T>::remove(T Element) {
    CAvlNode<T>* pNodeToDel = find(Element);

    if (NULL == pNodeToDel)
        return false;

    return remove(pNodeToDel);
}

template<typename T>
bool CAvl<T>::remove(CAvlNode<T>* pNodeToDel) {
    if (NULL == pNodeToDel)
        return false;
    
    pNodeToDel->m_bDeleteNextSameKeyIndex = true;
    if ((NULL == pNodeToDel->m_pChildLeft) && (NULL == pNodeToDel->m_pChildRight))
        return removeChildNone(pNodeToDel);
    else if ((NULL != pNodeToDel->m_pChildLeft) && (NULL != pNodeToDel->m_pChildRight))
        return removeChildTwo(pNodeToDel);
    else
        return removeChildOne(pNodeToDel);
}

template<typename T>
bool CAvl<T>::removeChildNone(CAvlNode<T>* pNodeToDel) {
    if (NULL == pNodeToDel)
        return false;

    /// 删除结点后, 只影响父节点
    if (NULL == pNodeToDel->m_pParent)
        m_pRoot = NULL; ///< 要删除的是根结点
    else if (pNodeToDel->m_pParent->m_pChildLeft == pNodeToDel)
        pNodeToDel->m_pParent->m_pChildLeft = NULL;
    else
        pNodeToDel->m_pParent->m_pChildRight = NULL;

    adjustBf(pNodeToDel);
    delete pNodeToDel;
    m_nNodeCounter--;
    return true;
}

template<typename T>
bool CAvl<T>::removeChildOne(CAvlNode<T>* pNodeToDel) {
    CAvlNode<T>* pNodeChild = NULL; ///< pNodeToDel的独子结点

    if (NULL == pNodeToDel)
        return false;

    /// 删除结点后, 影响父节点和子节点
    if (NULL != pNodeToDel->m_pChildLeft)
        pNodeChild = pNodeToDel->m_pChildLeft;
    else
        pNodeChild = pNodeToDel->m_pChildRight;
    
    if (NULL == pNodeToDel->m_pParent)
        m_pRoot = pNodeChild;
    else {
        if (pNodeToDel->m_pParent->m_pChildLeft == pNodeToDel)
            pNodeToDel->m_pParent->m_pChildLeft = pNodeChild;
        else
            pNodeToDel->m_pParent->m_pChildRight = pNodeChild;
    }

    pNodeChild->m_pParent = pNodeToDel->m_pParent;
    adjustBf(pNodeToDel);
    delete pNodeToDel;
    m_nNodeCounter--;
    return true;
}

template<typename T>
bool CAvl<T>::removeChildTwo(CAvlNode<T>* pNodeToDel) {
    /// 在有序2叉树中
    /// 删除一个有2个孩子的结点后, 用孩子族谱中位置最接近本结点的后代继位
    /// 如果从左边找, 继位者是左边最大的
    /// 如果是从右边找, 继位者是右边最小的

    /// 使用下列方法之一就可以
    // return removeChildTwoUseLeft(pNodeToDel);
    return removeChildTwoUseRight(pNodeToDel);
}

template<typename T>
bool CAvl<T>::removeChildTwoUseLeft(CAvlNode<T>* pNodeToDel) {
    CAvlNode<T>* pSubNodeAsParent = NULL;
    
    if (NULL == pNodeToDel)
        return false;
    
    /// 从被删除节点的左边找到最大的一个节点
    pSubNodeAsParent = findRightMaxOnNodeLeft(pNodeToDel);
    assert(NULL != pSubNodeAsParent);

    return removeChildTwoUseNew(pNodeToDel, pSubNodeAsParent);
}

template<typename T>
bool CAvl<T>::removeChildTwoUseRight(CAvlNode<T>* pNodeToDel) {
    CAvlNode<T>* pSubNodeAsParent = NULL;
    
    if (NULL == pNodeToDel)
        return false;
    
    /// 从被删除节点的右边找到最小的一个节点
    pSubNodeAsParent = findLeftMinOnNodeRight(pNodeToDel);
    assert(NULL != pSubNodeAsParent);

    return removeChildTwoUseNew(pNodeToDel, pSubNodeAsParent);
}

template<typename T>
bool CAvl<T>::removeChildTwoUseNew(
    CAvlNode<T>* pNodeToDel,
    CAvlNode<T>* pNodeNew) {
    CAvlNode<T>* pNodeTmp = NULL;
    if ((NULL == pNodeToDel) || (NULL == pNodeNew))
        return false;

    /// 将新节点赋值到要删除的节点
    pNodeToDel->m_Element = pNodeNew->m_Element;

    /// 交换链表
    pNodeTmp = pNodeNew->m_pNextSameKeyIndex;
    pNodeNew->m_pNextSameKeyIndex = pNodeToDel->m_pNextSameKeyIndex;
    pNodeToDel->m_pNextSameKeyIndex = pNodeTmp;

    return remove(pNodeNew);
}

template<typename T>
CAvlNode<T>* CAvl<T>::findRightMaxOnNodeLeft(CAvlNode<T>* pNode) {
    /// 在pNode的左边找最右边的结点
    if ((NULL == pNode) || (NULL == pNode->m_pChildLeft))
        return NULL;

    pNode = pNode->m_pChildLeft;
    while (NULL != pNode->m_pChildRight)
        pNode = pNode->m_pChildRight;

    return pNode;
}

template<typename T>
CAvlNode<T>* CAvl<T>::findLeftMinOnNodeRight(CAvlNode<T>* pNode) {
    /// 在pNode的右边找最左边的结点
    if ((NULL == pNode) || (NULL == pNode->m_pChildRight))
        return NULL;
    
    pNode = pNode->m_pChildRight;
    while (NULL != pNode->m_pChildLeft)
        pNode = pNode->m_pChildLeft;
    
    return pNode;
}

template<typename T>
CAvlNode<T>* CAvl<T>::find(T Element) {
    CAvlNode<T>* pNodeCur = getRoot();

    while (NULL != pNodeCur) {
        if (Element > pNodeCur->m_Element)
            pNodeCur = pNodeCur->m_pChildRight; ///< 新节点在右边
        else if (Element < pNodeCur->m_Element)
            pNodeCur = pNodeCur->m_pChildLeft; ///< 新节点在左边
        else
            break; ///< 找到了相等的树结点值, 结点为pNodeCur
    }

    return pNodeCur;
}

template<typename T>
CAvlNode<T>* CAvl<T>::insert(T Element) {
    bool bInsertOk = false;
    CAvlNode<T>* pNewNode = new CAvlNode<T>(Element);
    CAvlNode<T>* pNodeCur = NULL;
    
    if (NULL != pNewNode)
        m_nNodeCounter++;

    if (NULL == m_pRoot) {
        /// 在空树中插入根节点
        m_pRoot = pNewNode;
        return pNewNode;
    }
    
    /// 在非空树中, 插入到一个空结点
    pNodeCur = m_pRoot;
    while (NULL != pNodeCur) {
        if (Element > pNodeCur->m_Element) {
            /// 应该将新节点插入当前结点右边
            if (NULL == pNodeCur->m_pChildRight) {
                pNodeCur->m_pChildRight = pNewNode;
                bInsertOk = true;
                break;
            }
            
            pNodeCur = pNodeCur->m_pChildRight;
            continue;
        }
        else if (Element < pNodeCur->m_Element) {
            /// 应该将新节点插入当前结点左边
            if (NULL == pNodeCur->m_pChildLeft) {
                pNodeCur->m_pChildLeft = pNewNode;
                bInsertOk = true;
                break;
            }
            
            pNodeCur = pNodeCur->m_pChildLeft;
            continue;
        }
        else
        {
            /// 找到了相等的树结点值
            pNewNode->m_pNextSameKeyIndex = pNodeCur->m_pNextSameKeyIndex;
            pNodeCur->m_pNextSameKeyIndex = pNewNode;
        }
        
        break;
    }

    if (bInsertOk) {
        pNewNode->m_pParent = pNodeCur;
        adjustBf(pNewNode);
    }
    
    return pNewNode;
}

template<typename T>
CAvlNode<T>* CAvl<T>::MakeNewNode(T Element) {
    CAvlNode<T>* pNewNode = new CAvlNode<T>();
    pNewNode->m_Element = Element;
    
    return pNewNode;
}

template<typename T>
CAvlNode<T>* CAvl<T>::insertNode(CAvlNode<T>* pNode, bool isLeft, T Element) {
    CAvlNode<T>* pNodeChild = NULL;
    if (NULL != pNode) {
        pNodeChild = new CAvlNode<T>(Element);
        pNodeChild->m_pParent = pNode;

        if (isLeft)
            pNode->m_pChildLeft = pNodeChild;
        else
            pNode->m_pChildRight = pNodeChild;
    }
    
    return pNode;
}

template<typename T>
CAvlNode<T>* CAvl<T>::insertNode(CAvlNode<T>* pNode, bool isLeft, CAvlNode<T>* pNodeChildExist) {
    if (NULL != pNode) {
        if (NULL != pNodeChildExist)
            pNodeChildExist->m_pParent = pNode;

        if (isLeft)
            pNode->m_pChildLeft = pNodeChildExist;
        else
            pNode->m_pChildRight = pNodeChildExist;
    }
    
    return pNodeChildExist;
}

template<typename T>
int CAvl<T>::BF(CAvlNode<T>* pNode) {
    return  (NULL != pNode) ? pNode->m_BF : 0;
}

template<typename T>
void CAvl<T>::adjustBf(CAvlNode<T>* pNode) {
    CAvlNode<T>* pParent = (NULL != pNode) ? pNode->m_pParent : NULL;
        /*
                G                     G
            AD1                     AD2
         A     AD2       ==>     AD1     AD3
              B   AD3          A     B 
        */
    /// AD mean's "node need adjust"
    CAvlNode<T>* pAD1 = NULL; ///< 入参节点pNode的父节点
    CAvlNode<T>* pAD2 = NULL; ///< pAD1 偏重的子树节点
    CAvlNode<T>* pAD3 = NULL; ///< pAD2 偏重的子树节点

    int iBfLeft = 0; ///< 左树的平衡因子
    int iBfRight = 0; ///< 右树的平衡因子

    while (NULL != pParent) {
        iBfLeft = BF(pParent->m_pChildLeft);
        iBfRight = BF(pParent->m_pChildRight);

        /// 调整父节点的平衡因子
        pParent->m_BF = max(iBfLeft, iBfRight) + 1;

        /// 检查平衡
        if (abs(iBfLeft - iBfRight) > 1) {
            /// 不平衡, 需要调整AVL为平衡
            pAD1 = pParent;

            if (iBfLeft > iBfRight)
                pAD2 = pAD1->m_pChildLeft;
            else
                pAD2 = pAD1->m_pChildRight;

            if (NULL != pAD2) {
                if (BF(pAD2->m_pChildLeft) > BF(pAD2->m_pChildRight))
                    pAD3 = pAD2->m_pChildLeft;
                else
                    pAD3 = pAD2->m_pChildRight;

                adjustBf(pAD1, pAD2, pAD3);
            }
        }

        /// 将父节点链都调整为AVL平衡
        pParent = pParent->m_pParent;
    }
}

template<typename T>
void CAvl<T>::adjustBf(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) {
    if ((pAD2 == pAD1->m_pChildRight) && (pAD3 == pAD2->m_pChildRight)) {
        /// 不平衡且有序, 右斜树, 经过一次左旋平衡
        rotateL(pAD1, pAD2, pAD3);
    }
    else if ((pAD2 == pAD1->m_pChildLeft) && (pAD3 == pAD2->m_pChildLeft)) {
        /// 不平衡且有序, 左斜树, 经过一次右旋平衡
        rotateR(pAD1, pAD2, pAD3);
    }
    else if ((pAD2 == pAD1->m_pChildLeft) && (pAD3 == pAD2->m_pChildRight)) {
        /// 不平衡且无序, 经过左双旋平衡
        rotateLR(pAD1, pAD2, pAD3);
    }
    else if ((pAD2 == pAD1->m_pChildRight) && (pAD3 == pAD2->m_pChildLeft)) {
        /// 不平衡且无序, 经过右双旋平衡
        rotateRL(pAD1, pAD2, pAD3);
    }
}

template<typename T>
void CAvl<T>::rotateL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) {
    ///< 左旋
    /*
            G                     G
        AD1                     AD2
     A     AD2       ==>     AD1     AD3
          B   AD3          A     B 
    */
    CAvlNode<T>* pNodeA = pAD1->m_pChildLeft;
    CAvlNode<T>* pNodeB = pAD2->m_pChildLeft;
    CAvlNode<T>* pNodeC = pAD3;
    CAvlNode<T>* pNodeG = pAD1->m_pParent;
    
    /// 更新pNodeB
    if (NULL != pNodeB)
        pNodeB->m_pParent = pAD1;
    
    /// 更新pNodeG
    if (NULL != pNodeG) {
        if (pAD1 == pNodeG->m_pChildLeft)
            pNodeG->m_pChildLeft = pAD2;
        else
            pNodeG->m_pChildRight = pAD2;
    }
    else
        m_pRoot = pAD2;
    
    /// 更新pAD1
    pAD1->m_pChildRight = pNodeB;
    pAD1->m_pParent = pAD2;
    
    /// 更新pAD2
    pAD2->m_pChildLeft = pAD1;
    pAD2->m_pParent = pNodeG;
    
    //调整pAD1,pAD2的高度
    pAD1->m_BF = max(BF(pAD1->m_pChildLeft), BF(pAD1->m_pChildRight)) + 1;
    pAD2->m_BF = max(BF(pAD2->m_pChildLeft), BF(pAD2->m_pChildRight)) + 1;
}

template<typename T>
void CAvl<T>::rotateR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) {
    ///< 右旋
    /*
                G                   G
            AD1                  AD2
         AD2   A      ==>     AD3     AD1
      AD3    B                      B     A
    */
    CAvlNode<T>* pNodeA = pAD1->m_pChildRight;
    CAvlNode<T>* pNodeB = pAD2->m_pChildRight;
    CAvlNode<T>* pNodeC = pAD3;
    CAvlNode<T>* pNodeG = pAD1->m_pParent;
    
    /// 更新pNodeB
    if (NULL != pNodeB)
        pNodeB->m_pParent = pAD1;
    
    /// 更新pNodeG
    if (NULL != pNodeG) {
        if (pAD1 == pNodeG->m_pChildLeft)
            pNodeG->m_pChildLeft = pAD2;
        else
            pNodeG->m_pChildRight = pAD2;
    }
    else
        m_pRoot = pAD2;
    
    /// 更新pAD1
    pAD1->m_pParent = pAD2;
    pAD1->m_pChildLeft = pNodeB;
    
    /// 更新pAD2
    pAD2->m_pChildRight = pAD1;
    pAD2->m_pParent = pNodeG;
    
    //调整pAD1,pAD2的高度
    pAD1->m_BF = max(BF(pAD1->m_pChildLeft), BF(pAD1->m_pChildRight)) + 1;
    pAD2->m_BF = max(BF(pAD2->m_pChildLeft), BF(pAD2->m_pChildRight)) + 1;
}

template<typename T>
void CAvl<T>::rotateLR(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) {
    ///< 左双旋(先左后右)
    rotateL(pAD2, pAD3, NULL);
    rotateR(pAD1, pAD3, pAD2);
}

template<typename T>
void CAvl<T>::rotateRL(CAvlNode<T>* pAD1, CAvlNode<T>* pAD2, CAvlNode<T>* pAD3) {
    ///< 右双旋(先右后左)
    rotateR(pAD2, pAD3, NULL);
    rotateL(pAD1, pAD3, pAD2);
}

#endif // !defined(AFX_LSTREE_H__4898D3E6_65B2_4A17_9CA5_910BEF38E313__INCLUDED_)
// LsStack.h: interface for the CLsLinkedList class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
#define LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "LsDoublyLinkedList.h"

/**
栈
    栈也是线性表.
    栈是先进后出, 只操作栈顶的数据结构.
    栈是可以回溯的
    栈可以用来计算用来制作堆栈机, 用堆栈机算法来模拟逆波兰表达式的运算结果, 可以模拟汇编指令的执行, 用于虚拟机.
实现方法
    * 用链表类实现
    继承于链表, 只在头部操作(增加,删除).
    * 用数组类实现
    继承于数组, 只在尾部操作(增加,删除).
*/
template<typename T>
class CLsStack : public CLsLinkedList<T> {
public:
    CLsStack() {}
    virtual ~CLsStack() {}

    void push(T Element);
    T pop();
};

template<typename T>
void CLsStack<T>::push(T Element) {
    addHead(Element);
}

template<typename T>
T CLsStack<T>::pop() {
    T Rc = (T)0;

    if (getLength() > 0) {
        Rc = *getHead();
        removeHead();
    }

    return Rc;
}

#endif // !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
// LsDoublyLinkedList.h: interface for the CLsLinkedList class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
#define LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632

/**
链表总结
空间
    链式存储
时间复杂度
    尽量避免提供非常量阶的接口
    增加操作: O(1) 常量阶, 快
    删除操作: O(1) 常量阶, 快
    修改操作:O(1) 快(条件:知道位置, 用的是先前返回的位置类或结点指针)
    查询操作:O(n) 线性阶, 慢
    随机访问:O(n) 线性阶, 慢
使用场合
    * 问题规模不确定
    * 随机访问频率低
    * 数据更新频率高(主要指的是添加和删除操作)
缺点
    * 查询速度慢(数组和链表查询速度都慢)
原生new的时间复杂度
    new实现是线性阶.
    调用的memset是线性阶, 有循环操作.
    HeapAlloc中没源码, 但是有循环操作, 是线性阶.
    new不影响时间增长率.

结论
    当算法中, new次数较少时, 可以忽略new对算法时间复杂度的影响.
    当new次数较多时, 可以一次多new几个元素(e.g. 10个), 下次就不用new, 直接取已经new好的数据操作, 等用完了, 才再次new几个元素出来.
    这样对new操作做优化, 等于自己做堆管理, 需要再做一个链表, 将new出来的10个一组的小块内存空间管理起来, 当一个类指针不用了, 就称为闲置空间, 放在内存池中. 下次不用再申请了, 可以复用.
    等链表析构时, 链表的原生操作完成后, 再一块释放内存池.
*/

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/// ----------------------------------------------------------------------
/// CLsLinkedList 双链表 定义
/// ----------------------------------------------------------------------
template <typename T>
class CLsLinkedList {
public:
    /// ----------------------------------------------------------------------
    /// CLsLinkedNode 定义
    /// ----------------------------------------------------------------------
    
    /// LsDoublyLinkedList's Node
    template <typename T>
        struct CLsLinkedNode {
        friend CLsLinkedList<T>; ///< 不需要前向声明, 用到的时候才检查
        friend CLsLinkedList<T>::iterator;

    private:
        CLsLinkedNode(T Elem)
            :m_Elem(Elem)
            ,m_pNext(NULL)
            ,m_pPrev(NULL) {}
        
        ~CLsLinkedNode() {}

        T m_Elem; //数据元素
        CLsLinkedNode<T>* m_pPrev; //前驱
        CLsLinkedNode<T>* m_pNext; //后继
    };

    /// ----------------------------------------------------------------------
    /// 正向迭代器 定义
    /// ----------------------------------------------------------------------
    class iterator {
        friend class CLsLinkedList<T>;
    public:
        iterator() {
            m_pNode = NULL;
        }

        iterator(CLsLinkedNode<T>* pNode) {
            m_pNode = pNode;
        }
        
        iterator operator++() {
            m_pNode = m_pNode->m_pNext;
            return m_pNode;
        }
        
        iterator operator++(int) {
            CLsLinkedNode<T> *pTemp = m_pNode;
            m_pNode = m_pNode->m_pNext;
            return pTemp;
        }

        iterator operator--() {
            m_pNode = m_pNode->m_pPrev;
            return m_pNode;
        }
        
        iterator operator--(int) {
            CLsLinkedNode<T> *pTemp = m_pNode;
            m_pNode = m_pNode->m_pPrev;
            return pTemp;
        }
        
        T& operator* () {
            return m_pNode->m_Elem;
        }
        
        bool operator!= (const iterator& obj) {
            return m_pNode != obj.m_pNode;
        }

        bool operator== (const iterator& obj) {
            return m_pNode == obj.m_pNode;
        }

    private:
        CLsLinkedNode<T>* GetNode() {
            return m_pNode;
        }

    private:
        CLsLinkedNode<T>* m_pNode;
    };

public:
    iterator begin() {
        return m_pHead;
    }

    iterator end() {
        return NULL;
    }

public:
    CLsLinkedList();
    virtual ~CLsLinkedList();

    /// 只提供O(1)的接口^_^

    iterator getTail() const;
    iterator getHead() const;
    inline bool isEmpty() const;
    inline size_t getLength() const;  //表长
    void clear();

    iterator addTail(T newElem);
    bool removeTail();

    iterator addHead(T newElem);
    bool removeHead();

    T getAt(iterator it) const;
    void setAt(iterator it, T newElem);
    bool removeAt(iterator it);

    bool insert(iterator it, T newElem);

private:
    CLsLinkedNode<T>* m_pHead;  //头结点
    CLsLinkedNode<T>* m_pTail;  //尾结点
    size_t m_nLength;
};

/// ----------------------------------------------------------------------
/// CLsLinkedList 实现
/// ----------------------------------------------------------------------
template <typename T>
inline size_t CLsLinkedList<T>::getLength() const {
    return m_nLength;
}

template <typename T>
inline bool  CLsLinkedList<T>::isEmpty() const {
    return (NULL == m_pHead) ? true : false;
}

template <typename T>
CLsLinkedList<T>::CLsLinkedList()
:m_pHead(NULL)
,m_pTail(NULL)
,m_nLength(0) {}

template <typename T>
CLsLinkedList<T>::~CLsLinkedList() {
    clear();
}

template <typename T>
void CLsLinkedList<T>::clear() {
    while (!isEmpty()) {
        removeTail();
    }
}

template <typename T>
T CLsLinkedList<T>::getAt(CLsLinkedList::iterator it) const {
    return *it;
}

template <typename T>
void CLsLinkedList<T>::setAt(CLsLinkedList::iterator it, T newElem) {
    *it = newElem;
}

template <typename T>
bool CLsLinkedList<T>::insert(CLsLinkedList::iterator it, T newElem) {
    CLsLinkedNode<T>* pNewNode = NULL;
    CLsLinkedNode<T>* pPrev = NULL;
    CLsLinkedNode<T>* pNext = NULL;

    pPrev = it.GetNode();
    if (NULL == pPrev) {
        return false;
    }

    pNewNode = new CLsLinkedNode<T>(newElem);
    pNext = pPrev->m_pNext;
    
    /*
    1 2 3 [6] 4 5
    3.next = 6
    4.prev = 6
    6.prev = 3
    6.next = 4
    
      1 2 3 4 5 [6]
    */
    pPrev->m_pNext = pNewNode;
    if (NULL != pNext) {
        pNext->m_pPrev = pNewNode;
    }

    pNewNode->m_pPrev = pPrev;
    pNewNode->m_pNext = pNext;
    m_nLength++;
    return true;
}

template <typename T>
bool CLsLinkedList<T>::removeTail() {
    bool bRc = false;
    CLsLinkedNode<T>* pPrev = NULL;

    if (NULL == m_pHead) {
        return false;
    }
    
    //1 2 [3]
    if (NULL != m_pTail) {
        pPrev = m_pTail->m_pPrev;
        if (NULL != pPrev)
            pPrev->m_pNext = NULL;
        else
            m_pHead = NULL;
        
        delete m_pTail;
        bRc = true;
        m_pTail = pPrev;
        m_nLength--;
    }

    return bRc;
}

template <typename T>
bool CLsLinkedList<T>::removeHead() {
    if (NULL == m_pHead)
        return false;
    
    //[1] 2 3
    CLsLinkedNode<T>* pNext = m_pHead->m_pNext;
    if (NULL != pNext)
        pNext->m_pPrev = NULL;
    else
        m_pTail = NULL;
    
    delete m_pHead;
    m_nLength--;
    m_pHead = pNext;
    return true;
}

template <typename T>
bool CLsLinkedList<T>::removeAt(CLsLinkedList::iterator it) {
    CLsLinkedNode<T>* pDelNode = it.GetNode();
    CLsLinkedNode<T>* pPrev = NULL;
    CLsLinkedNode<T>* pNext = NULL;

    if ((NULL == m_pHead) || (NULL == pDelNode))
        return false;
    
    /*
    1 2 [3] 4 5 
    2.next = 4
    4.prev = 2
    
      [1] 2 3 4 5 
      
        1 2 3 4 [5]
        
          [1]
    */
    pPrev = pDelNode->m_pPrev;
    pNext = pDelNode->m_pNext;

    if (NULL != pPrev)
        pPrev->m_pNext = pNext;
    else
        m_pHead = pNext;
    
    if (NULL != pNext)
        pNext->m_pPrev = pPrev;
    else
        m_pTail = pPrev;
    
    delete pDelNode;
    m_nLength--;
    
    return true;
}

template <typename T>
CLsLinkedList<T>::iterator CLsLinkedList<T>::addTail(T newElem) {
    CLsLinkedList<T>::CLsLinkedNode<T>* pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem);
    
    //空表
    if (NULL == m_pHead)
        m_pHead = m_pTail = pNewNode;
    else {
        //1 2 3 4 5 [6]
        //5.next = 6    6.prev = 5  tail = 6
        m_pTail->m_pNext = pNewNode;
        pNewNode->m_pPrev = m_pTail;
        m_pTail = pNewNode;
    }

    m_nLength++;

    return pNewNode;
}

template <typename T>
CLsLinkedList<T>::iterator CLsLinkedList<T>::addHead(T newElem) {
    CLsLinkedList<T>::CLsLinkedNode<T> *pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem);
    
    //空表
    if (NULL == m_pHead)
        m_pHead = m_pTail = pNewNode;
    else {
        //[6] 1 2 3 4 5 
        //1.prev = 6    6.next = 1  head = 6
        m_pHead->m_pPrev = pNewNode;
        pNewNode->m_pNext = m_pHead;
        m_pHead = pNewNode;
    }

    m_nLength++;
    return pNewNode;
}

template <typename T>
CLsLinkedList<T>::iterator CLsLinkedList<T>::getTail() const {
    return m_pTail;
}

template <typename T>
CLsLinkedList<T>::iterator CLsLinkedList<T>::getHead() const {
    return m_pHead;
}

#endif // !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
    原文作者:AVL树
    原文地址: https://blog.csdn.net/lostspeed/article/details/50509736
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞