/// <summary> /// 比较两个多维数据封装是否相同 /// </summary> /// <param name="inputOne">输入1</param> /// <param name="inputTwo">输入2</param> /// <param name="ifCheck">是否进行输入检查</param> /// <returns>是否相同</returns> /// <exception cref="ArgumentException">输入为Null或维度不相同或维度为0</exception> internal static bool IfDDimensionIsEqula (IDimensionValueBean inputOne, IDimensionValueBean inputTwo, bool ifCheck = true) { if (ifCheck) { inputCheck(inputOne, inputTwo); } bool returnValue = true; int sumNumber = inputOne.GetSumDimensionNumber(); //检查各维度 for (int tempIndex = 0; tempIndex < sumNumber; tempIndex++) { //当出现不等时 if (CompareResultEnum.Equal != CompareDoulbe (inputOne.GetValueAtDimensionIndex(tempIndex), inputTwo.GetValueAtDimensionIndex(tempIndex))) { returnValue = false; } } return(returnValue); }
/// <summary> /// 计算两个多维数据之间的欧几里得距离 /// </summary> /// <param name="inputOne">输入1</param> /// <param name="inputTwo">输入2</param> /// <returns>欧几里得距离</returns> /// <exception cref="ArgumentException">输入为Null或维度不相同或维度为0</exception> internal static double CalculateDistanceByEuclidean (IDimensionValueBean inputOne, IDimensionValueBean inputTwo, bool ifCheck = true) { if (ifCheck) { inputCheck(inputOne, inputTwo); } double returnValue = 0.0d; int tempSize = inputOne.GetSumDimensionNumber(); //维度距离累计 for (int tempIndex = 0; tempIndex < tempSize; tempIndex++) { returnValue = returnValue + Math.Pow ((inputOne.GetValueAtDimensionIndex(tempIndex) - inputTwo.GetValueAtDimensionIndex(tempIndex)), 2.0D); } //开根号 returnValue = Math.Pow(returnValue, 0.5D); return(returnValue); }
/// <summary> /// 输入检查 /// </summary> /// <param name="inputOne">输入1</param> /// <param name="inputTwo">输入2</param> /// <exception cref="ArgumentException">输入为Null或维度不相同或维度为0</exception> private static void inputCheck(IDimensionValueBean inputOne, IDimensionValueBean inputTwo) { //null值检查 维度相同检查 if (null == inputOne || null == inputTwo || inputOne.GetSumDimensionNumber() != inputTwo.GetSumDimensionNumber() || 0 >= inputOne.GetSumDimensionNumber() ) { throw new ArgumentException(); } }
/// <summary> /// 递归寻找方法 /// </summary> /// <param name="inputNode">输入的节点</param> /// <param name="inputValue">输入的值</param> /// <returns>找到的值若为Null则未找到</returns> private KDTreeNode searchRecursion(KDTreeNode inputNode, IDimensionValueBean inputValue) { if (null == inputNode) { return(null); } //若两节点相同 else if (UtilityMethod.IfDDimensionIsEqula (inputNode.ThisDataValue, inputValue, ifUseRecursionCheck)) { //若节点已删除 if (inputNode.IsDeleteTag) { return(null); } else { return(inputNode); } } else { //获取维度索引 int dimensionIndex = inputNode.NowDimisionIndex; //获取多维数据封装 IDimensionValueBean nodeValue = inputNode.ThisDataValue; //获得当前节点维度的值 double tempDimensionValue = nodeValue.GetValueAtDimensionIndex(dimensionIndex); //获得输入数值在节点维度的值 double tempInputValue = inputValue.GetValueAtDimensionIndex(dimensionIndex); //比较两值 CompareResultEnum compareResult = UtilityMethod.CompareDoulbe(tempInputValue, tempDimensionValue); //比较结果调整 compareResult = equalStrategy(compareResult); //次轮迭代使用的节点 KDTreeNode nextRoundNode = null; //若小于去左节点 if (compareResult == CompareResultEnum.Less) { nextRoundNode = inputNode.LeftChild; } //其它去右节点 else { nextRoundNode = inputNode.RightChild; } //递归执行 return(searchRecursion(nextRoundNode, inputValue)); } }
/// <summary> /// 寻找一个节点 /// </summary> /// <param name="inputValue">输入的多维封装</param> /// <returns>找到的节点</returns> public IDimensionValueBean Search(IDimensionValueBean inputValue) { KDTreeNode tempNode = SearchNode(inputValue); if (null == tempNode) { return(null); } else { return(tempNode.ThisDataValue); } }
/// <summary> /// 节点插入(不进行平衡调整) /// </summary> /// <param name="inputValue">输入的多维数据值</param> /// <returns>插入结果</returns> public bool InsertNoneBlance(IDimensionValueBean inputValue) { //若根节点为Null if (null == rootNode) { inputCheck(inputValue, false); int tempIndex = GetUseDimensionIndex(); KDTreeNode tempTreeNode = new KDTreeNode(inputValue, tempIndex); rootNode = tempTreeNode; nodeCount++; return(true); } else { inputCheck(inputValue); return(insertLoopMethod(inputValue)); } }
/// <summary> /// 节点删除(不进行平衡调整) /// </summary> /// <param name="inputValue"></param> /// <returns></returns> public bool DeleteNoneBlace(IDimensionValueBean inputValue) { //寻找节点 KDTreeNode findedNode = SearchNode(inputValue); //若没找到或目前节点已删除 if (null == findedNode || findedNode.IsDeleteTag == true) { return(false); } //正常情况仅调整标签 else { findedNode.IsDeleteTag = true; nodeCount--; return(true); } }
/// <summary> /// 输入检查 /// </summary> /// <param name="inputValue"></param> private void inputCheck(IDimensionValueBean inputValue, bool ifCheckDimensionNumber = true) { //若需检查维度数 if (ifCheckDimensionNumber) { if (null == inputValue || inputValue.GetSumDimensionNumber() != nodeCount || 0 >= inputValue.GetSumDimensionNumber()) { throw new ArgumentException(); } } else { if (null == inputValue || 0 >= inputValue.GetSumDimensionNumber()) { throw new ArgumentException(); } } }
/// <summary> /// 构造器 /// </summary> /// <param name="inputValue">输入的值</param> public KDTree(IDimensionValueBean inputValue) { InsertNoneBlance(inputValue); }
/// <summary> /// 添加节点的递归方法 /// </summary> /// <param name="inputValue">输入的值</param> /// <returns></returns> private bool insertLoopMethod(IDimensionValueBean inputValue) { //当前递归节点 KDTreeNode currentNode = rootNode; //当前节点的父节点 KDTreeNode parentNode = null; //临时节点 KDTreeNode tempNode = null; //父节点的索引 int tempDimensionIndex = -1; //当前节点应当使用的索引 int tempNowIndex = -1; //表征节点前进方向是否是向左节点 bool ifIsLeftTag = true; double tempParentValue = 0.0d; double tempCurrentValue = 0.0d; CompareResultEnum tempCompareResult; //递归寻找添加位点 while (true) { //当前递归层级节点变为父节点 parentNode = currentNode; //获得父节点的索引 tempDimensionIndex = parentNode.NowDimisionIndex; //获得父节点的值 tempParentValue = parentNode.ThisDataValue. GetValueAtDimensionIndex(tempDimensionIndex); //获取此节点的值 tempCurrentValue = inputValue. GetValueAtDimensionIndex(tempDimensionIndex); //比较节点值 tempCompareResult = UtilityMethod. CompareDoulbe(tempCurrentValue, tempParentValue); //按相等策略调整 tempCompareResult = equalStrategy(tempCompareResult); //小于:左子树方向 if (tempCompareResult == CompareResultEnum.Less) { ifIsLeftTag = true; } //其它右子树方向 else { ifIsLeftTag = false; } //获取父节点相应位置处的子节点 currentNode = parentNode.GetChildNode(ifIsLeftTag); //获得子节点的索引 tempNowIndex = GetUseDimensionInde(tempDimensionIndex); if (null == currentNode) { tempNode = new KDTreeNode(inputValue, tempNowIndex); parentNode.SetChildNode(ifIsLeftTag, tempNode); break; } //若多维值相同 if (UtilityMethod.IfDDimensionIsEqula(currentNode.ThisDataValue, inputValue)) { //若需要替换或当前节点是已删除状态 if (ifEqualValueReplace || currentNode.IsDeleteTag) { currentNode.ThisDataValue = inputValue; currentNode.IsDeleteTag = false; } break; } } nodeCount++; return(true); }
/// <summary> /// 寻找树中相应节点 /// </summary> /// <param name="inputValue">输入的多维数据</param> /// <returns>找到的节点</returns> private KDTreeNode SearchNode(IDimensionValueBean inputValue) { //输入检查 inputCheck(inputValue); return(searchRecursion(rootNode, inputValue)); }
/// <summary> /// 比较输入多维数据是否与此节点数据相同 /// </summary> /// <param name="inputValue">输入的多维数据</param> /// <returns>是否相同</returns> internal bool IfEqula(IDimensionValueBean inputValue) { return(UtilityMethod.IfDDimensionIsEqula(this.thisDataValue, inputValue)); }
/// <summary> /// 构造方法 /// </summary> /// <param name="inputValue">核心数值</param> /// <param name="useIndex">使用的维度索引</param> internal KDTreeNode(IDimensionValueBean inputValue, int useIndex) { this.thisDataValue = inputValue; this.sumDiminsionNumber = this.thisDataValue.GetSumDimensionNumber(); this.nowDimisionIndex = useIndex; }