算法导论-数据结构的扩张

首先给出数据结构的扩张的四个步骤:

1)选择基础的数据结构;

2)确定要在基础数据结构中添加哪些信息;

3)验证可以用基础数据结构上的基本修改操作来维护这些新添加的信息;

4)设计新的操作。


算法导论书上给出的是红黑树的一种扩张-动态顺序统计。

将容量为n的随机样本的各个测定值 (x1,x2,……,xn),从小到大顺序的排列,xi所在的顺序位置就是它的顺序统计量。

动态顺序统计是指,在一个动态的无序的集合中,任意的顺序统计量都可以在O(lgn)时间内确定(线性的结构需要O(n)的时间)。

至于扩展红黑树,最终要的一点就是扩展之后操作已经新域的维护都可以控制在原复杂度内。


扩展步骤如下(c++实现):

1.在红黑树的成员中添加一个int型的size变更。

class BRTreeNode
{
private:
	friend class BRTree;
	int key;
	int size;
	bool color;
	BRTreeNode* left;
	BRTreeNode* right;
	BRTreeNode* parent;
}

2.维护数据域,主要有左旋,右旋。

//左旋节点node
	bool LeftRotate(BRTreeNode* node)
	{
		BRTreeNode*y;
		if(node->right==nil)
		{
			cout<<"can't left rotate!"<<endl;
			return 0;
		}
		y=node->right;
		node->right=y->left;
		if(y->left!=nil)
		{
			y->left->parent=node;
		}
		y->parent=node->parent;
		if(node->parent==nil)
		{
			root=y;
		}
		else if(node->parent->left==node)
		{
			node->parent->left=y;
		}
		else
		{
			node->parent->right=y;
		}
		y->left=node;
		node->parent=y;
		//维护size域
		y->size=node->size;
		node->size=node->left->size+node->right->size+1;
		return 1;
	}
	//右旋节点
	bool RightRotate(BRTreeNode* node)
	{
		if(node->left==nil)
		{
			cout<<"can't rightrotate!"<<endl;
			return 0;
		}
		BRTreeNode* x;
		x=node->left;
		node->left=x->right;
		if(x->right!=nil)
		{
			x->right->parent=node;
		}
		x->parent=node->parent;
		if(node->parent==nil)
		{
			root=x;
		}
		else if(node->parent->left==node)
		{
			node->parent->left=x;
		}
		else
		{
			node->parent->right=x;
		}
		node->parent=x;
		x->right=node;
		//维护size域
		node->size=x->size;
		x->size=x->left->size+x->right->size+1;
		return 1;
	}

3.定义新的操作

1)先根遍历

	void Preorder(BRTreeNode*node)
	{
		if(node!=nil)
		{
			cout<<node->key<<" "<<"size:"<<node->size<<"  ";
			Preorder(node->left);
			Preorder(node->right);
		}
	}

2)查找树中第num小的顺序统计量

BRTreeNode* GetIthnode(BRTreeNode*node,int num)
	{
		int r=node->left->size+1;
		if(r==num)
		{
		    cout<<"Got it!"<<node->key<<endl;
			return node;
		}
		else if(r>num)
		{
			return GetIthnode(node->left,num);
		}
		else
		{
			return GetIthnode(node->right,num-r);
		}
	}

3)确定树中某个以k为key值的元素的秩

int getRank(BRTreeNode*node,int key)
	{
	    int r=node->left->size+1;
	    int k=node->key;
	    if(k==key)
	    {
	        return r;
	    }

	    else if(key<k)
	    {
	        return getRank(node->left,key)-1;
	    }
	    else
	    {
	        return r+getRank(node->right,key);
	    }

	}

最后来测试一下:

int mian()
{    BRTree tree;
    tree.init();
    cout<<"Insert 8 numbers:"<<endl;
    int a[8]={1,2,3,4,5,6,7,8};
    int i;
    for(i=0;i<8;i++)
    {
        tree.Insert(a[i]);
        tree.Preorder(tree.Getroot());
        cout<<"Insert finish"<<endl;
    }
    cout<<"Get No.6 node"<<endl;
    tree.GetIthnode(tree.Getroot(),6);
     cout<<"Get rank of node whick key-value is 6:"<<endl;
    cout<<tree.getRank(tree.Getroot(),6)<<endl;
    return 0;
}

运行结果:


其余的操作可以参考之前的一片文章:

算法导论-红黑树C++实现

参考:

《算法导论》第二版


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值