假设我有一棵二叉树,我给它的头(左值) 小于右侧的值),树中有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);
}
但是在我的方法中,我没有使用树已排序的事实,您是否有更好的性能想法?带循环/递归
答案 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);
}
}
答案 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;
}
}
}