Treap C++代码实现

 一、全部代码

#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;

//Treap结构
struct TreapNode
{
    TreapNode *pLeft, *pRight;
    int value, fix;
};

//左旋
void TreapLeftRotate(TreapNode* &pCur){
    //首先,找到当前根节点的右子树
    TreapNode* rightChild = pCur->pRight;
    //然后把右子树的左孩子接到当前根节点的右子树
    pCur->pRight = rightChild->pLeft;
    //再设右子树的左孩子为当前根节点
    rightChild->pLeft = pCur;
    pCur = rightChild;
}
//右旋
void TreapRightRotate(TreapNode* & pCur){
    //首先,找到当前根节点左子树
    TreapNode* leftChild = pCur->pLeft;
    //然后,把左子树的右孩子接到当前根节点的左子树
    pCur->pLeft = leftChild->pRight;
    //再设左子树的右孩子为当前根节点
    leftChild->pRight = pCur;
    pCur = leftChild;
}
//插入
void TreapInsert(TreapNode* &pCur, int newV){
    //要插入首先要找到插入的位置,如果要插入的节点为NULL,说明到达了该插入的时机
    if(pCur == NULL){
        pCur = new TreapNode; //开辟空间
        pCur->value = newV; //赋值
        pCur->pLeft = NULL; //新节点左子树为NULL
        pCur->pRight = NULL; //新节点右子树为NULL
        pCur->fix = rand()%10000; //给予一个修正随机数
    }
    //如果当前节点的值比newV大,就往左找
    else if(newV < pCur->value){
        TreapInsert(pCur->pLeft, newV);//向左递归插入
        //插入之后,要进行fix的修正,因为是向左子树递归,所以判断左子树的fix大小并右旋即可
        if(pCur->pLeft->fix < pCur->fix){
            TreapRightRotate(pCur);
        }
    }
    //同上
    else{
        TreapInsert(pCur->pRight, newV);
        if(pCur->pRight->fix < pCur->fix){
            TreapLeftRotate(pCur);
        }
    }
}

//查找
TreapNode* TreapSearch(TreapNode* pCur, int totalValue){
    //相等说明找到了
    if(pCur == NULL) return NULL;
    if(pCur->value == totalValue){
        return pCur;
    }
    //不相等就判断他在当前节点的左边还是右边
    else if(pCur->value < totalValue)
        return TreapSearch(pCur->pRight, totalValue);
    else
        return TreapSearch(pCur->pLeft, totalValue);
}

//删除
void TreapDelete(TreapNode* &pCur, int deleteValue){
    //如果相等说明有这个值,进行删除
    if(pCur->value == deleteValue){
        //如果是只有一个节点或者没有节点的情况
        if(pCur->pLeft == NULL || pCur->pRight == NULL){
            TreapNode* deleteNode = pCur; //记录要删除的节点
            //判断左右子树哪个不是NULL,直接将它放在删除节点的位置
            if(pCur->pLeft != NULL){
                pCur = pCur->pLeft;
            }
            else{
                pCur = pCur->pRight;
            }
            delete deleteNode; //删除节点
        }
        //如果是有两个结点的情况
        else{
            //左子树fix值比右子树fix值小
            if(pCur->pLeft->fix < pCur->pRight->fix){
                TreapRightRotate(pCur);//右旋
                TreapDelete(pCur->pRight, deleteValue); //由于右旋将要删除的元素移动到了右侧,所以向右继续递归删除
            }
            else{
                TreapLeftRotate(pCur);
                TreapDelete(pCur->pLeft, deleteValue);
            }
        }
    }
    //如果不相等就继续找
    else if(pCur->value < deleteValue)
        TreapDelete(pCur->pRight, deleteValue);
    else
        TreapDelete(pCur->pLeft, deleteValue);
}

//先序遍历
void preOrder(TreapNode* pCur){
    if(pCur != NULL){
        cout << "(" << pCur->value << " ," << pCur->fix << ")";
        preOrder(pCur->pLeft);
        preOrder(pCur->pRight);
    }

}

//中序遍历
void inOrder(TreapNode* pCur){
    if(pCur == NULL){
        inOrder(pCur->pLeft);
        cout << "(" << pCur->value << " ," << pCur->fix << ")";
        inOrder(pCur->pRight);
    }

}
TreapNode *root=NULL;
int main()
{
    srand((unsigned)time(0));
    int data[]={1,2,3,4,5,6,7,8,9,10,2,5,6};
    int n=sizeof(data)/sizeof(int),i,cnt=0;
    for(i=0;i<n;i++)
    {
        //先查找是否存在
        TreapNode* pFound = TreapSearch(root, data[i]);
        //不存在就插入
        if(pFound==NULL)
        {
            TreapInsert(root,data[i]);
            cnt++;//记录元素个数
        }
    }
    //删除之前的树
    cout << "删除之前的树:";
    inOrder(root);//中序遍历
    cout << endl;
    preOrder(root); //先序遍历

    TreapDelete(root,4); //删除一个4测试

    //删除之后的树
    cout<<"\n"<<cnt<<endl;
    cout << "删除之后的树:";

    inOrder(root);
    cout<<endl;
    preOrder(root);
    return 0;
}

二、运行结果 

猜你喜欢

转载自blog.csdn.net/weixin_63484669/article/details/131042627
今日推荐