使用HashTable来实现树的查找

设计模式中,讲了一个组合模式,并给出了例子,但是应用中还是有一些不方便的
比如,树的遍历与查找,我最近在一个程序中遇到了一个树形问题,使用了组合模式,但是查找节点的时候,遇到了一点困难,
所以想一个办法来解决,就是使用hash表的方法来解决,
上下文(程序中使用的是.net framework1.1),为了兼容性,所以没有使用泛型:-<

需求
1.实现一个倒置的树,能从一个节点,找到他的父节点,及他的子节点(个数没有限制)
2.能快速地查找树中的任意一个节点,
3.能判断出一个节点是否从属于另一个节点,

解决的步骤
1.构造树
2.在结点类中声明一个静态的hashtable表,来放置节点
3.将树中的所有节点放在hashtable中
(每一个节点,都有一个唯一的值,由于是从数据库中取出的数据,所以每一条数据的主键就可以放到hashtable中),


这个类的好处,用一个类的静态变量来存储所有的节点,用hashtable中的查找算法,取代了树的查找,

但是有一个坏处这个树在应用中只能实例化一次,而不能多次实例化,为什么呢?
因为类中用来实现查找的hashtable是一个静态变量,这个变量不会释放自己,所以多次实例化,
而其中的无素不变,可能会在使用这程中出现问题,由于我使用的上下文中不存在这种情况,
所以我就可以安心的使用,这样一个类

有了需求就可以写测试了
以下是测试代码

  [TestFixture]
    
public   class  TestNode
    
{
        
private AbstractNode root;
        
private AbstractNode ceo;
        
private AbstractNode market;
        
private AbstractNode product;

        [SetUp]
        
public void InitTree()
        
{
            root 
= new AbstractNode(null,"root");
            ceo 
= new AbstractNode(root,"ceo");
            market 
= new AbstractNode(ceo,"market");
            product 
= new AbstractNode(ceo,"product"); 
            

            
for (int i = 8; i < 12; i++)
            
{
                AbstractNode ab 
= new AbstractNode(market,i.ToString());
                 market.AddChild(ab);
            }
 


            
for (int i = 0; i < 3; i++)
            
{
                AbstractNode ab 
= new AbstractNode(product,i.ToString());
                product.AddChild(ab);
            }


            root.AddChild(ceo);
            ceo.AddChild(product);
            ceo.AddChild(market);

        }


        [Test]
        
public void TestHasChild()
        
{
            Assert.IsTrue(root.HasChild(market),
"root must have market");
            AbstractNode ab
=new AbstractNode("9");
            Assert.IsTrue(root.HasChild(ab), 
"9 is under market");
            Assert.IsFalse(product.HasChild(ab), 
"9 is under market");
        }

        [Test]
        
public void TestChildPath()
        
{
            AbstractNode ab 
= new AbstractNode("9");
            Queue path 
= root.FindChild(ab);
            Assert.IsTrue(path.Count 
> 0"9 shold has a parent");
            Assert.IsTrue(path.Count 
== 3"deepth is 2");

            
int levelcount = path.Count;
            
while (path.Count > 0)
            
{
                AbstractNode pathab 
= path.Dequeue() as AbstractNode;
                
if (pathab == null)
                    LogHelper.LogIt(
"it is the head");
                
else
                    LogHelper.LogIt(
"this is the :" + levelcount.ToString() + " node and its key is: " + pathab.Key);
                levelcount
++;
            }

        }

}

 有了测试代码,可以设计一个类了,这个类是模式的抽象(组合模式)

类图

using  System;
using  System.Text;
using  System.Collections;

namespace  cdtest
{
    
public class AbstractNode
    
{
        
public AbstractNode()
        
{
            childear 
= new ArrayList();
            childpath 
= new Queue();

        }

        
public AbstractNode(string pkey)
            : 
this()
        
{
            
this.key = pkey;
        }



        
public AbstractNode(AbstractNode pparent, string pkey)
            : 
this(pkey)
        
{
            parent 
= pparent;
            
if (pparent != null)
                pparent.AddChild(
this);
        }


         

        
/// <summary>
        
/// store level
        
/// </summary>

        private int level;
        
/// <summary>
        
/// used to store the key and object
        
/// </summary>

        protected static Hashtable hs=new Hashtable();
        
/// <summary>
        
/// store child
        
/// </summary>

        private ArrayList childear;
        
/// <summary>
        
/// store parent
        
/// </summary>

        private AbstractNode parent;
        
/// <summary>
        
/// store key
        
/// </summary>

        private string key;
        
/// <summary>
        
/// store the path to the child
        
/// </summary>

        private Queue childpath;

        
/// <summary>
        
/// node level
        
/// </summary>

        public int Level
        
{
            
get
            
{
                
return level;
            }

            
set
            
{
                level 
= value;
            }

        }


        
/// <summary>
        
/// node parent
        
/// </summary>

        public AbstractNode Parent
        
{
            
get
            
{
                
return parent;
            }

        }


        
/// <summary>
        
/// key of this node
        
/// </summary>

        public String Key
        
{
            
get
            
{
                
return key;
            }

            
set
            
{
                key 
= value;
            }

        }


        
public Hashtable Nodes
        
{
            
get
            
{
                
return hs;
            }

        }


        
/// <summary>
        
/// has child or not
        
/// </summary>

        public bool IsLeaf
        
{
            
get
            
{
                
return Nodes.Count == 0;
            }

             
        }


        
public IEnumerator GetChild()
        
{
            
return childear.GetEnumerator();
        }


        
public void AddChild(AbstractNode childnode)
        
{
            childear.Add(childnode);
            
if (!hs.ContainsKey(childnode.Key))
            
{
                childnode.Level 
= this.level + 1;
                hs.Add(childnode.key, childnode);                
            }

        }


        
public bool HasChild(AbstractNode pchild)
        
{
            
if (pchild.Key == this.Key)
                
return true;

            
bool found=false;
            AbstractNode subordinates 
= null;
            IEnumerator ienu 
= GetChild();
            
while (!found&& ienu.MoveNext())
            
{
                subordinates 
= ienu.Current as AbstractNode;
                found 
= subordinates.HasChild(pchild); 
            }

            
return found;
        }


        
public Queue FindChild(AbstractNode pchild)
        
{
            AbstractNode ab 
= Nodes[pchild.Key] as AbstractNode;
            
while (ab != null)
            
{
                AbstractNode parentab 
= ab.Parent;
                
//we use null as node root
                if (parentab != null)
                
{
                    childpath.Enqueue(parentab);
                }

                ab 
= parentab;
            }


            
return childpath;
        }

    }

}

有了模式的抽象,就可以以到现实中的例子做实验了,如部门,及员式
部门下还可以细分部门,员工下边还可管理员工,等等

代码比较多,就不贴了

有了现实中的例子,那么我们就可以应用的不同的应用程序中去了
如:使用数据库技术存储的DBDepartment,或者使用Xml文件存储的XmlDepartment
DBDepartment:Department
XmlDepartment:Department

 有兴趣的朋友,可以看看全部代码,以后会在空间中贴出

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值