• 使用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

    有兴趣的朋友,可以看看全部代码

  • 相关阅读:
    自制游戏Zombie代码
    HNOI2020总结
    20200615题解:继续扮演
    20200611题解:树网的核
    历次考试总结
    寒假总结和省选大体规划
    每日总结
    有一种感动叫ACM(记WJMZBMR在成都赛区开幕式上的讲话)
    递推求欧拉函数的最简单的详解
    总结一些好用的C++小技巧
  • 原文地址:https://www.cnblogs.com/sunbingzibo/p/1030644.html
Copyright © 2020-2023  润新知