[入门] D语言的红黑树的添加和删除操作,谁能教教我怎么从上倒下一次遍历完成的算法

myyxm 2007-12-29
module dstl.drbtree;
private import std.stdio;
private import dstl.dfreelist;
private enum rb { red = 0 , block}
private enum lr { left = 0,right = 1,none = 2}
public class rbTreeNode(T)
{
	T value;
	private rbTreeNode!(T) left,right,parent;
	private rb color;
	public void set(T v,rbTreeNode!(T) l = null,rbTreeNode!(T) r = null,rbTreeNode!(T) p = null,rb c = rb.red)
	{
		value = v;left = l;right =r;parent = p;color = c;
	}
	public void set(rbTreeNode!(T) l = null,rbTreeNode!(T) r = null,rbTreeNode!(T) p = null,rb c = rb.red)
	{
		left = l;right =r;parent = p;color = c;
	}
	public this()
	{
	}

	mixin freelist!(rbTreeNode!(T));
}


public class rbTree(T)
{
	private alias rbTreeNode!(T) rbnode;

	private rbnode m_head,nullnode;

	public this(T value)
	{
		nullnode = rbnode.alloc();
		nullnode.set(null,null,null,rb.block);
		m_head = rbnode.alloc();
		m_head.set(value,nullnode,nullnode,null,rb.block);
		nullnode.parent = m_head;
	}
	public void list(rbTreeNode!(T) node = null)
	{
		static int i=0;
		if(node is null)
			node = m_head;
		++i;
		if(node !is nullnode)
		{
			if(node.parent is null)
				node.parent = nullnode;
			writefln("i:%d,node.value:%d,node.color:%d\tnode.left:%d,node.right:%d,node.parent:%d",i,node.value,node.color,node.left.value,node.right.value,node.parent.value);
			if(node.parent is nullnode)
				node.parent = null;
		}
		else
			return;
		list(node.left);
		list(node.right);
		
	}
	public void insert(T value)
	{
		nullnode.set(null,null,null,rb.block);
		debug
		{
			writefln("root value:%d",m_head.value);
			writefln("insert value:%d",value);
		}
		//寻找插入地方
		rbnode node = m_head;
		rbnode currect = null;
		while(node !is nullnode)
		{
			currect = node;
			if(node.value > value)
				node = node.left;
			else if(node.value < value)
				node = node.right;
			else
				return;
		}
		//当前位置为空,表明树是空的.
		if(currect is null)
		{
			m_head = rbnode.alloc();
			m_head.set(value,nullnode,nullnode,null,rb.block);
			return;
		}
		node = rbnode.alloc();
		node.set(value,nullnode,nullnode,currect,rb.red);
		if(currect.value > value)
			currect.left = node;
		else
			currect.right = node;

		
		
		while(node.parent.color is rb.red)
		{
			//父亲和叔叔都是红色
			if(node.parent.parent.left.color is node.parent.parent.right.color)
			{
				node.parent.parent.left.color = node.parent.parent.right.color = rb.block;
				node.parent.parent.color = rb.red;
				node = node.parent.parent;
			} 
			//开始旋转
			else
			{
				
				//父亲是爷爷的左子树
				if(node.parent is node.parent.parent.left)
				{
					debug
					{
					writefln("...father is grand left,node value:%d,father value:%d,grand value:%d",node.value,node.parent.value,node.parent.parent.value);
					}
					if(node is node.parent.right)
					{
						
						rotateLeft(node.parent);
						node = node.left;
						debug
						{
							writefln(".....father is grand left,and node is father right,node value:%d,father value:%d,grand value:%d",node.value,node.parent.value,node.parent.parent.value);
						}
					}
					rotateRight(node.parent.parent);
					
					
				}
				else if(node.parent is node.parent.parent.right)
				{
					debug
					{
					writefln("...father is grand right,node value:%d,father value:%d,grand value:%d",node.value,node.parent.value,node.parent.parent.value);
					}
					if(node is node.parent.left)
					{
						this.rotateRight(node.parent);
						node = node.right;
						debug
						{
							writefln(".....father is grand right,and node is father left,node value:%d,father value:%d,grand value:%d",node.value,node.parent.value,node.parent.parent.value);
						}
					}
					rotateLeft(node.parent.parent);
				}
				node = node.parent;
				node.left.color = node.right.color = rb.block;
				node.color = rb.red;
				debug
				{
					writefln("...flip end,node value:%d,left value:%d,right value:%d",node.value,node.left.value,node.right.value);
				}
				
			}
			if(node is m_head)
			{
				node.color = rb.block;
				break;
			}
		}
		
	}

	public void remove(T value)
	{
		//查询删除的位置
		nullnode.set(null,null,null,rb.block);
		rbnode delnode = m_head;
		rbnode x;
		rbnode currect = null;
		while(delnode !is nullnode)
		{
			if(delnode.value > value)
				delnode = delnode.left;
			else if(delnode.value < value)
				delnode = delnode.right;
			else
				break;
		}
		if(delnode is nullnode)
			throw new Exception("delete error");
		//如果当前节点有左右孩子
		currect = delnode;
		if(currect.left !is nullnode && currect.right ! is nullnode)
		{
			delnode = currect.right;
			while(delnode.left !is nullnode)
				delnode = delnode.left;
			currect.value = delnode.value;
			currect = delnode;
		}
		//寻找结束,删除delnode,并且保留替换的节点
		if(currect.left !is nullnode)
		{
			if(currect is currect.parent.left)
				currect.parent.left = currect.left;
			else
				currect.parent.right = currect.left;
			currect.left.parent = currect.parent;
			delnode = currect.left;
		}
		else if(currect.right !is nullnode)
		{
			if(currect is currect.parent.left)
				currect.parent.left = currect.right;
			else
				currect.parent.right = currect.right;
			currect.right.parent = currect.parent;
			delnode = currect.right;
		}
		else
		{
			if(currect is currect.parent.left)
				currect.parent.left = nullnode;
			else
				currect.parent.right = nullnode;
			delnode = nullnode;
			delnode.parent = currect.parent;
			//writefln("currect.value:%d,currect.parent.value:%d",currect.value,currect.parent.value);
			
		}
		//writefln("delnode.parent:%d\t delnode.value:%d,delnode.color:%d",delnode.parent.value,delnode.value,delnode.color);
		/*
			currect 为删除的节点
			delnode 为替代的节点
			翻转颜色,恢复红黑树性质
		*/
		if(currect.color is rb.block)
		{
			while(1)
			{
				if(delnode.color is rb.red || delnode is m_head)
				{
					delnode.color = rb.block;
					break;
				}
				//代替节点为父节点的左子树
				if(delnode is delnode.parent.left)
				{

					debug
					{
						writefln("delnode is delnode.parent.left");
						writefln("delnode.color: %d\tdelnode.value:%d",delnode.color,delnode.value);
						writefln("delnode.parent.color:%d\tdelnode.parent.value:%d",delnode.parent.color,delnode.parent.value);
						writefln("delnode.parent.right.color:%d\tdelnode.parent.left.value:%d",delnode.parent.right.color,delnode.parent.right.value);
						writefln("delnode.parent.right.left.color:%d\tdelnode.parent.right.left.value:%d",delnode.parent.right.left.color,delnode.parent.right.left.value);
						writefln("delnode.parent.right.right.color:%d\tdelnode.parent.right.right.value:%d",delnode.parent.right.right.color,delnode.parent.right.right.value);
					}
					
					
					//case 1:兄弟节点为红色
					if(delnode.parent.right.color is rb.red)
					{
						//调整颜色
						delnode.parent.color = rb.red;
						delnode.parent.right.color = rb.block;
						//对父亲节点进行做旋转
						rotateLeft(delnode.parent);
						
					}
					//case 2,3,4:兄弟节点是黑色
					if(delnode.parent.right.color is rb.block)
					{
						//case 2:子侄节点都是黑色
						if(delnode.parent.right.left.color is rb.block && delnode.parent.right.right.color is rb.block)
						{
							delnode.parent.right.color = rb.red;
							delnode = delnode.parent;
							continue;
						}
						//case 3:
						if(delnode.parent.right.left.color is rb.red && delnode.parent.right.right.color is rb.block)
						{
							delnode.parent.right.left.color = rb.block;
							delnode.parent.right.color = rb.red;
							rotateRight(delnode.parent.right);
						}
						if(delnode.parent.right.right.color is rb.red && delnode.parent.right.left.color is rb.block)
						{
							delnode.parent.right.right.color = rb.block;
							delnode.parent.right.color = rb.red;
							rotateLeft(delnode.parent);
							break;
						}
					}
				}
				if(delnode is delnode.parent.right)
				{
					debug
					{
						writefln("delnode is delnode.parent.right");
						writefln("delnode.color: %d\tdelnode.value:%d",delnode.color,delnode.value);
						writefln("delnode.parent.color:%d\tdelnode.parent.value:%d",delnode.parent.color,delnode.parent.value);
						writefln("delnode.parent.left.color:%d\tdelnode.parent.left.value:%d",delnode.parent.left.color,delnode.parent.left.value);
						writefln("delnode.parent.left.left.color:%d\tdelnode.parent.left.left.value:%d",delnode.parent.left.left.color,delnode.parent.left.left.value);
						writefln("delnode.parent.left.right.color:%d\tdelnode.parent.left.right.value:%d",delnode.parent.left.right.color,delnode.parent.left.right.value);
					}
					
					//case 1:
					if(delnode.parent.left.color is rb.red)
					{
						delnode.parent.left.color = rb.block;
						delnode.parent.color = rb.red;
						rotateRight(delnode.parent);
					}
					//case 2,3,4:
					if(delnode.parent.left.color is rb.block)
					{   
					    
						//case 2:
						if(delnode.parent.left.left.color is rb.block && delnode.parent.left.right.color is rb.block)
						{
							delnode.parent.left.color = rb.red;
							delnode = delnode.parent;
							continue;
						}
						//case 3:
						if(delnode.parent.left.right.color is rb.red && delnode.parent.left.left.color is rb.block)
						{
							//writefln("run case 2");
							delnode.parent.left.right.color = rb.block;
							delnode.parent.left.color = rb.red;
							rotateLeft(delnode.parent.left);
							//writefln("run case 2");
						}
						//case 4:
						if(delnode.parent.left.left.color is rb.red && delnode.parent.left.right.color is rb.block)
						{
							delnode.parent.left.left.color = rb.block;
							delnode.parent.left.color = rb.red;
							rotateRight(delnode.parent);
							//writefln("run case 4");
							break;
						}
					}
				}
			}
		}
		
		rbnode.release(currect);
	}
	/*
	           x                  x
	          /                  /
			node 			    n
			/	\     ->       / \
		   a	 n           node c
			    / \          / \
			   b   c        a   b
    不改变node的指向
	*/
	public void rotateLeft(rbnode node)
	{
		rbnode n = node.right;
		node.right = n.left;
		node.right.parent = node;
		n.left = node;
		n.parent = node.parent;
		node.parent = n;
		if(n.parent !is null)
		{
			if(n.parent.left is node)
				n.parent.left = n;
			else
				n.parent.right = n;
		}
		else
			m_head = n;
	}
	/*
             x                           x
			  \                           \
			  node         ->              n
			  / \                         / \
			 n   a                       b  node
            / \                             / \  
           b   c                           c   a   

    不改变node的指向
	*/
	public void rotateRight(rbnode node)
	{
		rbnode n = node.left;
		node.left = n.right;
		node.left.parent = node;
		n.right = node;
		//writefln("n value:%d",n.value);
		n.parent = node.parent;
		if(node is null)
			writefln("node is null");
		node.parent = n;
		
		if(n.parent !is null)
		{
			if(n.parent.left is node)
				n.parent.left = n;
			else
				n.parent.right = n;
		}
		else
		{
			m_head = n;
		}
	}
}

//测试

	rbTreeNode!(int) node = rbTreeNode!(int).alloc();

	node.set(1,node,node,node);
	rbTree!(int) rb = new rbTree!(int)(100);

	rb.insert(50);
	rb.insert(77);
	rb.insert(7);
	rb.insert(66);
	rb.insert(122);
	rb.insert(18);
	rb.insert(32);
	rb.insert(246);
	rb.remove(66);
	rb.insert(66);
	rb.insert(98);
	rb.list();
	getch();
	return 0;

输出:

root value:100
insert value:50
root value:100
insert value:77
...father is grand left,node value:77,father value:50,grand value:100
.....father is grand left,and node is father right,node value:50,father value:77
,grand value:100
...flip end,node value:77,left value:50,right value:100
root value:77
insert value:7
root value:77
insert value:66
root value:77
insert value:122
root value:77
insert value:18
root value:77
insert value:32
...father is grand right,node value:32,father value:18,grand value:7
...flip end,node value:18,left value:7,right value:32
...father is grand left,node value:18,father value:50,grand value:77
...flip end,node value:50,left value:18,right value:77
root value:50
insert value:246
...father is grand right,node value:246,father value:122,grand value:100
...flip end,node value:122,left value:100,right value:246
delnode is delnode.parent.left
delnode.color: 1        delnode.value:0
delnode.parent.color:1  delnode.parent.value:77
delnode.parent.right.color:0    delnode.parent.left.value:122
delnode.parent.right.left.color:1       delnode.parent.right.left.value:100
delnode.parent.right.right.color:1      delnode.parent.right.right.value:246
root value:50
insert value:66
i:1,node.value:50,node.color:1  node.left:18,node.right:122,node.parent:0
i:2,node.value:18,node.color:1  node.left:7,node.right:32,node.parent:50
i:3,node.value:7,node.color:1   node.left:0,node.right:0,node.parent:18
i:6,node.value:32,node.color:1  node.left:0,node.right:0,node.parent:18
i:9,node.value:122,node.color:1 node.left:77,node.right:246,node.parent:50
i:10,node.value:77,node.color:1 node.left:66,node.right:100,node.parent:122
i:11,node.value:66,node.color:0 node.left:0,node.right:0,node.parent:77
i:14,node.value:100,node.color:0        node.left:0,node.right:0,node.parent:77
i:17,node.value:246,node.color:1        node.left:0,node.right:0,node.parent:122

please input any key to end ........

E:\dprjects\dstl>dstl
root value:100
insert value:50
root value:100
insert value:77
...father is grand left,node value:77,father value:50,grand value:100
.....father is grand left,and node is father right,node value:50,father value:77
,grand value:100
...flip end,node value:77,left value:50,right value:100
root value:77
insert value:7
root value:77
insert value:66
root value:77
insert value:122
root value:77
insert value:18
root value:77
insert value:32
...father is grand right,node value:32,father value:18,grand value:7
...flip end,node value:18,left value:7,right value:32
...father is grand left,node value:18,father value:50,grand value:77
...flip end,node value:50,left value:18,right value:77
root value:50
insert value:246
...father is grand right,node value:246,father value:122,grand value:100
...flip end,node value:122,left value:100,right value:246
delnode is delnode.parent.left
delnode.color: 1        delnode.value:0
delnode.parent.color:1  delnode.parent.value:77
delnode.parent.right.color:0    delnode.parent.left.value:122
delnode.parent.right.left.color:1       delnode.parent.right.left.value:100
delnode.parent.right.right.color:1      delnode.parent.right.right.value:246
root value:50
insert value:66
root value:50
insert value:98
i:1,node.value:50,node.color:1  node.left:18,node.right:122,node.parent:0
i:2,node.value:18,node.color:1  node.left:7,node.right:32,node.parent:50
i:3,node.value:7,node.color:1   node.left:0,node.right:0,node.parent:18
i:6,node.value:32,node.color:1  node.left:0,node.right:0,node.parent:18
i:9,node.value:122,node.color:1 node.left:77,node.right:246,node.parent:50
i:10,node.value:77,node.color:0 node.left:66,node.right:100,node.parent:122
i:11,node.value:66,node.color:1 node.left:0,node.right:0,node.parent:77
i:14,node.value:100,node.color:1        node.left:98,node.right:0,node.parent:77

i:15,node.value:98,node.color:0 node.left:0,node.right:0,node.parent:100
i:19,node.value:246,node.color:1        node.left:0,node.right:0,node.parent:122


算法来源:http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=639737&page=0&view=collapsed&sb=5&o=7&fpart=
oldrev 2007-12-29
参考这个:

http://www.dsource.org/projects/arclib/browser/trunk/arclib/arc/templates/redblacktree.d
Global site tag (gtag.js) - Google Analytics