C#實現二叉查詢樹
二叉查詢樹(binary search tree)
1)概念:對於樹中的每個節點n,其左子節點中儲存的所有數值都小於n儲存的數值,右子節點儲存的數值都大於n儲存的數值。
2)二叉查詢樹可以實現更為優越的查詢效能,主要實現方式有陣列和連結串列結構,相比較而言,連結串列實現更為容易,因為陣列實現刪除和新增功能需要移動陣列元素(如填補刪除空位等)
今天下午在列印問題搞定後用C#實現了一下,比java版本比較有趣的使用C#的delegate來代替遍歷二叉樹時的visit方法,這樣一來可以在遍歷時對節點進行你所想要的任何操作。我們知道C#的delegate是型別化的函式指標,而C++的函式指標可以模仿動態語言的閉包或者匿名函式。這裡也有這樣的味道。
程式碼如下,只實現了整數型的,節點定義:
public class BSTIntNode
{
public int value;
public BSTIntNode left;
public BSTIntNode right;
public BSTIntNode(int value, BSTIntNode left, BSTIntNode right)
{
this.value = value;
this.left = left;
this.right = right;
}
public BSTIntNode(int value)
{
this.value = value;
this.left = null;
this.right = null;
}
}
{
public int value;
public BSTIntNode left;
public BSTIntNode right;
public BSTIntNode(int value, BSTIntNode left, BSTIntNode right)
{
this.value = value;
this.left = left;
this.right = right;
}
public BSTIntNode(int value)
{
this.value = value;
this.left = null;
this.right = null;
}
}
然後定義一個Delegate,作為遍歷時的訪問方法:
public delegate void Visit(BSTIntNode node);
然後就是二叉樹的實現,刪除演算法只實現了複製刪除法:
public class BSTIntTree
{
protected BSTIntNode root;
public Visit visit;
public BSTIntTree()
{
this.root = null;
}
private BSTIntNode Search(BSTIntNode node, int el)
{
while (node != null)
{
if (el == node.value)
return node;
else if (el < node.value)
node = node.left;
else
node = node.right;
}
return null;
}
//查詢
public BSTIntNode Search(int el)
{
return Search(root, el);
}
//廣度優先遍歷,利用佇列實現,至上而下,至左而右
public void BreadthFirst()
{
BSTIntNode p = root;
Queue queue = new ListQueue();
if (p != null)
{
queue.Enqueue(p);
while (!queue.IsEmpty())
{
p = (BSTIntNode)queue.Dequeue();
visit(p);
if (p.left != null)
queue.Enqueue(p.left);
if (p.right != null)
queue.Enqueue(p.right);
}
}
}
//深度優先遍歷,遞迴實現線序,中序和後序
//先序
protected void PreOrder(BSTIntNode p)
{
if (p != null)
{
visit(p);
PreOrder(p.left);
PreOrder(p.right);
}
}
public void PreOrder()
{
PreOrder(root);
}
//中序
protected void InOrder(BSTIntNode p)
{
if (p != null)
{
InOrder(p.left);
visit(p);
InOrder(p.right);
}
}
public void InOrder()
{
InOrder(root);
}
//後序
protected void PostOrder(BSTIntNode p)
{
if (p != null)
{
PostOrder(p.left);
PostOrder(p.right);
visit(p);
}
}
public void PostOrder()
{
PostOrder(root);
}
//插入節點操作
public void Insert(int el)
{
BSTIntNode p = root, prev = null;
//查詢節點位置
while (p != null)
{
prev = p;
if (p.value < el)
p = p.right;
else
p = p.left;
}
if (root == null) //空樹
root = new BSTIntNode(el);
else if (prev.value < el) //大於節點,插入右子樹
prev.right = new BSTIntNode(el);
else
prev.left = new BSTIntNode(el);
}
//複製刪除法的實現,歸併刪除法可能改變樹的高度
public void Delete(int el)
{
BSTIntNode node, p = root, prev = null;
//查詢節點位置
while (p != null&&p.value!=el)
{
prev = p;
if (p.value < el)
p = p.right;
else
p = p.left;
}
node = p;
if (p != null && p.value == el)
{
if (node.right == null)
node = node.left;
else if (node.left == null)
node = node.right;
else
{
BSTIntNode temp = node.left;
BSTIntNode previous = node;
while (temp.right != null) //查詢左位元組數的最右子節點
{
previous = temp;
temp = temp.right;
}
node.value = temp.value;
if (previous == node)
previous.left = temp.left;
else
previous.right = temp.left;
}
if (p == root)
root = node;
else if (prev.left == p)
prev.left = node;
else
prev.right = node;
}
else if (root != null)
{
Console.WriteLine("沒有找到節點:{0}", el);
}
else
Console.WriteLine("樹為空!");
}
}
{
protected BSTIntNode root;
public Visit visit;
public BSTIntTree()
{
this.root = null;
}
private BSTIntNode Search(BSTIntNode node, int el)
{
while (node != null)
{
if (el == node.value)
return node;
else if (el < node.value)
node = node.left;
else
node = node.right;
}
return null;
}
//查詢
public BSTIntNode Search(int el)
{
return Search(root, el);
}
//廣度優先遍歷,利用佇列實現,至上而下,至左而右
public void BreadthFirst()
{
BSTIntNode p = root;
Queue queue = new ListQueue();
if (p != null)
{
queue.Enqueue(p);
while (!queue.IsEmpty())
{
p = (BSTIntNode)queue.Dequeue();
visit(p);
if (p.left != null)
queue.Enqueue(p.left);
if (p.right != null)
queue.Enqueue(p.right);
}
}
}
//深度優先遍歷,遞迴實現線序,中序和後序
//先序
protected void PreOrder(BSTIntNode p)
{
if (p != null)
{
visit(p);
PreOrder(p.left);
PreOrder(p.right);
}
}
public void PreOrder()
{
PreOrder(root);
}
//中序
protected void InOrder(BSTIntNode p)
{
if (p != null)
{
InOrder(p.left);
visit(p);
InOrder(p.right);
}
}
public void InOrder()
{
InOrder(root);
}
//後序
protected void PostOrder(BSTIntNode p)
{
if (p != null)
{
PostOrder(p.left);
PostOrder(p.right);
visit(p);
}
}
public void PostOrder()
{
PostOrder(root);
}
//插入節點操作
public void Insert(int el)
{
BSTIntNode p = root, prev = null;
//查詢節點位置
while (p != null)
{
prev = p;
if (p.value < el)
p = p.right;
else
p = p.left;
}
if (root == null) //空樹
root = new BSTIntNode(el);
else if (prev.value < el) //大於節點,插入右子樹
prev.right = new BSTIntNode(el);
else
prev.left = new BSTIntNode(el);
}
//複製刪除法的實現,歸併刪除法可能改變樹的高度
public void Delete(int el)
{
BSTIntNode node, p = root, prev = null;
//查詢節點位置
while (p != null&&p.value!=el)
{
prev = p;
if (p.value < el)
p = p.right;
else
p = p.left;
}
node = p;
if (p != null && p.value == el)
{
if (node.right == null)
node = node.left;
else if (node.left == null)
node = node.right;
else
{
BSTIntNode temp = node.left;
BSTIntNode previous = node;
while (temp.right != null) //查詢左位元組數的最右子節點
{
previous = temp;
temp = temp.right;
}
node.value = temp.value;
if (previous == node)
previous.left = temp.left;
else
previous.right = temp.left;
}
if (p == root)
root = node;
else if (prev.left == p)
prev.left = node;
else
prev.right = node;
}
else if (root != null)
{
Console.WriteLine("沒有找到節點:{0}", el);
}
else
Console.WriteLine("樹為空!");
}
}
注意,在樹中我們維持了一個Visit的delegate,看看使用方法:
public static void Main(string[] args)
{
BSTIntTree tree=new BSTIntTree();
int []num={10,20,6,12,23,15,8};
for (int i = 0; i < num.Length; i++)
tree.Insert(num[i]);
//新增遍歷處理函式,可以有多個
tree.visit += new Visit(printNode);
Console.WriteLine("廣度優先遍歷");
tree.BreadthFirst();
Console.WriteLine("先序");
tree.PreOrder();
Console.WriteLine("中序");
tree.InOrder();
Console.WriteLine("後序");
tree.PostOrder();
tree.Delete(8);
tree.Delete(15);
Console.WriteLine("刪除後廣度優先遍歷");
tree.BreadthFirst();
}
public static void printNode(BSTIntNode node)
{
Console.WriteLine("訪問節點:{0}", node.value);
}
{
BSTIntTree tree=new BSTIntTree();
int []num={10,20,6,12,23,15,8};
for (int i = 0; i < num.Length; i++)
tree.Insert(num[i]);
//新增遍歷處理函式,可以有多個
tree.visit += new Visit(printNode);
Console.WriteLine("廣度優先遍歷");
tree.BreadthFirst();
Console.WriteLine("先序");
tree.PreOrder();
Console.WriteLine("中序");
tree.InOrder();
Console.WriteLine("後序");
tree.PostOrder();
tree.Delete(8);
tree.Delete(15);
Console.WriteLine("刪除後廣度優先遍歷");
tree.BreadthFirst();
}
public static void printNode(BSTIntNode node)
{
Console.WriteLine("訪問節點:{0}", node.value);
}
可以看到,C#的delegate機制非常有趣,如果在java中恐怕需要用inner class來實現了。
相關文章
- 二叉查詢樹概念及實現
- JavaScript實現簡單二叉查詢樹JavaScript
- 二叉查詢樹的實現——C++C++
- 第 34 題:如何實現二叉查詢樹?
- 二叉樹 & 二叉查詢樹二叉樹
- 查詢二叉樹二叉樹
- 二叉查詢樹
- 二叉查詢樹(二叉排序樹)排序
- 手擼二叉樹——二叉查詢樹二叉樹
- 使用JS去實現一個BST(二叉查詢樹)JS
- C++二叉查詢樹實現過程詳解C++
- 轉:C++實現的變種二分查詢法(折半查詢)--二叉查詢樹C++
- 平衡二叉查詢樹:紅黑樹
- 二叉查詢樹和笛卡爾樹
- 二叉查詢樹【二叉排序樹】構建和查詢演算法 PHP 版排序演算法PHP
- 二叉查詢樹的插入刪除查詢
- 二叉樹路徑查詢二叉樹
- 實現二叉搜尋樹的新增,查詢和刪除(JAVA)Java
- 查詢|有序表折半查詢判定樹|二叉排序樹|3階B-樹排序
- Amazing tree —— 二叉查詢樹
- 二叉查詢樹的個數
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- 5分鐘瞭解二叉樹之二叉查詢樹二叉樹
- 二叉查詢樹(查詢、插入、刪除)——C語言C語言
- 二叉排序樹查詢,插入,刪除排序
- 五大經典查詢(1)_二叉排序樹查詢排序
- Mysql 實現樹狀遞迴查詢MySql遞迴
- Connect by實現樹查詢的妙用
- Python實現二叉樹的增、刪、查Python二叉樹
- c# winform 實現分頁查詢C#ORM
- 二叉樹實現二叉樹
- #查詢演算法#【2】二叉排序樹演算法排序
- Java實現遞迴查詢樹結構Java遞迴
- 用Python實現二叉樹的增、刪、查Python二叉樹
- 資料結構與演算法——二叉查詢樹類的C++實現資料結構演算法C++
- IP地址查詢API的C#實現APIC#
- 二叉樹java實現二叉樹Java
- 【谷歌面試題】找出二叉查詢樹中出現頻率最高的元素谷歌面試題