C#实现二叉树--二叉链表结构
二叉树的简单介绍
关于二叉树的介绍请看这里 :
二叉树的简单介绍 http://www.cnblogs.com/JiYF/p/7048785.html
二叉链表存储结构:
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。其结点结构为:
其中,data域存放某结点的数据信息;lchild与rchild分别存放指向左孩子和右孩子的指针,当左孩子或右孩子不存在时,相应指针域值为空(用符号∧或NULL表示)。利用这样的结点结构表示的二叉树的链式存储结构被称为二叉链表,如图5-8所示。
C#实现代码
二叉树的节点类:
1 Binary Tree 2 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 8 namespace DataStructure 9 { 10 /// <summary> 11 /// 二叉链表结点类 12 /// </summary> 13 /// <typeparam name="T"></typeparam> 14 public class TreeNode<T> 15 { 16 private T data; //数据域 17 private TreeNode<T> lChild; //左孩子 树中一个结点的子树的根结点称为这个结点的孩子 18 private TreeNode<T> rChild; //右孩子 19 20 public TreeNode(T val, TreeNode<T> lp, TreeNode<T> rp) 21 { 22 data = val; 23 lChild = lp; 24 rChild = rp; 25 } 26 27 public TreeNode(TreeNode<T> lp, TreeNode<T> rp) 28 { 29 data = default(T); 30 lChild = lp; 31 rChild = rp; 32 } 33 34 public TreeNode(T val) 35 { 36 data = val; 37 lChild = null; 38 rChild = null; 39 } 40 41 public TreeNode() 42 { 43 data = default(T); 44 lChild = null; 45 rChild = null; 46 } 47 48 public T Data 49 { 50 get { return data; } 51 set { data = value; } 52 } 53 54 public TreeNode<T> LChild 55 { 56 get { return lChild; } 57 set { lChild = value; } 58 } 59 60 public TreeNode<T> RChild 61 { 62 get { return rChild; } 63 set { rChild = value; } 64 } 65 66 }
定义索引文件结点的数据类型
1 /// <summary> 2 /// 定义索引文件结点的数据类型 3 /// </summary> 4 public struct indexnode 5 { 6 int key; //键 7 int offset; //位置 8 public indexnode(int key, int offset) 9 { 10 this.key = key; 11 this.offset = offset; 12 } 13 14 //键属性 15 public int Key 16 { 17 get { return key; } 18 set { key = value; } 19 } 20 //位置属性 21 public int Offset 22 { 23 get { return offset; } 24 set { offset = value; } 25 } 26 27 28 } 29 30 31 public class LinkBinaryTree<T> 32 { 33 private TreeNode<T> head; //头引用 34 35 public TreeNode<T> Head 36 { 37 get { return head; } 38 set { head = value; } 39 } 40 41 public LinkBinaryTree() 42 { 43 head = null; 44 } 45 46 public LinkBinaryTree(T val) 47 { 48 TreeNode<T> p = new TreeNode<T>(val); 49 head = p; 50 } 51 52 public LinkBinaryTree(T val, TreeNode<T> lp, TreeNode<T> rp) 53 { 54 TreeNode<T> p = new TreeNode<T>(val, lp, rp); 55 head = p; 56 } 57 58 //判断是否是空二叉树 59 public bool IsEmpty() 60 { 61 if (head == null) 62 return true; 63 else 64 return false; 65 } 66 67 //获取根结点 68 public TreeNode<T> Root() 69 { 70 return head; 71 } 72 73 //获取结点的左孩子结点 74 public TreeNode<T> GetLChild(TreeNode<T> p) 75 { 76 return p.LChild; 77 } 78 79 public TreeNode<T> GetRChild(TreeNode<T> p) 80 { 81 return p.RChild; 82 } 83 84 //将结点p的左子树插入值为val的新结点,原来的左子树称为新结点的左子树 85 public void InsertL(T val, TreeNode<T> p) 86 { 87 TreeNode<T> tmp = new TreeNode<T>(val); 88 tmp.LChild = p.LChild; 89 p.LChild = tmp; 90 } 91 92 //将结点p的右子树插入值为val的新结点,原来的右子树称为新节点的右子树 93 public void InsertR(T val, TreeNode<T> p) 94 { 95 TreeNode<T> tmp = new TreeNode<T>(val); 96 tmp.RChild = p.RChild; 97 p.RChild = tmp; 98 } 99 100 //若p非空 删除p的左子树 101 public TreeNode<T> DeleteL(TreeNode<T> p) 102 { 103 if ((p == null) || (p.LChild == null)) 104 return null; 105 TreeNode<T> tmp = p.LChild; 106 p.LChild = null; 107 return tmp; 108 } 109 110 //若p非空 删除p的右子树 111 public TreeNode<T> DeleteR(TreeNode<T> p) 112 { 113 if ((p == null) || (p.RChild == null)) 114 return null; 115 TreeNode<T> tmp = p.RChild; 116 p.RChild = null; 117 return tmp; 118 } 119 120 //编写算法 在二叉树中查找值为value的结点 121 122 public TreeNode<T> Search(TreeNode<T> root, T value) 123 { 124 TreeNode<T> p = root; 125 if (p == null) 126 return null; 127 if (!p.Data.Equals(value)) 128 return p; 129 if (p.LChild != null) 130 { 131 return Search(p.LChild, value); 132 } 133 if (p.RChild != null) 134 { 135 return Search(p.RChild, value); 136 } 137 return null; 138 } 139 140 //判断是否是叶子结点 141 public bool IsLeaf(TreeNode<T> p) 142 { 143 if ((p != null) && (p.RChild == null) && (p.LChild == null)) 144 return true; 145 else 146 return false; 147 } 148 149 150 //中序遍历 151 //遍历根结点的左子树->根结点->遍历根结点的右子树 152 public void inorder(TreeNode<T> ptr) 153 { 154 if (IsEmpty()) 155 { 156 Console.WriteLine("Tree is Empty !"); 157 return; 158 } 159 if (ptr != null) 160 { 161 inorder(ptr.LChild); 162 Console.WriteLine(ptr.Data + " "); 163 inorder(ptr.RChild); 164 } 165 } 166 167 168 //先序遍历 169 //根结点->遍历根结点的左子树->遍历根结点的右子树 170 public void preorder(TreeNode<T> ptr) 171 { 172 if (IsEmpty()) 173 { 174 Console.WriteLine("Tree is Empty !"); 175 return; 176 } 177 if (ptr != null) 178 { 179 Console.WriteLine(ptr.Data + " "); 180 preorder(ptr.LChild); 181 preorder(ptr.RChild); 182 } 183 } 184 185 186 //后序遍历 187 //遍历根结点的左子树->遍历根结点的右子树->根结点 188 public void postorder(TreeNode<T> ptr) 189 { 190 if (IsEmpty()) 191 { 192 Console.WriteLine("Tree is Empty !"); 193 return; 194 } 195 if (ptr != null) 196 { 197 postorder(ptr.LChild); 198 postorder(ptr.RChild); 199 Console.WriteLine(ptr.Data + ""); 200 } 201 } 202 203 204 //层次遍历 205 //引入队列 206 public void LevelOrder(TreeNode<T> root) 207 { 208 if (root == null) 209 { 210 return; 211 } 212 CSeqQueue<TreeNode<T>> sq = new CSeqQueue<TreeNode<T>>(50); 213 sq.EnQueue(root); 214 while (!sq.IsEmpty()) 215 { 216 //结点出队 217 TreeNode<T> tmp = sq.DeQueue(); 218 //处理当前结点 219 Console.WriteLine("{0}", tmp); 220 //将当前结点的左孩子结点入队 221 if (tmp.LChild != null) 222 { 223 sq.EnQueue(tmp.LChild); 224 } 225 if (tmp.RChild != null) 226 { 227 sq.EnQueue(tmp.RChild); 228 } 229 } 230 } 231 }
二叉搜索树:结点的左子节点的值永远小于该结点的值,而右子结点的值永远大于该结点的值 称为二叉搜索树
1 /// <summary> 2 /// 二叉搜索树:结点的左子节点的值永远小于该结点的值,而右子结点的值永远大于该结点的值 称为二叉搜索树 3 /// </summary> 4 public class LinkBinarySearchTree : LinkBinaryTree<indexnode> 5 { 6 //定义增加结点的方法 7 public void insert(indexnode element) 8 { 9 TreeNode<indexnode> tmp, parent = null, currentNode = null; 10 //调用FIND方法 11 find(element, ref parent, ref currentNode); 12 if (currentNode != null) 13 { 14 Console.WriteLine("Duplicates words not allowed"); 15 return; 16 } 17 else 18 { 19 //创建结点 20 tmp = new TreeNode<indexnode>(element); 21 if (parent == null) 22 Head = tmp; 23 else 24 { 25 if (element.Key < parent.Data.Key) 26 parent.LChild = tmp; 27 else 28 parent.RChild = tmp; 29 } 30 } 31 } 32 33 //定义父结点 34 public void find(indexnode element, ref TreeNode<indexnode> parent, ref TreeNode<indexnode> currentNode) 35 { 36 currentNode = Head; 37 parent = null; 38 while ((currentNode != null) && (currentNode.Data.Key.ToString() != element.Key.ToString()) && (currentNode.Data.Offset .ToString() != element.Offset .ToString()))// 39 { 40 parent = currentNode; 41 if (element.Key < currentNode.Data.Key) 42 currentNode = currentNode.LChild; 43 else 44 currentNode = currentNode.RChild; 45 } 46 } 47 48 //定位结点 49 public void find(int key) 50 { 51 TreeNode<indexnode> currentNode = Head; 52 while ((currentNode != null) && (currentNode.Data.Key.ToString () != key.ToString ())) 53 { 54 Console.WriteLine(currentNode.Data.Offset.ToString()); 55 if (key < currentNode.Data.Key) 56 currentNode = currentNode.LChild; 57 else 58 currentNode = currentNode.RChild; 59 } 60 } 61 62 //中序遍历 63 //遍历根结点的左子树->根结点->遍历根结点的右子树 64 public void inorderS(TreeNode<indexnode> ptr) 65 { 66 if (IsEmpty()) 67 { 68 Console.WriteLine("Tree is Empty !"); 69 return; 70 } 71 if (ptr != null) 72 { 73 inorderS(ptr.LChild); 74 Console.WriteLine(ptr.Data.Key + " "); 75 inorderS(ptr.RChild); 76 } 77 } 78 79 80 //先序遍历 81 //根结点->遍历根结点的左子树->遍历根结点的右子树 82 public void preorderS(TreeNode<indexnode> ptr) 83 { 84 if (IsEmpty()) 85 { 86 Console.WriteLine("Tree is Empty !"); 87 return; 88 } 89 if (ptr != null) 90 { 91 Console.WriteLine(ptr.Data.Key + " "); 92 preorderS(ptr.LChild); 93 preorderS(ptr.RChild); 94 } 95 } 96 97 98 //后序遍历 99 //遍历根结点的左子树->遍历根结点的右子树->根结点 100 public void postorderS(TreeNode<indexnode> ptr) 101 { 102 if (IsEmpty()) 103 { 104 Console.WriteLine("Tree is Empty !"); 105 return; 106 } 107 if (ptr != null) 108 { 109 postorderS(ptr.LChild); 110 postorderS(ptr.RChild); 111 Console.WriteLine(ptr.Data.Key + ""); 112 } 113 } 114 } 115 116 117 /// <summary> 118 /// 循环顺序队列 119 /// </summary> 120 /// <typeparam name="T"></typeparam> 121 class CSeqQueue<T> 122 { 123 private int maxsize; //循环顺序队列的容量 124 private T[] data; //数组,用于存储循环顺序队列中的数据元素 125 private int front; //指示最近一个已经离开队列的元素所占有的位置 循环顺序队列的对头 126 private int rear; //指示最近一个进入队列的元素的位置 循环顺序队列的队尾 127 128 public T this[int index] 129 { 130 get { return data[index]; } 131 set { data[index] = value; } 132 } 133 134 //容量属性 135 public int Maxsize 136 { 137 get { return maxsize; } 138 set { maxsize = value; } 139 } 140 141 //对头指示器属性 142 public int Front 143 { 144 get { return front; } 145 set { front = value; } 146 } 147 148 //队尾指示器属性 149 public int Rear 150 { 151 get { return rear; } 152 set { rear = value; } 153 } 154 155 public CSeqQueue() 156 { 157 158 } 159 160 public CSeqQueue(int size) 161 { 162 data = new T[size]; 163 maxsize = size; 164 front = rear = -1; 165 } 166 167 //判断循环顺序队列是否为满 168 public bool IsFull() 169 { 170 if ((front == -1 && rear == maxsize - 1) || (rear + 1) % maxsize == front) 171 return true; 172 else 173 return false; 174 } 175 176 //清空循环顺序列表 177 public void Clear() 178 { 179 front = rear = -1; 180 } 181 182 //判断循环顺序队列是否为空 183 public bool IsEmpty() 184 { 185 if (front == rear) 186 return true; 187 else 188 return false; 189 } 190 191 //入队操作 192 public void EnQueue(T elem) 193 { 194 if (IsFull()) 195 { 196 Console.WriteLine("Queue is Full !"); 197 return; 198 } 199 rear = (rear + 1) % maxsize; 200 data[rear] = elem; 201 } 202 203 //出队操作 204 public T DeQueue() 205 { 206 if (IsEmpty()) 207 { 208 Console.WriteLine("Queue is Empty !"); 209 return default(T); 210 } 211 front = (front + 1) % maxsize; 212 return data[front]; 213 } 214 215 //获取对头数据元素 216 public T GetFront() 217 { 218 if (IsEmpty()) 219 { 220 Console.WriteLine("Queue is Empty !"); 221 return default(T); 222 } 223 return data[(front + 1) % maxsize];//front从-1开始 224 } 225 226 //求循环顺序队列的长度 227 public int GetLength() 228 { 229 return (rear - front + maxsize) % maxsize; 230 } 231 }