二叉搜索树又称二叉查找树,亦称为二叉排序树。性质如下:
(1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
(2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)左、右子树也分别为二叉搜索树;
基础知识介绍:
上图中A为B的双亲结点,B为A的孩子结点。根为第一层,根的孩子为第二层,树中结点的最大层次数称为树的深度或高度。上图所示树的深度为4。
现将一组数{61, 87, 59, 47, 35, 73, 51, 98, 37, 93}此序列构造二叉搜索树,构造过程如下:
(1)i = 0,A[0] = 61,节点61作为根节点;
(2)i = 1,A[1] = 87,87 > 61,且节点61右孩子为空,故81为61节点的右孩子;
(3)i = 2,A[2] = 59,59 < 61,且节点61左孩子为空,故59为61节点的左孩子;
(4)i = 3,A[3] = 47,47 < 59,且节点59左孩子为空,故47为59节点的左孩子;
(5)i = 4,A[4] = 35,35 < 47,且节点47左孩子为空,故35为47节点的左孩子;
(6)i = 5,A[5] = 73,73 < 87,且节点87左孩子为空,故73为87节点的左孩子;
(7)i = 6,A[6] = 51,47 < 51,且节点47右孩子为空,故51为47节点的右孩子;
(8)i = 7,A[7] = 98,98 < 87,且节点87右孩子为空,故98为87节点的右孩子;
(9)i = 8,A[8] = 93,93 < 98,且节点98左孩子为空,故93为98节点的左孩子
C#代码实现,代码来自https://www.cnblogs.com/BrokenIce/p/5929169.htm,做了修改l
class Node
{
private object _data;
private Node _left;
private Node _right;
public object Data
{
get { return _data; }
set { _data = value; }
}
public Node Left
{
get { return _left; }
set { _left = value; }
}
public Node Right
{
get { return _right; }
set { _right = value; }
}
public Node(object data)
{
this._data = data;
}
public override string ToString()//重写
{
return _data.ToString();
}
}
class BinaryTree
{
private Node _head;
private string cStr;
public Node Head
{
get { return _head; }
set { _head = value;}
}
public BinaryTree()
{
_head=null;
}
//**********构建二叉搜索树
public Node rootNode = null;
public void Insert(int data)
{
Node Parent;
//将所需插入的数据包装进节点
Node newNode = new Node(data);
//如果为空树,则插入根节点
if (rootNode == null)
{
rootNode = newNode;
}
else//否则找到合适叶子节点位置插入
{
Node Current = rootNode;
while (true)
{
Parent = Current;
if ((int)newNode.Data < (int)Current.Data)
{
Current = Current.Left;
if (Current == null)
{
Parent.Left = newNode;
//插入叶子后跳出循环
break;
}
}
else
{
Current = Current.Right;
if (Current == null)
{
Parent.Right = newNode;
//插入叶子后跳出循环
break;
}
}
}
}
}
//递归先序遍历
public void PreOrder(Node node)
{
if (node != null)
{
Console.Write(node);
Console.Write(" ");
PreOrder(node.Left);
PreOrder(node.Right);
}
}
//递归中序遍历
public void InOrder(Node node)
{
if (node != null)
{
InOrder(node.Left);
Console.Write(node);
Console.Write(" ");
InOrder(node.Right);
}
}
//递归后序遍历
public void AfterOrder(Node node)
{
if (node != null)
{
AfterOrder(node.Left);
AfterOrder(node.Right);
Console.Write(node);
Console.Write(" ");
}
}
}
class Program
{
static void Main(string[] args)
{
//*****
BinaryTree b = new BinaryTree();
/*插入节点*/
b.Insert(61);
b.Insert(87);
b.Insert(59);
b.Insert(47);
b.Insert(35);
b.Insert(73);
b.Insert(51);
b.Insert(98);
b.Insert(37);
b.Insert(93);
/*插入结束 */
Console.Write("先序遍历:");
b.PreOrder(b.rootNode);
Console.WriteLine(" ");
Console.Write("\n中序遍历:");
b.InOrder(b.rootNode);
Console.Write("\n后序遍历:");
b.AfterOrder(b.rootNode);
Console.ReadLine();
//*****
}
}
//找到最大节点
public void FindMax()
{
Node current = rootNode;
//找到最右边的节点即可
while (current.Right != null)
{
current = current.Right;
}
Console.WriteLine("\n最大节点为:" + current.Data);
}
//找到最小节点
public void FindMin()
{
Node current = rootNode;
//找到最左边的节点即可
while (current.Left != null)
{
current = current.Left;
}
Console.WriteLine("\n最小节点为:" + current.Data);
}
public Node Delete(int key)//删除操作
{
Node parent = rootNode;
Node current = rootNode;
//首先找到需要被删除的节点&其父节点
while (true)
{
if (key <(int) current.Data)
{
if (current.Left == null)
break;
parent = current;
current = current.Left;
}
else if (key > (int)current.Data)
{
if (current == null)
break;
parent = current;
current = current.Right;
}
//找到被删除节点,跳出循环
else
{
break;
}
}
//找到被删除节点后,分四种情况进行处理
//情况一,所删节点是叶子节点时,直接删除即可
if (current.Left == null && current.Right == null)
{
//如果被删节点是根节点,且没有左右孩子
if (current == rootNode && rootNode.Left == null && rootNode.Right == null)
{
rootNode = null;
}
else if ((int)current.Data <(int) parent.Data)
parent.Left = null;
else
parent.Right = null;
}
//情况二,所删节点只有左孩子节点时
else if (current.Left != null && current.Right == null)
{
if ((int)current.Data < (int)parent.Data)
parent.Left = current.Left;
else
parent.Right = current.Left;
}
//情况三,所删节点只有右孩子节点时
else if (current.Left == null && current.Right != null)
{
if ((int)current.Data < (int)parent.Data)
parent.Left = current.Right;
else
parent.Right = current.Right;
}
//情况四,所删节点有左右两个孩子
else
{
//current是被删的节点,temp是被删左子树最右边的节点
Node temp;
//先判断是父节点的左孩子还是右孩子
if ((int)current.Data < (int)parent.Data)
{
parent.Left = current.Left;
temp = current.Left;
//寻找被删除节点最深的右孩子
while (temp.Right != null)
{
temp = temp.Right;
}
temp.Right = current.Right;
}
//右孩子
else if ((int)current.Data > (int)parent.Data)
{
parent.Right = current.Left;
temp = current.Left;
//寻找被删除节点最深的左孩子
while (temp.Left != null)
{
temp = temp.Left;
}
temp.Right = current.Right;
}
//当被删节点是根节点,并且有两个孩子时
else
{
temp = current.Left;
while (temp.Right != null)
{
temp = temp.Right;
}
temp.Right = rootNode.Right;
rootNode = current.Left;
}
}
return current;
}