zoukankan      html  css  js  c++  java
  • avl树

    自动平衡二叉树,可以保证每次增加,输出,查询只用log(N)的时间复杂度

    模板

    struct node
    {
    	int lc,rc,h,v;
    }tree[N];
    int pos=0,x1,x2,root;
    int right_rotate(int r)//zig右旋
    {
    	int t = tree[r].lc;
    	tree[r].lc = tree[t].rc;
    	tree[t].rc = r;
    	tree[r].h = max(tree[tree[r].lc].h,tree[tree[r].rc].h)+1;
    	tree[t].h = max(tree[tree[t].lc].h,tree[tree[t].rc].h)+1;
    	return t;
    }
    int left_rotate(int r)//zag左旋
    {
    	int t = tree[r].rc;
    	tree[r].rc = tree[t].lc;
    	tree[t].lc = r;
    	tree[r].h = max(tree[tree[r].lc].h,tree[tree[r].rc].h)+1;
    	tree[t].h = max(tree[tree[t].lc].h,tree[tree[t].rc].h)+1;
    	return t;
    }
    int right_left_rotate(int r)//zigzag双旋
    {
    	tree[r].rc = right_rotate(tree[r].rc);
    	return left_rotate(r);
    }
    int left_right_rotate(int r)//zagzig双旋
    {
    	tree[r].lc = left_rotate(tree[r].lc);
    	return right_rotate(r);
    }
    void maintain(int &r)//维持平衡
    {
    	if(tree[tree[r].lc].h == tree[tree[r].rc].h+2)//左子树高了
    	{
    		int t = tree[r].lc;
    		if(tree[tree[t].lc].h == tree[tree[r].rc].h+1) r = right_rotate(r);//左子树的左儿子,对应第一种情况
    		else if(tree[tree[t].rc].h == tree[tree[r].rc].h+1) r = left_right_rotate(r);	
    	}
    	else if(tree[tree[r].rc].h == tree[tree[r].lc].h+2)//右子树高了
    	{
    		int t = tree[r].rc;
    		if(tree[tree[t].rc].h == tree[tree[r].lc].h+1) r = left_rotate(r);//右子树的右儿子,对应第四种情况
    		else if(tree[tree[t].lc].h == tree[tree[r].lc].h+1) r = right_left_rotate(r);
    	}
    	tree[r].h = max(tree[tree[r].lc].h,tree[tree[r].rc].h)+1;//高度更新
    }
    
    int insert(int r,int x)//插入x
    {
    	if(r == 0)//找到一个空的节点,赋值
    	{
    		tree[++pos].h = 1;//高度初始化
    		tree[pos].v = x;
    		return pos;
    	}
    	if(x < tree[r].v) tree[r].lc = insert(tree[r].lc,x);//插入的数小于根节点,因此在它的左子树插入
    	else if(x > tree[r].v) tree[r].rc = insert(tree[r].rc,x);
    	maintain(r);//维持节点r的平衡
    	return r;//返回新的根节点
    }
    int kth(int r,int k)//查找第k大,tree[r].tot保存了值等于tree[r].v的个数
    {
    	if(k >= tree[tree[r].rc].sz+1&&k <= tree[tree[r].rc].sz+tree[r].tot) return tree[r].v;//找到
    	if(k < tree[tree[r].rc].sz+1) return kth(tree[r].rc,k);//在右子树中
    	else return kth(tree[r].lc,k-tree[tree[r].rc].sz-tree[r].tot);//在左子树中,此种情况下,K值发生变化,因为要求得的那个点它在左子树中的排名发生了变化
    }
    
    int delt(int &r,int x)//删除x
    {
        int tx;
        if(x == tree[r].v||(x<tree[r].v&&tree[r].lc==0)||(x>tree[r].v&&tree[r].rc==0))
        {
            if(tree[r].lc == 0||tree[r].rc == 0)
            {
                tx = tree[r].v;
                r = tree[r].lc+tree[r].rc;
                return tx;
            }
            else tree[r].v = delt(tree[r].lc,x);//用左子树的最大值来替换
        }
        else
        {
            if(x < tree[r].v) tx = delt(tree[r].lc,x);
            else tx = delt(tree[r].rc,x);
        }
        maintain(r);//调整根节点
        return tx;//返回最大值
    }
    void find(int x,int r)
    {
    	int v=tree[r].v;
    	if(x==v) 
    	{
    		prf(x);
    		return;
    	}
    	pf("%d ",v );
    	if(x<v)
    		find(x,tree[r].lc);
    	else
    		find(x,tree[r].rc);
    }
    void prem(int x,int r)//x的前驱
    {
        if(r == 0) return;
        if(tree[r].v < x)
        {
            x1 = tree[r].v;
            prem(x,tree[r].rc);
        }
        else prem(x,tree[r].lc);
    }
    void nexm(int x,int r)//后继
    {
        if(r == 0) return;
        if(tree[r].v > x)
        {
            x2 = tree[r].v;
            nexm(x,tree[r].lc);
        }
        else nexm(x,tree[r].rc);
    }
    
    
  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/wzl19981116/p/9940936.html
Copyright © 2011-2022 走看看