轉自 https://blog.csdn.net/qq_45071375/article/details/103715587
這是我們用代碼創建出來的二叉樹圖例
A
/ \
B C
/ \ \
D E F
友情提示:
在下面代碼中出現的#字符代表子樹為空,例如D結點下面左右子樹都沒有,就是兩個#號;C結點沒有左子樹就是一個#號,具體看Main函數運行代碼!
一,字段腳本
using System; using System.Collections.Generic; using System.Text; namespace BinaryDemo { public class TreeNode { /* * 樹的知識點 * 樹結點 根結點 結點子樹 * 結點的度 結點關系 結點層次 * 樹的深度/高度 */ //結點下標 結點下標字符串數據 左子樹 右子樹 private int index; private string data; private TreeNode leftChild; private TreeNode rightChild; private TreeNode parent; /// <summary> /// 有參構造結點下標 結點下標的字符串數據 /// </summary> /// <param name="index"></param> /// <param name="data"></param> public TreeNode(int index, string data) { this.index = index; this.data = data; this.leftChild = null; this.rightChild = null; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } //拿到左右子串的數據 public String getData() { return data; } public void setData(String data) { this.data = data; } //拿到左子樹 public TreeNode getLeftChild() { return leftChild; } public void setLeftChild(TreeNode leftChild) { this.leftChild = leftChild; } //拿到右子樹 public TreeNode getRightChild() { return rightChild; } public void setRightChild(TreeNode rightChild) { this.rightChild = rightChild; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } //快捷鍵生成的字段get和set public int Index { get => index; set => index = value; } public string Data { get => data; set => data = value; } public TreeNode LeftChild { get => leftChild; set => leftChild = value; } public TreeNode RightChild { get => rightChild; set => rightChild = value; } public TreeNode Parent { get => parent; set => parent = value; } } }
二,二叉樹具體實現構建遍歷的腳本
using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace BinaryDemo { public class BinaryTree { //根結點 public TreeNode root = null; public static string[] str; public static int count; /// <summary> /// 無參構造設置根結點並賦值數據 /// </summary> public BinaryTree() { root = new TreeNode(1,"A"); } /// <summary> /// 構建二叉樹的方法 B C D E F /// 手動的構建一棵二叉樹 很快就可以得出這個二叉樹的結構 /// </summary> public void CreateBinaryTree() { TreeNode nodeb = new TreeNode(2,"B"); TreeNode nodec = new TreeNode(3, "C"); TreeNode noded = new TreeNode(4, "D"); TreeNode nodee = new TreeNode(5, "E"); TreeNode nodef = new TreeNode(6, "F"); root.LeftChild = nodeb; root.RightChild = nodec; nodeb.LeftChild = noded; nodeb.RightChild = nodee; nodec.RightChild = nodef; } /// <summary> /// 先序遍歷 --迭代 /// 若二叉樹為空樹直接返回,先序遍歷的特點根左右 /// </summary> public void PreOrder(TreeNode node) { if (node == null) { return; } else { //node.getData()我們可以獲取到二叉樹的根結點的數據 Console.WriteLine("先序遍歷" + "\t迭代" + node.getData()); //得到左子樹的數據 PreOrder(node.LeftChild); //得到右子樹的數據 PreOrder(node.RightChild); } } /// <summary> /// 中序遍歷--迭代 /// 若二叉樹為空樹直接返回,中序遍歷的特點左根右 /// </summary> /// <param name="node"></param> public void MidOrder(TreeNode node) { if (node == null) { return; } else { MidOrder(node.LeftChild); Console.WriteLine("中序遍歷" + "\t迭代" + node.getData()); MidOrder(node.RightChild); } } /// <summary> /// 后序遍歷--迭代 /// 若二叉樹為空樹直接返回,中序遍歷的特點左右根 /// </summary> /// <param name="node"></param> public void LastOrder(TreeNode node) { if (node == null) { return; } else { LastOrder(node.LeftChild); LastOrder(node.RightChild); Console.WriteLine("后序遍歷" + "\t迭代" + node.getData()); } } //-----------------------------------分界線------------------------------------------ /* 迭代與普通循環的區別是:迭代時,循環代碼中參與運算的變量同時是保存結果的變量, 當前保存的結果作為下一次循環計算的初始值。 遞歸與普通循環的區別是:循環是有去無回,而遞歸則是有去有回(因為存在終止條件)。 */ /// <summary> /// 根據先序序列構建二叉樹 /// </summary> /// <param name="data"></param> /// <returns></returns> public TreeNode CreateBinaryTree(List<String> data) { return CreateBinaryTree(data.Count, data); } /// <summary> /// 根據先序遞歸創建二叉樹 /// "A","B","D","#","#","E","#","#","C","#","F","#","#" /// 1、首先判斷集合的長度是否為0,為空樹或者結點都已經賦值成功 /// 2、把存儲每個結點的集合以及長度傳參進來 index為結點下標 /// 3、先序遍歷根左右首先確定根結點也就是集合的第0項,結點下標為0結點數據為A,從集合中刪除結點數據 /// A,現在集合中有12數量 /// /// 4、然后進到獲取左子樹結點里面,結點B、D一樣的執行原理, /// 5、注意#的使用 #號代表結點沒有左子樹或者右子樹 一個#代表沒有左子樹,但是有右子樹 兩個#左右子 /// 樹都沒有 /// /// 6、注意里面的順序 根結點 左子樹 如果出現#號 根據個數判斷 一層一層的遍歷 /// </summary> /// <param name="count"></param> /// <param name="data"></param> /// <returns></returns> private TreeNode CreateBinaryTree(int count, List<string> data) { if (data.Count == 0) { return null; } string d = data[0]; TreeNode node = null; int index = count - data.Count; if (d.Equals("#")) { node = null; data.RemoveAt(0);//刪除# return node;//退出 } node = new TreeNode(index,d);//創建新的結點 if (index == 0) { root = node; } data.RemoveAt(0); node.LeftChild = CreateBinaryTree(count, data); node.RightChild = CreateBinaryTree(count, data); return node; } /// <summary> /// 求二叉樹的高度 /// </summary> /// <returns></returns> public int GetHeight() { return GetHeight(root); } private int GetHeight(TreeNode node) { //根結點為空 高度為0 if (node == null) { return 0; } else { Console.WriteLine(node.getData()); //求出左子樹和右子樹的高度 int i = GetHeight(node.LeftChild); int j = GetHeight(node.RightChild); //左右子樹的高度就是樹的深度 三目運算符判斷哪棵子樹的高度高 樹的高度就是返回值 return (i < j) ? j + 1 : i + 1; } } /// <summary> /// 獲取二叉樹的結點數 /// </summary> /// <returns></returns> public int GetSize() { return GetSize(root); } private int GetSize(TreeNode node) { //沒有根結點即為空樹 所以也就不存在結點 if (node == null) { return 0; } else { //不是空樹的情況下 拿到所有的左子樹的結點和右子樹的結點 最后加上根結點 return 1 + GetSize(node.LeftChild) + GetSize(node.RightChild); } } /// <summary> /// 前序遍歷-------非迭代 /// 棧里面的操作A進棧-->B進棧-->D進棧-->D出棧-->B出棧-->E進棧-->E出棧-->A出棧-->C進棧-->C出棧 ///-->F進棧-->F出棧 /// </summary> /// <param name="root"></param> public void TheFirstOrder(TreeNode root) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode node = root; //結點數不為空或者棧的數量大於0 while (node != null||stack.Count>0) { if (node != null) { Console.WriteLine("前序遍歷"+"非迭代進棧"+node.getData()); stack.Push(node);//壓棧訪問 node = node.LeftChild; } else { //彈棧 node = stack.Pop(); node=node.RightChild; } } } /// <summary> /// 中序遍歷-------非迭代 /// </summary> /// <param name="root"></param> public void TheMidleOrder(TreeNode root) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode node = root; while (node != null || stack.Count > 0) { if (node != null) { stack.Push(node);//壓棧 node = node.LeftChild; } else { node = stack.Pop();//彈棧訪問 Console.WriteLine("中序遍歷" + "非迭代出棧" + node.getData()); node = node.RightChild; } } } /// <summary> /// 后序遍歷-------非迭代 /// </summary> /// <param name="root"></param> public void TheLastOrder(TreeNode root) { Stack<TreeNode> stack = new Stack<TreeNode>(); Stack<TreeNode> output = new Stack<TreeNode>();//新建一個中間棧來存儲后序遍歷的結果 TreeNode node = root; //先序遍歷根左右 后序遍歷左右根 首先確定根結點 右子樹 左子樹 反過來就行 while (node != null || stack.Count > 0) { if (node != null) { output.Push(node); stack.Push(node); node = node.RightChild; } else { //彈棧 node = stack.Pop(); node = node.LeftChild; } } while (output.Count > 0) { Console.WriteLine("后序遍歷"+"非迭代"+output.Pop().getData()); } } } }
三,Main方法調試
using System; using System.Collections.Generic; namespace BinaryDemo { class Program { static void Main(string[] args) { //方法一 /* BinaryTree binarytree = new BinaryTree(); //在代碼中手動的創建了二叉樹 binarytree.CreateBinaryTree(); //先序遍歷 binarytree.PreOrder(binarytree.root); Console.WriteLine(); //中序遍歷 binarytree.MidOrder(binarytree.root); Console.WriteLine(); //后序遍歷 binarytree.LastOrder(binarytree.root); */ //方法二 //用集合存儲所有的結點 List<String> data = new List<string>(); //存儲先序遍歷每一個結點的數組 String[] dataArray = new string[] {"A","B","D","#","#","E","#","#","C","#","F","#","#"}; //遍歷存儲結點的數組存儲到集合里面 foreach (string item in dataArray) { data.Add(item); } BinaryTree binary = new BinaryTree(); binary.CreateBinaryTree(data);//創建二叉樹 int height = binary.GetHeight();//求二叉樹的高度 Console.WriteLine("二叉樹的高度是"+height); int size = binary.GetSize();//過去所以的結點數 Console.WriteLine("二叉樹的結點數是"+size); binary.TheFirstOrder(binary.root); Console.WriteLine(); binary.TheMidleOrder(binary.root); Console.WriteLine(); binary.TheLastOrder(binary.root); Console.ReadKey(); } } }