C#通過KD樹進行距離最近點的尋找的執行個體分析

來源:互聯網
上載者:User
這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的尋找,具有一定的參考價值,感興趣的小夥伴們可以參考一下

本文首先介紹Kd-Tree的構造方法,然後介紹Kd-Tree的搜尋流程及代碼實現,最後給出本人利用C#語言實現的二維KD樹代碼。這也是我自己動手實現的第一個樹形的資料結構。理解上難免會有偏差,敬請各位多多斧正。

1. KD樹介紹

Kd-Tree(KD樹),即K-dimensional tree,是一種高維索引樹形資料結構,常用於在大規模的高維資料空間進行最鄰近尋找和近似最鄰近尋找。我實現的KD樹是二維的Kd - tree。目的是在點集中尋找最近點。參考資料是Kd-Tree的百度百科。並且根據百度百科的邏輯組織了代碼。

2. KD樹的數學解釋

3. KD樹的構造方法

這裡是用的二維點集進行構造Kd-tree。三維的與此類似。
樹中每個節點的資料類型:


public class KDTreeNode  {    /// <summary>    /// 分裂點    /// </summary>    public Point pisionPoint { get; set; }    /// <summary>    /// 分裂類型    /// </summary>    public EnumpisionType pisionType { get; set; }    /// <summary>    /// 左子節點    /// </summary>    public KDTreeNode LeftChild { get; set; }    /// <summary>    /// 右子節點    /// </summary>    public KDTreeNode RightChild { get; set; }  }

3.1 KD樹構造邏輯流程

  • 將所有的點放入集合a中

  • 對集合所有點的X座標求得方差xv,Y座標求得方差yv

  • 如果xv > yv,則對集合a根據X座標進行排序。如果 yv > xv,則對集合a根據y座標進行排序。

  • 得到排序後a集合的中位元m。則以m為斷點,將[0,m-2]索引的點放到a1集合中。將[m,a.count]索引的點放到a2的集合中(m點的索引為m-1)。

  • 構建節點,節點的值為a[m-1],如果操作集合中節點的個數大於1,則左節點對[0,m-2]重複2-5步,右節點為對[m,a.count]重複2-5步;反之,則該節點為葉子節點。

3.2 代碼實現


private KDTreeNode CreateTreeNode(List<Point> pointList){  if (pointList.Count > 0)  {    // 計算方差    double xObtainVariance = ObtainVariance(CreateXList(pointList));    double yObtainVariance = ObtainVariance(CreateYList(pointList));    // 根據方差確定分裂維度    EnumpisionType pisionType = SortListByXOrYVariances(xObtainVariance,    yObtainVariance, ref pointList);    // 獲得中位元    Point medianPoint = ObtainMedian(pointList);    int medianIndex = pointList.Count / 2;    // 構建節點    KDTreeNode treeNode = new KDTreeNode()    {      pisionPoint = medianPoint,      pisionType = pisionType,      LeftChild = CreateTreeNode(pointList.Take(medianIndex).ToList()),      RightChild = CreateTreeNode(pointList.Skip(medianIndex + 1).ToList())    };    return treeNode;  }  else  {    return null;  }}

4. KD樹搜尋方法

Kd-Tree的總體搜尋流程先根據普通的尋找找到一個最近的葉子節點。但是這個葉子節點不一定是最近的點。再進行回溯的操作找到最近點。

4.1 KD樹搜尋邏輯流程

  • 對於根據點集構建的樹t,以及尋找點p.將根節點作為節點t進行如下的操作

  • 如果t為葉子節點。則得到最近點n的值為t的分裂點的值,跳到第5步;如果t不是葉子節點,進行第3步

  • 則確定t的分裂方式,如果是按照x軸進行分裂,則用p的x值與節點的分裂點的x值進行比較,反之則進行Y座標的比較

  • 如果p的比較值小於t的比較值,則將t指定為t的左孩子節點。反之將t指定為t的右孩子節點,執行第2步

  • 定義檢索點m,將m設定為n

  • 計算m與p的距離d1,n與m的距離d2。

  • 如果d1 >= d2且有父節點,則將m的父節點作為m的值執行5步,若沒有父節點,則得到真正的最近點TN; 如果d1 < d2就表示n點不是最近點,執行第8步

  • 若n有兄弟節點,則 n = n的兄弟節點;若n沒有兄弟節點,則 n = n的父節點。刪除原來的n節點。將m的值設定為新的n節點;執行第6步。

4.2 代碼實現


public Point FindNearest(Point searchPoint){  // 按照尋找方式尋找最近點  Point nearestPoint = DFSSearch(this.rootNode, searchPoint);    // 進行回溯  return BacktrcakSearch(searchPoint, nearestPoint);}private Point DFSSearch(KDTreeNode node,Point searchPoint,bool pushStack = true){  if(pushStack == true)  {    // 利用堆棧記錄查詢的路徑,由於樹節點中沒有記載父節點的原因    backtrackStack.Push(node);  }  if (node.pisionType == EnumpisionType.X)  {    return DFSXsearch(node,searchPoint);  }  else  {    return DFSYsearch(node, searchPoint);  }}private Point BacktrcakSearch(Point searchPoint,Point nearestPoint){  // 如果記錄路徑的堆棧為空白則表示已經回溯到根節點,則查到的最近點就是真正的最近點  if (backtrackStack.IsEmpty())  {    return nearestPoint;  }  else  {    KDTreeNode trackNode = backtrackStack.Pop();        // 分別求回溯點與最近點距尋找點的距離    double backtrackDistance = ObtainDistanFromTwoPoint(searchPoint,     trackNode.pisionPoint);    double nearestPointDistance = ObtainDistanFromTwoPoint(searchPoint, nearestPoint);        if (backtrackDistance < nearestPointDistance)    {      // 深拷貝節點的目的是為了避免損壞樹      KDTreeNode searchNode = new KDTreeNode()      {        pisionPoint = trackNode.pisionPoint,        pisionType = trackNode.pisionType,        LeftChild = trackNode.LeftChild,        RightChild = trackNode.RightChild      };      nearestPoint = DFSBackTrackingSearch(searchNode, searchPoint);   }   // 遞迴到根節點   return BacktrcakSearch(searchPoint, nearestPoint);  }}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.