C#实现二叉查找树以及二叉树的删除
首先需要知道二叉树的基础知识,比父节点小的元素放在左边,大的放在右边
一.实现二叉查找树
对二叉树进行遍历查找
没有找到返回-1
二.实现二叉树的节点删除
二叉树的节点删除难点就在于要分类讨论的地方太多了,容易混乱
1.前提是删除的节点得存在(使用上面提到的二叉查找树)
2.首先需要找到需要删除的节点
3.需要找到删除节点的父节点
代码实现如下
之后就需要分类进行讨论了
代码里面的注释非常的详细了
整体删除节点方法的代码如下
public void Delete(int item)
{
if (FindItem(item) == -1)
throw new Exception("删除的元素不在二叉树内");
//当元素存在时
else
{
//寻找到要删除的节点
//寻找到要删除元素的父节点
Node currNode = rootNode;
Node parentNode = rootNode;
//和寻找元素一样,只不过这次寻找的不是元素而是节点
while (true)
{
if (item < currNode.item)
{
parentNode = currNode;
currNode = currNode.leftNode;
}
else if (item > currNode.item)
{
parentNode = currNode;
currNode = currNode.rightNode;
}
else
{
//找到了退出循环
break;
}
}
/******下面进行分类讨论******/
//1.当要删除的节点既没有左节点也没有右节点时
if (currNode.leftNode == null && currNode.rightNode == null)
{
/*这时还是有两种情况*/
//1.为叶子节点时
if (parentNode != currNode)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = null;
//右边时
else
parentNode.rightNode = null;
}
//2.为根节点时
else
{
rootNode = null;
}
}
//2.当要删除的节点只有左节点时
else if (currNode.leftNode != null && currNode.rightNode == null)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = currNode.leftNode;
//右边时
else if(currNode.item > parentNode.item)
parentNode.rightNode = currNode.leftNode;
else
{
rootNode = currNode.leftNode;
}
}
//3.当要删除的节点只有右节点时
else if (currNode.leftNode == null && currNode.rightNode != null)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = currNode.rightNode;
//右边时
else if(currNode.item > parentNode.item)
parentNode.rightNode = currNode.rightNode;
else
{
rootNode = currNode.rightNode;
}
}
//4.当删除的节点既有左又有右节点时
else
{
Node tmp=null;//暂时存储
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if(currNode.item < parentNode.item)
{
parentNode.leftNode = currNode.leftNode;
tmp = currNode.rightNode;
while (currNode.leftNode != null)
{
currNode = currNode.leftNode;
}
currNode.rightNode = tmp;
}
//右边时
else if (currNode.item > parentNode.item)
{
parentNode.rightNode = currNode.rightNode;
tmp = currNode.leftNode;
while (currNode.rightNode!=null)
{
currNode = currNode.rightNode;
}
currNode.leftNode = tmp;
}
//为根节点时
else
{
rootNode = rootNode.rightNode;
tmp = currNode.leftNode;
while (currNode.rightNode != null)
{
currNode = currNode.rightNode;
}
currNode.leftNode = tmp;
}
}
}
}
接下来我用中序遍历来测试结果
class Program
{
static void Main(string[] args)
{
int[] arr = { 5, 8, 3, 9, 6, 0, 4, 2, 1, 7 };
MyTree myTree = new MyTree(arr);
Console.WriteLine("寻找到的元素:"+myTree.FindItem(4));
Console.WriteLine("删除前的中序遍历:");
myTree.OrderShow(myTree.rootNode);
Console.WriteLine();
myTree.Delete(4);
Console.WriteLine("删除后的中序遍历:");
myTree.OrderShow(myTree.rootNode);
Console.ReadKey();
}
}
最后是整体的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp22
{
class Program
{
static void Main(string[] args)
{
int[] arr = { 5, 8, 3, 9, 6, 0, 4, 2, 1, 7 };
MyTree myTree = new MyTree(arr);
Console.WriteLine("寻找到的元素:"+myTree.FindItem(4));
Console.WriteLine("删除前的中序遍历:");
myTree.OrderShow(myTree.rootNode);
Console.WriteLine();
myTree.Delete(4);
Console.WriteLine("删除后的中序遍历:");
myTree.OrderShow(myTree.rootNode);
Console.ReadKey();
}
}
class Node
{
public Node leftNode;
public Node rightNode;
public int item;
public Node(int item)
{
this.item = item;
leftNode = null;
rightNode = null;
}
}
class MyTree
{
public Node rootNode;
public MyTree(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
AddNode2Tree(arr[i]);
}
}
//建立二叉树
private void AddNode2Tree(int item)
{
Node currNode = rootNode;
if (rootNode == null)
{
rootNode = new Node(item);
return;
}
while (true)
{
if (item < currNode.item)
{
if (currNode.leftNode == null)
{
currNode.leftNode = new Node(item);
return;
}
else
{
currNode = currNode.leftNode;
}
}
else
{
if (currNode.rightNode == null)
{
currNode.rightNode = new Node(item);
return;
}
else
{
currNode = currNode.rightNode;
}
}
}
}
//寻找二叉树中的元素
public int FindItem(int item)
{
Node node = rootNode;
while (true)
{
if (item == node.item)
{
return node.item;
}
else if (item < node.item)
{
node = node.leftNode;
}
else
{
node = node.rightNode;
}
if (node == null)
{
return -1;
}
}
}
//删除二叉树中的元素
public void Delete(int item)
{
if (FindItem(item) == -1)
throw new Exception("删除的元素不在二叉树内");
//当元素存在时
else
{
//寻找到要删除的节点
//寻找到要删除元素的父节点
Node currNode = rootNode;
Node parentNode = rootNode;
//和寻找元素一样,只不过这次寻找的不是元素而是节点
while (true)
{
if (item < currNode.item)
{
parentNode = currNode;
currNode = currNode.leftNode;
}
else if (item > currNode.item)
{
parentNode = currNode;
currNode = currNode.rightNode;
}
else
{
//找到了退出循环
break;
}
}
/******下面进行分类讨论******/
//1.当要删除的节点既没有左节点也没有右节点时
if (currNode.leftNode == null && currNode.rightNode == null)
{
/*这时还是有两种情况*/
//1.为叶子节点时
if (parentNode != currNode)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = null;
//右边时
else
parentNode.rightNode = null;
}
//2.为根节点时
else
{
rootNode = null;
}
}
//2.当要删除的节点只有左节点时
else if (currNode.leftNode != null && currNode.rightNode == null)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = currNode.leftNode;
//右边时
else
parentNode.rightNode = currNode.leftNode;
}
//3.当要删除的节点只有右节点时
else if (currNode.leftNode == null && currNode.rightNode != null)
{
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if (currNode.item < parentNode.item)
parentNode.leftNode = currNode.rightNode;
//右边时
else
parentNode.rightNode = currNode.rightNode;
}
//4.当删除的节点既有左又有右节点时
else
{
Node tmp=null;//暂时存储
/*先判断是父节点的左孩子还是右孩子*/
//左边时
if(currNode.item < parentNode.item)
{
parentNode.leftNode = currNode.leftNode;
tmp = currNode.rightNode;
while (currNode.leftNode != null)
{
currNode = currNode.leftNode;
}
currNode.rightNode = tmp;
}
//右边时
else if (currNode.item > parentNode.item)
{
parentNode.rightNode = currNode.rightNode;
tmp = currNode.leftNode;
while (currNode.rightNode!=null)
{
currNode = currNode.rightNode;
}
currNode.leftNode = tmp;
}
//为根节点时
else
{
rootNode = rootNode.rightNode;
tmp = currNode.leftNode;
while (currNode.rightNode != null)
{
currNode = currNode.rightNode;
}
currNode.leftNode = tmp;
}
}
}
}
//中序遍历
public void OrderShow(Node rootNode)
{
if (rootNode != null)
{
OrderShow(rootNode.leftNode);
Console.Write(rootNode.item);
OrderShow(rootNode.rightNode);
}
}
}
}
本篇文章参考:https://www.cnblogs.com/BrokenIce/p/5929169.html