排序的二叉树中最有效的搜索方式

时间:2018-09-23 09:44:39

标签: c# search binary-tree

假设我有一棵二叉树,我给它的头(左值) 小于右侧的值),树中有ip地址,例如:

       2.1.1.7
      /       \
     /         \
1.1.10.17      3.4.4.5 

我需要编写一个搜索该特定地址的函数。

目前,我所做的是顺序遍历,如:

private HashSet<string> adr = new HashSet<string>();    
void Inorder(Node root){
  if(root.Left != null)
    Inorder(root.Left);
    adr.Add(root.Data);// <----root.Data it's an ip address (string)
  if(root.Right != null)
    Inorder(root.Right);
 }

承包商:

private Node root;// <--- points to the root of the addresses tree

public MyClass{
  Inorder(root);
}

功能:

bool FindAddress(string address){
 return adr.Contains(address);
}

但是在我的方法中,我没有使用树已排序的事实,您是否有更好的性能想法?带循环/递归

2 个答案:

答案 0 :(得分:1)

您可以按以下方式编写FindAddress函数,以利用对数据进行排序的事实:

var node = FindAddress(IPAddress.Parse(searchAddress), assembledTree, new IPAddressCompare());

static Node FindAddress(IPAddress address, Node root, IComparer<IPAddress> addressCompare)
{        
    if (root == null) return null;
    var comp = addressCompare.Compare(IPAddress.Parse(root.Data), address);
    if (comp == 0) return root;
    if (comp < 0) return FindAddress(address, root.Left, addressCompare);
    if (comp > 0) return FindAddress(address, root.Right, addressCompare);
    return null;
}

利用自定义比较器,通过将两个不同的IP地址的表示形式更改为Int32来比较这两个IP地址,并考虑到该地址开头的字节最为重要。

public class IPAddressCompare : IComparer<IPAddress>
{
    public int Compare(IPAddress x, IPAddress y)
    {
        var intA = BitConverter.ToUInt32(x.GetAddressBytes().Reverse().ToArray(), 0);
        var intB = BitConverter.ToUInt32(y.GetAddressBytes().Reverse().ToArray(), 0);
        return intB.CompareTo(intA);
    }
}

完整示例:https://dotnetfiddle.net/viRy5b

答案 1 :(得分:1)

我将使用简单列表,然后将二进制搜索与比较器一起使用。避免了创建自己的树的麻烦,并且性能是最好的。

using System;
using System.Collections.Generic;
using System.Net;



class app
{    
    static void Main()
    {
        List<IPAddress> sortedIPs = new List<IPAddress>();

        AddToList(sortedIPs, new byte[4] { 6, 10, 54, 100 });
        AddToList(sortedIPs, new byte[4] { 143, 0, 254, 10 });
        AddToList(sortedIPs, new byte[4] { 48, 0, 0, 1 });
        AddToList(sortedIPs, new byte[4] { 0, 0, 82, 19 });
        AddToList(sortedIPs, new byte[4] { 13, 0, 254, 1 });
        AddToList(sortedIPs, new byte[4] { 63, 93, 4, 111 });
        AddToList(sortedIPs, new byte[4] { 98, 3, 74, 1 });
        AddToList(sortedIPs, new byte[4] { 98, 4, 74, 1 });
        AddToList(sortedIPs, new byte[4] { 98, 3, 14, 1 });
        AddToList(sortedIPs, new byte[4] { 98, 3, 14, 2 });
        AddToList(sortedIPs, new byte[4] { 7, 175, 25, 65 });
        AddToList(sortedIPs, new byte[4] { 46, 86, 21, 91 });

        IPAddress findAddress = new IPAddress(new byte[4] { 48, 0, 0, 1 });

        int index = sortedIPs.BinarySearch(findAddress, new IPAddressComparer());

    }

    private static void AddToList(List<IPAddress> list, byte[] address)
    {
        IPAddress a1 = new IPAddress(address);
        IPAddressComparer ipc = new IPAddressComparer();
        int index = list.BinarySearch(a1, ipc);
        if (index >= 0) throw new Exception("IP address already exists in list");
        list.Insert(~index, a1);
    }

    public class IPAddressComparer : IComparer<IPAddress>
    {
        public int Compare(IPAddress x, IPAddress y)
        {
            byte[] xb = x.GetAddressBytes();
            byte[] yb = y.GetAddressBytes();
            for (int i = 0; i < 4; i++)
            {
                int result = xb[i].CompareTo(yb[i]);
                if (result != 0) return result; 
            }
            return 0;
        }
    }

}