C# 数据结构 之 树
树(Tree)是n(n>=0)个相同类型的数据元素的有限集合。树中的数据元素叫结点(Node)。n=0的树称为空树(Empty Tree);对于n>0的任意非空树T有:
1.有且只有一个特殊的结点称为树的根(Root)结点,根没有前驱结点。
2.若n>1,则除根结点外,其余结点被分成了m(m>0)个互不相交的集合T1,T2,T3,...Tm,其中每个集合Ti(1<=i<=m)本身又是一棵树。树T1,T2,...Tm称为这棵树的子树(Subtree)。
由树的定义可知,树的定义是递归的,用树来定义树,因此,树的许多运算都使用过了递归。
树的相关术语
结点(Node)。表示树中的数据元素,由数据项和数据元素之间的关系组成。
结点的度。结点所拥有的子树的个数。
树的度。树中各结点度的最大值。
叶子结点。度为0的结点,也叫终端结点。
其他术语参考二叉树。
用多重链表表示法存储树
每个结点指针域的个数等于树的度数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DataStructure { public interface ITree<T> { T Root(); //求树的根结点 T Parent(T t); //求结点t的双亲结点 T Child(T t, int i); //求结点t的第i个子结点 T RightSibling(T t); //求结点t第一个右边兄弟结点 bool Insert(T s, T t, int i); //将树s加入树中作为结点t的第i颗子树 T Delete(T t, int i); //删除结点t的第i颗子树 void Traverse(int TraverseType); //按某种方式遍历树 void Clear(); //清空树 bool IsEmpty(); //判断是否为空 int GetDepth(T t); //求树的深度 } /// <summary> /// 循环顺序队列 /// </summary> /// <typeparam name="T"></typeparam> class CSeqQueue<T> { private int maxsize; //循环顺序队列的容量 private T[] data; //数组,用于存储循环顺序队列中的数据元素 private int front; //指示最近一个已经离开队列的元素所占有的位置 循环顺序队列的对头 private int rear; //指示最近一个进入队列的元素的位置 循环顺序队列的队尾 public T this[int index] { get { return data[index]; } set { data[index] = value; } } //容量属性 public int Maxsize { get { return maxsize; } set { maxsize = value; } } //对头指示器属性 public int Front { get { return front; } set { front = value; } } //队尾指示器属性 public int Rear { get { return rear; } set { rear = value; } } public CSeqQueue() { } public CSeqQueue(int size) { data = new T[size]; maxsize = size; front = rear = -1; } //判断循环顺序队列是否为满 public bool IsFull() { if ((front == -1 && rear == maxsize - 1) || (rear + 1) % maxsize == front) return true; else return false; } //清空循环顺序列表 public void Clear() { front = rear = -1; } //判断循环顺序队列是否为空 public bool IsEmpty() { if (front == rear) return true; else return false; } //入队操作 public void EnQueue(T elem) { if (IsFull()) { Console.WriteLine("Queue is Full !"); return; } rear = (rear + 1) % maxsize; data[rear] = elem; } //出队操作 public T DeQueue() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } front = (front + 1) % maxsize; return data[front]; } //获取对头数据元素 public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } return data[(front + 1) % maxsize];//front从-1开始 } //求循环顺序队列的长度 public int GetLength() { return (rear - front + maxsize) % maxsize; } } /// <summary> /// 树的多链表结点类 /// </summary> /// <typeparam name="T"></typeparam> class MLNode<T> { private T data; //存储结点的数据 private MLNode<T>[] childs; //存储子结点的位置 public MLNode(int max) { childs = new MLNode<T>[max]; for (int i = 0; i < childs.Length; i++) { childs[i] = null; } } public T Data { get { return data; } set { data = value; } } public MLNode<T>[] Childs { get { return childs; } set { childs = value; } } } class MLTree<T> : ITree<MLNode<T>> { private MLNode<T> head; public MLNode<T> Head { get { return head; } set { head = value; } } public MLTree() { head = null; } public MLTree(MLNode<T> node) { head = node; } //求树的根结点 public MLNode<T> Root() { return head; } public void Clear() { head = null; } //待测试!!! public int GetDepth(MLNode <T> root) { int len; if (root == null) { return 0; } for (int i = 0; i < root.Childs.Length; i++) { if (root.Childs[i] != null) { len = GetDepth(root.Childs[i]); return len + 1; } } return 0; } public bool IsEmpty() { return head == null; } //求结点t的双亲结点,如果t的双亲结点存在,返回双亲结点,否则返回空 //按层序遍历的算法进行查找 public MLNode<T> Parent(MLNode<T> t) { MLNode<T> temp = head; if (IsEmpty() || t == null) return null; if (temp.Data.Equals(t.Data)) return null; CSeqQueue<MLNode<T>> queue = new CSeqQueue<MLNode<T>>(50); queue.EnQueue(temp); while (!queue.IsEmpty()) { temp = (MLNode<T>)queue.DeQueue(); for (int i = 0; i < temp.Childs.Length; i++) { if (temp.Childs[i] != null) { if (temp.Childs[i].Data.Equals(t.Data)) { return temp; } else { queue.EnQueue(temp.Childs[i]); } } } } return null; } //求结点t的第i个子结点。如果存在,返回第i个子结点,否则返回空 //i=0时,表示求第一个子节点 public MLNode<T> Child(MLNode<T> t, int i) { if (t != null && i < t.Childs.Length) { return t.Childs[i]; } else { return null; } } //求结点t第一个右边兄弟结点,如果存在,返回第一个右边兄弟结点,否则返回空 public MLNode<T> RightSibling(MLNode<T> t) { MLNode<T> pt = Parent(t); if (pt != null) { int i = FindRank(t); return Child(pt, i + 1); } else { return null; } } //查找结点t在兄弟中的排行,成功时返回位置,否则返回-1 private int FindRank(MLNode<T> t) { MLNode<T> pt = Parent(t); for (int i = 0; i < pt.Childs.Length; i++) { MLNode<T> temp = pt.Childs[i]; if (temp != null && temp.Data.Equals(t.Data)) { return i; } } return -1; } //查找在树中的结点t,成功是返回t的位置,否则返回null private MLNode<T> FindNode(MLNode<T> t) { if (head.Data.Equals(t.Data)) return head; MLNode<T> pt = Parent(t); foreach (MLNode<T> temp in pt.Childs) { if (temp != null && temp.Data.Equals(t.Data)) { return temp; } } return null; } //把以s为头结点的树插入到树中作为结点t的第i颗子树。成功返回true public bool Insert(MLNode<T> s, MLNode<T> t, int i) { if (IsEmpty()) head = t; t = FindNode(t); if (t != null && t.Childs.Length > i) { t.Childs[i] = s; return true; } else { return false; } } //删除结点t的第i个子树。返回第i颗子树的根结点。 public MLNode<T> Delete(MLNode<T> t, int i) { t = FindNode(t); MLNode<T> node = null; if (t != null && t.Childs.Length > i) { node = t.Childs[i]; t.Childs[i] = null; } return node; } //先序遍历 //根结点->遍历根结点的左子树->遍历根结点的右子树 public void preorder(MLNode<T> root) { if (root == null) return; Console.WriteLine(root.Data + " "); for (int i = 0; i < root.Childs.Length; i++) { preorder(root.Childs[i]); } } //后序遍历 //遍历根结点的左子树->遍历根结点的右子树->根结点 public void postorder(MLNode<T> root) { if (root == null) { return; } for (int i = 0; i < root.Childs.Length; i++) { postorder(root.Childs[i]); } Console.WriteLine(root.Data + " "); } //层次遍历 //引入队列 public void LevelOrder(MLNode<T> root) { Console.WriteLine("遍历开始:"); if (root == null) { Console.WriteLine("没有结点!"); return; } MLNode<T> temp = root; CSeqQueue<MLNode<T>> queue = new CSeqQueue<MLNode<T>>(50); queue.EnQueue(temp); while (!queue.IsEmpty()) { temp = (MLNode<T>)queue.DeQueue(); Console.WriteLine(temp.Data + " "); for (int i = 0; i < temp.Childs.Length; i++) { if (temp.Childs[i] != null) { queue.EnQueue(temp.Childs[i]); } } } Console.WriteLine("遍历结束!"); } //按某种方式遍历树 //0 先序 //1 后序 //2 层序 public void Traverse(int TraverseType) { if (TraverseType == 0) preorder(head); else if (TraverseType == 1) postorder(head); else LevelOrder(head); } } class Tree { static void Main(string[] args) { MLTree<string> tree = new MLTree<string>(); char ch; do { Console.WriteLine("1.添加结点"); Console.WriteLine("2.删除结点"); Console.WriteLine("3.遍历树"); Console.WriteLine("4.添加子结点"); Console.WriteLine("5.退出"); Console.WriteLine(); ch = Convert.ToChar(Console.ReadLine()); switch (ch) { case '1': Console.WriteLine("输入父结点:"); string str = Convert.ToString(Console.ReadLine()); MLNode<string> pt = new MLNode<string>(4); pt.Data = str; Console.WriteLine("输入子结点:"); str = Convert.ToString(Console.ReadLine()); MLNode<string> ct = new MLNode<string>(4); ct.Data = str; Console.WriteLine("输入插入子结点的位置:"); int i = Convert.ToInt32(Console.ReadLine()); bool ok = tree.Insert(ct, pt, i); if (ok) { Console.WriteLine("插入{0}成功", ct.Data); Console.WriteLine(tree.GetDepth(pt)); } break; case '2': Console.WriteLine("输入要删除的结点:"); str = Convert.ToString(Console.ReadLine()); pt = new MLNode<string>(4); pt.Data = str; tree.Delete(pt, 0); break; case '3': tree.Traverse(2); break; } } while (ch != '5'); } } }
树的遍历
1.先序遍历
访问数的根结点->按照从左到右的顺序先序遍历树中的每一颗树
2.后序遍历
按照从左到右的顺序后序遍历树中的每一颗子树->访问根结点
3.层序遍历
按照树的结构从上到下 从左到右的顺序访问树的结点。
树的存储方式
双亲表示法
孩子链表表示法
多重链表表示法
双亲孩子表示法
孩子兄弟表示法
注:本文整理自《数据结构(C#语言版)》!!!
posted on 2012-08-29 10:50 YuanSong 阅读(12225) 评论(1) 编辑 收藏 举报