这个二叉树弄了一上午,不过原理上基本上懂了,还发现,其实用C来写树的话,由于指针的存在更容易理解。
下面是代码,参考“一线码农”,发现他的删除函数其实写的是有问题的,经过修改之后顺利通过。
using System; using System.Collections.Generic; using System.Linq; using System.Text; //哈希查找程序 namespace Test { class Program { static void Main(string[] args) { List<int> list = new List<int>() { 50, 30, 70, 10, 40, 90, 80 }; //创建二叉树 BSTree bsTree = CreateBST(list); Console.Write("中序遍历的原始数据:"); LDR_BST(bsTree); Console.WriteLine("\n--------------------------------------"); Console.WriteLine("\n10在二叉树中是否包含:" + SearchBST(bsTree, 10)); Console.WriteLine("\n--------------------------------------"); bool isExcute = false; InsertBST(bsTree, 20, ref isExcute); Console.WriteLine("\n20插入到二叉树,中序遍历为:"); LDR_BST(bsTree); Console.WriteLine("\n--------------------------------------"); Console.WriteLine("删除叶子节点20,\n中序遍历:"); DeleteBST(ref bsTree, 20); LDR_BST(bsTree); Console.WriteLine("\n--------------------------------------"); Console.WriteLine("删除单孩子节点90,\n中序遍历:"); DeleteBST(ref bsTree, 90); LDR_BST(bsTree); Console.WriteLine("\n--------------------------------------"); Console.WriteLine("删除根节点50,\n中序遍历:"); DeleteBST(ref bsTree, 50); LDR_BST(bsTree); Console.ReadLine(); } //二叉排序树结构 public class BSTree { public int data; public BSTree left; public BSTree right; } static void InsertBST(BSTree bsTree, int key, ref bool isExcute) { if (bsTree == null) return; if (bsTree.data > key) InsertBST(bsTree.left, key, ref isExcute); else InsertBST(bsTree.right, key, ref isExcute); if (!isExcute) { BSTree current = new BSTree() { data = key, left = null, right = null }; if (bsTree.data > key) bsTree.left = current; else bsTree.right = current; isExcute = true; } } static BSTree CreateBST(List<int> list) { BSTree bsTree = new BSTree() { data = list[0], left = null, right = null }; for (int i = 1; i < list.Count; i++) { bool isExcute = false; InsertBST(bsTree, list[i], ref isExcute); } return bsTree; } static bool SearchBST(BSTree bsTree, int key) { if (bsTree == null) return false; if (bsTree.data == key) return true; if (bsTree.data > key) return SearchBST(bsTree.left, key); else return SearchBST(bsTree.right, key); } //中序遍历二叉树 static void LDR_BST(BSTree bsTree) { if (bsTree != null) { LDR_BST(bsTree.left); Console.Write(bsTree.data+","); LDR_BST(bsTree.right); } } static void DeleteBST(ref BSTree bsTree, int key) { if (bsTree == null) return; if (bsTree.data == key) { //第一种情况:叶子节点 if (bsTree.left == null && bsTree.right == null) { bsTree = null; return; } //第二种情况:左子树不为空 if (bsTree.left != null && bsTree.right == null) { bsTree = bsTree.left; return; } //第三种情况,右子树不为空 if (bsTree.left == null && bsTree.right != null) { bsTree = bsTree.right; return; } //第四种情况,左右子树都不为空 if (bsTree.left != null && bsTree.right != null) { var node = bsTree.right;//被删除节点的右孩子 BSTree lastPnode = bsTree;//用来保存右孩子的最左节点的父节点。 //找到右子树中的最左节点 while (node.left != null) { lastPnode = node;//保存左子树的父节点 //遍历它的左子树 node = node.left; } bsTree.data = node.data; if (lastPnode.right == node)//删除节点的右节点没有左节点的时候。即上边的while循环没执行。 { bsTree.right = node.right; } else { if (lastPnode.left == node)//删除节点的右节点有左节点的时候。 { lastPnode.left = node.right; } } node = null;//将换位到删除节点去的右子树的最左子树赋值为空。 } } if (bsTree.data > key) { DeleteBST(ref bsTree.left, key); } else { DeleteBST(ref bsTree.right, key); } } } }
学完了这个,那么排序和查找也就告一段落了。