平衡二叉树基本实现

这里实现了平衡二叉树的删除 插入 搜索 遍历

节点类

class Node{
public:
    int data;
    Node *r;             //右节点
    Node *l;            //左节点
    int h;              //节点的深度
    Node(int data){      //构造函数
        h = -1;
        this->data = data;
        r = l = NULL;
    }
    ~Node(){             //析构
        delete r, l;
    }

};

*Tree类

class Tree{
private:
    int max(int a, int b);          //返回较大值
    int height(Node *p);             //获取p节点的深度
    void singleright(Node* &p);      //单右旋
    void singleleft(Node *&p);       //单左旋
    void doubleright(Node *&p);      //双右旋
    void doubleleft(Node *&p);       //双左旋
    void insert(Node *&p, int data); //插入函数
    void preprint(Node *p){          //前序遍历,,中后序略
    void removes(Node *p,int data);  //删除函数
        if (p){
            cout <<p->data << endl;
            preprint(p->l);
            preprint(p->r);
        }
    }
public:
    Node *root;
    Tree(){
        root = NULL;
    }
    void insertnode(int data){       
        insert(root,data);
    }
    void prePrint(){              
        preprint(root);
    }
    void remove(int data){
    removes(root,data);
    }
    ~Tree(){
        delete root;
    }
};

下面是具体的实现:

int Tree::max(int a, int b){        //返回较大值
    return a > b ? a : b;
}

//
int Tree::height(Node *p){                             //获取某个节点的深度
    if (p)return p->h;            //p不为空,则返回深度
    return -1;
}

//右旋函数
void Tree::singleright(Node* &p){ //右旋转 .. p的left节点旋转到p的位置
    Node *pl = p->l;
    p->l = pl->r;
    pl->r = p;

//修改深度
p->h = max(height(p->l), height(p->r)) + 1; 
 //旋转后需要更新节点的h值; (h==p节点的深度)p旋转到了右边,p的h (深度)应为其左右孩子节点深度中的最大值加1
pl->h = max(p->h, height(pl->l)) + 1;       
  //pl旋转到了原来p的位置,它的深度是其左孩子和右孩子(p)的深度达较大者+1
    p = pl;
}

///左旋函数

void Tree::singleleft(Node *&p){ //左旋转  ..  p的right节点旋转到p的位置

    Node *pr = p->r;
    p->r = pr->l;
    pr->l = p;



    p->h = max(height(p->l), height(p->r)) + 1;
    //p旋转到了左边,p的深度(h)应为其左右孩子节点深度中的最大值加1
    pr->h = max(p->h, height(pr->r));                     //pr旋转到了原来p的位置,它的深度应该为它的左孩子(p)和有孩子的深度的较大者+1
    p = pr;
}




void Tree::doubleright(Node *&p){  //双右旋
    singleleft(p->l);
    singleright(p);
}



void Tree::doubleleft(Node *&p){    //双左旋
    singleright(p->r);
    singleleft(p);
}




//插入函数
void Tree::insert(Node *&p, int data){                 
    if (p == NULL){             //节点为空,则在p处插入新节点
        Node *node = new Node(data);
        p = node;
        p->h = 0;
    }

    //待插入值大于p的键值,则插入p的右子树
    else if (data>p->data){
        insert(p->l, data);

        if (2 == height(p->l) - height(p->r)){       //如果平衡被打破就进行调整
            if (data>p->l->data){  //如果是左左树,右旋转p
                singleright(p);
            }
            else doubleright(p); //如果是左右树 双右旋
        }
    }
    //待插入值小于p的键值,则插入p的左子树
    if (data < p->data){
        insert(p->r, data);

        if (2 == height(p->r) - height(p->l)){     //平衡被打破就进行调整
            if (data<p->r->data){    //如果是右右树,左旋
                singleleft(p);
            }
            else doubleleft(p);   //如果是右左树,双左旋p
        }
    }
    else return;
    p->h = max(height(p->r), height(p->l)) + 1;   
    //为新插入节点的深度赋值,递归的更新其他节点的深度
}


//删除函数
void Tree::removes(Node *&p, int data){
    if (!p)return;
    if (data>p->data){ //如果待删除的值大于p的键值  在p的左子树中查找data
    removes(p->l,data);    

    if (2==height(p->r)-height(p->l)){               //找到并且删除data后,修改树的平衡
        if (p->r->l && height(p->r->l) > height(p->r->r))doubleleft(p);  //左树减少了一个元素,判断是右左树还是右右树
        else singleleft(p); 
        }
    }
    else if (data < p->data ){ //如果待删除的值小于p的键值,在p的右子树中搜索data
        removes(p->r,data); 

 //删除后修改树的平衡   判断树是否平衡                       
        if (2 == height(p->l) - height(p->r)){    

        //右树减少了一个元素,判断p为首的树是左右树还是左左树        
            if (p->l->r && height(p->l->r)>height(p->l->l))doubleright(p);

            else singleright(p); 
        }
    }
    else {
//如果节点有左右孩子, 在左树中找出最小值取代p的键值,然后删除最小值
        if (p->r && p->l){     

            Node *temp = p->l;
            while (temp->r)temp = temp->r;
            p->data = temp->data;

            removes(p->l,temp->data);    //删除最小值

     if (2==height(p->r)-height(p->l)){//删除后判断树是否还是平衡的

    //由于删除了左树中的值,p树转变成右右树,或者右左树
     if (p->r->l && height(p->r->l) > height(p->r->r))                           doubleleft(p);  //双左旋

        else singleleft(p);//单左旋
            }
        }
        else {    //只有一子个节点或者没有孩子节点的情况
            Node * t = p;  
            if (!p->r)p = p->l;
            else if (!p->l)p = p->r;
            delete t;            
            t = NULL;
        }
    }
    if (!p)return;   //如果p节点已经被删除了就 return
    p->h = max(height(p->l),height(p->r))+1; //p节点没有被删除(p一定是有左右孩子的节点)则修改p节点的深度
}

///主函数
int main(){
Tree *t=new Tree();
t->insertnode(5);
t->insertnode(60);
t->insertnode(2);
t->insertnode(9);
t->insertnode(12);
t->insertnode(4);
t->insertnode(52);
t->insertnode(5);
t->prePrint();
cout << t->root->h<< endl;
delete t;
system(“pause”);
return 0;
}
“`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值