namespace Val_Tree { public class Node { //成员变量 private object _data; //数据 private Node _left; //左孩子 private Node _right; //右孩子 private int _bf; public int BF { get { return _bf; } set { _bf = value; } } 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) { _data = data; } public override string ToString() { return _data.ToString(); } } }
using System; using System.Collections; namespace Val_Tree { public class BinaryTree { private Node _head; //头指针 private string cStr; //用于构造二叉树的字符串 public Node Head //头指针 { get { return _head; } } //构造方法 public BinaryTree(string constructStr) { cStr = constructStr; _head = new Node(cStr[0]); //添加头结点 Add(_head, 0); //给头结点添加孩子结点 } private void Add(Node parent, int index) { int leftIndex = 2 * index + 1; //计算左孩子索引 if (leftIndex < cStr.Length) //如果索引没超过字符串长度 { if (cStr[leftIndex] != '#') //'#'表示空结点 { //添加左孩子 parent.Left = new Node(cStr[leftIndex]); //递归调用Add方法给左孩子添加孩子节点 Add(parent.Left, leftIndex); } } int rightIndex = 2 * index + 2; if (rightIndex < cStr.Length) { if (cStr[rightIndex] != '#') { //添加右孩子 parent.Right = new Node(cStr[rightIndex]); //递归调用Add方法给右孩子添加孩子节点 Add(parent.Right, rightIndex); } } } public void PreOrder(Node node) //先序遍历 { if (node != null) { Console.Write(node.ToString()); //打印字符 PreOrder(node.Left); //递归 PreOrder(node.Right); //递归 } } public void MidOrder(Node node) //中序遍历 { if (node != null) { MidOrder(node.Left); //递归 Console.Write(node.ToString()); //打印字符 MidOrder(node.Right); //递归 } } public void AfterOrder(Node node) //后继遍历 { if (node != null) { AfterOrder(node.Left); //递归 AfterOrder(node.Right); //递归 Console.Write(node.ToString()); //打印字符 } } public void LevelOrder() //宽度优先遍历 { Queue queue = new Queue(); //声明一个队例 queue.Enqueue(_head); //把根结点压入队列 while (queue.Count > 0) //只要队列不为空 { Node node = (Node)queue.Dequeue(); //出队 Console.Write(node.ToString()); //访问结点 if (node.Left != null) //如果结点左孩子不为空 { //把左孩子压入队列 queue.Enqueue(node.Left); } if (node.Right != null) //如果结点右孩子不为熔 { //把右孩子压入队列 queue.Enqueue(node.Right); } } } } }
namespace Val_Tree { public interface IBinaryTree { Node Head { get; } bool Add(int value); //添加一个元素 bool Remove(int value);//删除指定值 void RemoveNode(Node node);//删除指定节点 } }
using System; using System.Collections; namespace Val_Tree { public class BinarySearchTree : IBinaryTree //实现画树接口 { //成员变量 private Node _head; //头指针 private Node[] path = new Node[32]; //记录访问路径上的结点 private int p; //表示当前访问到的结点在_path上的索引 Node IBinaryTree.Head //显式接口实现 { get { return (Node)_head; } } public bool Add(int value) //添加一个元素 { //如果是空树,则新结点成为二叉排序树的根 if (_head == null) { _head = new Node(value); _head.BF = 0; return true; } p = 0; //prev为上一次访问的结点,current为当前访问结点 Node prev = null, current = _head; while (current != null) { path[p++] = current; //将路径上的结点插入数组 //如果插入值已存在,则插入失败 if ((int)current.Data == value) { return false; } prev = current; //当插入值小于当前结点,则继续访问左子树,否则访问右子树 current = (value < (int)prev.Data) ? prev.Left : prev.Right; } current = new Node(value); //创建新结点 current.BF = 0; if (value < (int)prev.Data) //如果插入值小于双亲结点的值 { prev.Left = current; //成为左孩子 } else //如果插入值大于双亲结点的值 { prev.Right = current; //成为右孩子 } path[p] = current; //将新元素插入数组path的最后 //修改插入点至根结点路径上各结点的平衡因子 int bf = 0; while (p > 0) { //bf表示平衡因子的改变量,当新结点插入左子树,则平衡因子+1 //当新结点插入右子树,则平衡因子-1 bf = (value < (int)path[p - 1].Data) ? 1 : -1; path[--p].BF += bf; //改变当父结点的平衡因子 bf = path[p].BF; //获取当前结点的平衡因子 //判断当前结点平衡因子,如果为0表示该子树已平衡,不需再回溯 //而改变祖先结点平衡因子,此时添加成功,直接返回 if (bf == 0) { return true; } else if (bf == 2 || bf == -2) //需要旋转的情况 { RotateSubTree(bf); return true; } } return true; } //删除指定值 public bool Remove(int value) { p = -1; //parent表示双亲结点,node表示当前结点 Node node = _head; //寻找指定值所在的结点 while (node != null) { path[++p] = node; //如果找到,则调用RemoveNode方法删除结点 if (value == (int)node.Data) { RemoveNode(node);//现在p指向被删除结点 return true; //返回true表示删除成功 } if (value < (int)node.Data) { //如果删除值小于当前结点,则向左子树继续寻找 node = node.Left; } else { //如果删除值大于当前结点,则向右子树继续寻找 node = node.Right; } } return false; //返回false表示删除失败 } //删除指定结点 public void RemoveNode(Node node) { Node tmp = null; //当被删除结点存在左右子树时 if (node.Left != null && node.Right != null) { tmp = node.Left; //获取左子树 path[++p] = tmp; while (tmp.Right != null) //获取node的中序遍历前驱结点,并存放于tmp中 { //找到左子树中的最右下结点 tmp = tmp.Right; path[++p] = tmp; } //用中序遍历前驱结点的值代替被删除结点的值 node.Data = tmp.Data; if (path[p - 1] == node) { path[p - 1].Left = tmp.Left; } else { path[p - 1].Right = tmp.Left; } } else //当只有左子树或右子树或为叶子结点时 { //首先找到惟一的孩子结点 tmp = node.Left; if (tmp == null) //如果只有右孩子或没孩子 { tmp = node.Right; } if (p > 0) { if (path[p - 1].Left == node) { //如果被删结点是左孩子 path[p - 1].Left = tmp; } else { //如果被删结点是右孩子 path[p - 1].Right = tmp; } } else //当删除的是根结点时 { _head = tmp; } } //删除完后进行旋转,现在p指向实际被删除的结点 int data = (int)node.Data; while (p > 0) { //bf表示平衡因子的改变量,当删除的是左子树中的结点时,平衡因子-1 //当删除的是右子树的孩子时,平衡因子+1 int bf = (data <= (int)path[p - 1].Data) ? -1 : 1; path[--p].BF += bf; //改变当父结点的平衡因子 bf = path[p].BF; //获取当前结点的平衡因子 if (bf != 0) //如果bf==0,表明高度降低,继续后上回溯 { //如果bf为1或-1则说明高度未变,停止回溯,如果为2或-2,则进行旋转 //当旋转后高度不变,则停止回溯 if (bf == 1 || bf == -1 || !RotateSubTree(bf)) { break; } } } } //旋转以root为根的子树,当高度改变,则返回true;高度未变则返回false private bool RotateSubTree(int bf) { bool tallChange = true; Node root = path[p], newRoot = null; if (bf == 2) //当平衡因子为2时需要进行旋转操作 { int leftBF = root.Left.BF; if (leftBF == -1) //LR型旋转 { newRoot = LR(root); } else if (leftBF == 1) { newRoot = LL(root); //LL型旋转 } else //当旋转根左孩子的bf为0时,只有删除时才会出现 { newRoot = LL(root); tallChange = false; } } if (bf == -2) //当平衡因子为-2时需要进行旋转操作 { int rightBF = root.Right.BF; //获取旋转根右孩子的平衡因子 if (rightBF == 1) { newRoot = RL(root); //RL型旋转 } else if (rightBF == -1) { newRoot = RR(root); //RR型旋转 } else //当旋转根左孩子的bf为0时,只有删除时才会出现 { newRoot = RR(root); tallChange = false; } } //更改新的子树根 if (p > 0) { if ((int)root.Data < (int)path[p - 1].Data) { path[p - 1].Left = newRoot; } else { path[p - 1].Right = newRoot; } } else { _head = newRoot; //如果旋转根为AVL树的根,则指定新AVL树根结点 } return tallChange; } //root为旋转根,rootPrev为旋转根双亲结点 private Node LL(Node root) //LL型旋转,返回旋转后的新子树根 { Node rootNext = root.Left; root.Left = rootNext.Right; rootNext.Right = root; if (rootNext.BF == 1) { root.BF = 0; rootNext.BF = 0; } else //rootNext.BF==0的情况,删除时用 { root.BF = 1; rootNext.BF = -1; } return rootNext; //rootNext为新子树的根 } private Node LR(Node root) //LR型旋转,返回旋转后的新子树根 { Node rootNext = root.Left; Node newRoot = rootNext.Right; root.Left = newRoot.Right; rootNext.Right = newRoot.Left; newRoot.Left = rootNext; newRoot.Right = root; switch (newRoot.BF) //改变平衡因子 { case 0: root.BF = 0; rootNext.BF = 0; break; case 1: root.BF = -1; rootNext.BF = 0; break; case -1: root.BF = 0; rootNext.BF = 1; break; } newRoot.BF = 0; return newRoot; //newRoot为新子树的根 } private Node RR(Node root) //RR型旋转,返回旋转后的新子树根 { Node rootNext = root.Right; root.Right = rootNext.Left; rootNext.Left = root; if (rootNext.BF == -1) { root.BF = 0; rootNext.BF = 0; } else //rootNext.BF==0的情况,删除时用 { root.BF = -1; rootNext.BF = 1; } return rootNext; //rootNext为新子树的根 } private Node RL(Node root) //RL型旋转,返回旋转后的新子树根 { Node rootNext = root.Right; Node newRoot = rootNext.Left; root.Right = newRoot.Left; rootNext.Left = newRoot.Right; newRoot.Right = rootNext; newRoot.Left = root; switch (newRoot.BF) //改变平衡因子 { case 0: root.BF = 0; rootNext.BF = 0; break; case 1: root.BF = 0; rootNext.BF = -1; break; case -1: root.BF = 1; rootNext.BF = 0; break; } newRoot.BF = 0; return newRoot; //newRoot为新子树的根 } public void LevelOrder() //宽度优先遍历 { Queue queue = new Queue(); //声明一个队例 queue.Enqueue(_head); //把根结点压入队列 while (queue.Count > 0) //只要队列不为空 { Node node = (Node)queue.Dequeue(); //出队 Console.Write(node.ToString()+" "); //访问结点 if (node.Left != null) //如果结点左孩子不为空 { //把左孩子压入队列 queue.Enqueue(node.Left); } if (node.Right != null) //如果结点右孩子不为熔 { //把右孩子压入队列 queue.Enqueue(node.Right); } } } } }
using System; namespace Val_Tree { class Program { static void Main(string[] args) { // 使用字符串构造二叉树 Console.WriteLine("二叉树遍历"); Console.WriteLine("ABCDE#F"); BinaryTree bTree = new BinaryTree("ABCDE#F"); Console.WriteLine("先序遍历:根左右"); bTree.PreOrder(bTree.Head); //先序遍历 Console.WriteLine(); Console.WriteLine(); Console.WriteLine("中序遍历:左根右"); bTree.MidOrder(bTree.Head); //中序遍历 Console.WriteLine(); Console.WriteLine(); Console.WriteLine("后序遍历:左右根"); bTree.AfterOrder(bTree.Head); //后序遍历 Console.WriteLine(); Console.WriteLine(); Console.WriteLine("宽度优先遍历:"); bTree.LevelOrder();//宽度优先遍历 Console.WriteLine(); Console.WriteLine(); //构建一颗平衡树 并放入1-?个元素后 宽度优先遍历输出 BinarySearchTree tree = new BinarySearchTree(); for (int i = 1; i <= 7; i++) tree.Add(i); tree.LevelOrder(); Console.ReadKey(); } } }