我有一本书,讲解二叉搜索树的理论非常糟糕。我知道左右子节点的顺序有关系,但我仍然不能理解一个子节点比前一个级别的子节点大的概念。
以这个字符串树为例:
(抱歉我画得不好)这个例子直接摘自我的书。
谁能向我解释这个顺序?这背后的逻辑是什么?
以这个字符串树为例:
(抱歉我画得不好)这个例子直接摘自我的书。
谁能向我解释这个顺序?这背后的逻辑是什么?
对于任何一个节点(例如根节点Karen),左子树中的每个节点(Bob,Alan,Ellen)在字典序上都比Karen小,右子树中的每个节点(Tom,Wendy)都比Karen大。
正如@mellamokb在评论中指出的那样,第二个Karen不应该存在。
因此,您可以像对待排序数组一样,在O(log N)时间内对该树进行二进制搜索。
using System;
using System.Collections.Generic;
namespace BSTString
{
public class BinaryStringSearchTree
{
// Private class so that it cannot be accessed outside of parent class
private class Node
{
// Data field of the node
public string _data;
// Stores address of left child
public Node _leftNode;
// Stores address of right child
public Node _rightNode;
/// <summary>
/// Constructor
/// </summary>
/// <param name="data"></param>
public Node(string data)
{
this._data = data; // String is stored in the data field of the node
this._rightNode = this._leftNode = null; // Right and left child are set to null
}
}
// Stores the root of the tree
private Node root;
/// <summary>
/// Constructor
/// Root is set as null
/// </summary>
public BinaryStringSearchTree()
{
root = null;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="value"></param> // Value which is to be stored in root
public BinaryStringSearchTree(string value)
{
// Creates a new node with value and stores into root
root = new Node(value);
}
/// <summary>
/// Function to call insertString() function
/// </summary>
/// <param name="data"></param>
public void insert(string data)
{
// Inserting data into tree
root = insertString(root, data);
}
/// <summary>
/// Private recursive function which is called to insert data into the tree
/// </summary>
/// <param name="root"></param>
/// <param name="data"></param>
/// <returns></returns>
private Node insertString(Node root, string data)
{
// Base Case:
// If the tree is empty
if (root == null)
{
// Data is stored at root
root = new Node(data);
// root node is returned
return root;
}
/*
* string.Compare(a, b) function will return
* 0 if a is equal to b
* 1 if a is greater than b
* -1 if a is smaller than b
*/
// -- Recursively moving down the tree --
// If data stored at root is greater then the data
if (string.Compare(root._data, data) > 0)
{
root._leftNode = insertString(root._leftNode, data);
}
// If data stored at root is smaller then the data
else if (string.Compare(root._data, data) < 0)
{
root._rightNode = insertString(root._rightNode, data);
}
return root;
}
/// <summary>
/// Function to call deleteString() function
/// </summary>
/// <param name="data"></param>
public void delete(string data)
{
root = deleteNode(root, data);
}
/// <summary>
/// Private recursive function which is called to delete data from the tree
/// </summary>
/// <param name="root"></param>
/// <param name="data"></param>
/// <returns></returns>
private Node deleteNode(Node root, string data)
{
// Base case:
// If the tree is empty
if (root == null)
{
return root;
}
// -- Recursively moving down the tree --
// If data stored at root is greater then the data
if (string.Compare(root._data, data) > 0)
{
root._leftNode = deleteNode(root._leftNode, data);
}
// If data stored at root is smaller then the data
else if (string.Compare(root._data, data) < 0)
{
root._rightNode = deleteNode(root._rightNode, data);
}
// If data stored at root is same as the data
else
{
// Base case
// If the node does not have right or left child
if (root._leftNode == null && root._rightNode == null)
{
return null;
}
// Node with only one child
if (root._rightNode == null)
{
return root._leftNode;
}
else if (root._leftNode == null)
{
return root._rightNode;
}
// Node which has two children
// Finds In-Order Sucessor - smallest in the right subtree
Node inodrsuc = inOrderSucessor(root._rightNode);
// Replacing the In-Order sucessor of root with data of root
root._data = inodrsuc._data;
// Delete the In-Order Sucessor
root._rightNode = deleteNode(root._rightNode, root._data);
}
return root;
}
/// <summary>
/// Function to find smallest element in the left subtree
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
private Node inOrderSucessor(Node inOrder)
{
// Loop runs till leaf node
while (inOrder._leftNode != null)
{
inOrder = inOrder._leftNode;
}
return inOrder;
}
/// <summary>
/// Function to call searchTree() function
/// </summary>
/// <param name="data"></param> String which is to be searched
/// <returns></returns>
public string search(string data)
{
Node result = searchTree(root, data);
// Data does not exist int the tree
if (result == null)
{
return "Not Found";
}
return result._data;
}
/// <summary>
/// Private recursive function to search for a particular node in a tree
/// </summary>
/// <param name="root"></param> Root of the tree
/// <param name="data"></param> String which is to be searched
/// <returns></returns>
private Node searchTree(Node root, string data)
{
// Base Case: root is null
// or data stored at root is equal to string which is to be searched
if (root == null || string.Compare(root._data, data) == 0)
{
return root;
}
// -- Recursively moving down the tree --
// Data stored at root is smaller than the string which is to be searched
if (string.Compare(root._data, data) < 0)
{
return searchTree(root._rightNode, data);
}
// Data stored at root is greater than the string which is to be searched
else
{
return searchTree(root._leftNode, data);
}
}
/// <summary>
/// Function to call private inOrder() function
/// </summary>
public void inOrder()
{
inOrder(root);
}
/// <summary>
/// -- In-Order traversal --
/// Traverse left subtree recursively
/// Visite root node
/// traverse right subtree resursively
/// </summary>
/// <param name="root"></param>
private void inOrder(Node root)
{
if (root != null)
{
inOrder(root._leftNode);
Console.WriteLine(root._data);
inOrder(root._rightNode);
}
}
/// <summary>
/// Function to call private preOrder() function
/// </summary>
public void preOrder()
{
preOrder(root);
}
/// <summary>
/// -- Pre-Order Traverse --
/// Visit root node
/// Traverse left subtree recursively
/// Traverse right subtree resursively
/// </summary>
/// <param name="root"></param>
private void preOrder(Node root)
{
if (root != null)
{
Console.WriteLine(root._data);
preOrder(root._leftNode);
preOrder(root._rightNode);
}
}
/// <summary>
/// Function to call private postOrder() function
/// </summary>
public void postOrder()
{
postOrder(root);
}
/// <summary>
/// -- Post-Order Traversal --
/// Traverse left subtree recursively
/// Traverse right subtree recursively
/// Visite root node
/// </summary>
/// <param name="root"></param>
private void postOrder(Node root)
{
if (root != null)
{
postOrder(root._leftNode);
postOrder(root._rightNode);
Console.WriteLine(root._data);
}
}
/// <summary>
/// Printing level order traversal using iterative approach
/// Referenced from: https://www.geeksforgeeks.org/print-level-order-traversal-line-line/
/// </summary>
public void printTree()
{
// Base Case
// Tree is empty
if (root == null)
{
return;
}
// Empty queue for level
Queue<Node> queue = new Queue<Node>();
queue.Enqueue(root);
while (true)
{
int nodeCount = queue.Count; //number of nodes at current level
if (nodeCount == 0)
{
break;
}
while (nodeCount > 0)
{
Node node = queue.Peek();
Console.Write(node._data + " ");
queue.Dequeue();
if (node._leftNode != null)
{
queue.Enqueue(node._leftNode);
}
if (node._rightNode != null)
{
queue.Enqueue(node._rightNode);
}
nodeCount--;
}
Console.WriteLine();
}
}
}
class Test
{
static void Main(string[] args)
{
// Creating an instance of BinaryStringSearchTree class
BinaryStringSearchTree tree = new BinaryStringSearchTree();
// Inserting element
tree.insert("Karen");
tree.insert("Bob");
tree.insert("Tom");
// Print tree
Console.WriteLine("Printing tree");
tree.printTree();
Console.WriteLine();
}
}
}
对于任何节点:
这提供了一些独特的属性
O(Log n)
时间内完成。在你的例子中,它们指的是每个名字中第一个符号的顺序。
如果你看一下,从左到右的名字顺序是从ABC的第一个字符到最后一个字符。
此外,KAREN名称的第二次出现有一个特殊情况 - 在这棵树中的默认行为是,如果输入相同的数据,则“向右移动”,然后将Karen与Tom进行比较 -> K“小于”T,因此它在其左侧。
无论如何,这里有一个更好的示例,您可以从中看到二叉树中的顺序数字: http://www.codeproject.com/Articles/4647/A-simple-binary-tree-implementation-with-VB-NET
我认为下面这篇文章将对你理解二叉树的概念非常有帮助,它还提供了C/C++和Java中常见的代码示例: