/// <summary> /// Поиск элемента в дереве /// </summary> /// <param name="node"></param> /// <returns></returns> /// В классе определен параметр finded для сокращения времени при удалении public bool Contains(T node) { if (Root == null) { return(false); } OneNode <T> el = Root; Queue <OneNode <T> > elems = new Queue <OneNode <T> >(); elems.Enqueue(el); while (elems.Count > 0) { el = elems.Dequeue(); if (el.info.CompareTo(node) == 0) { finded = el; return(true); } if (el.left != null) { elems.Enqueue(el.left); } if (el.right != null) { elems.Enqueue(el.right); } } finded = null; return(false); }
/// <summary> /// Удаление элемента из дерева, если дерево пусто - исключение /// </summary> /// <param name="node"></param> public void Remove(T node) { if (IsEmpty) { throw new RemovingFromEmptyTree(); } if (Contains(node)) { if (OrderNodes.Count == 0) { Clear(); } else { OneNode <T> inf = OrderNodes.Peek().right == null?OrderNodes.Peek().left : OrderNodes.Peek().right; finded.info = inf.info; finded.nodeview.Text = finded.info.ToString(); OneNode <T> peeked = OrderNodes.Pop(); if (peeked.right == null) { peeked.left.nodeview.Remove(); peeked.left = null; } else { peeked.right.nodeview.Remove(); peeked.right = null; } --Count; } } }
/// <summary> /// Перебор и преобразование всех эл-тов дерева /// </summary> /// <param name="tree"></param> /// <param name="action"></param> public static void ForEach(ITree <T> tree, ActionDelegate <T> action) { //Если дерево неизменяемо - исключение if (tree is UnmutableTree <T> ) { throw new AttemptOfChangingUnmutableTree(); } //Специальная форма для кажого представления if (tree is ArrayTree <T> ) { ArrayTree <T> t = (ArrayTree <T>)tree; for (int i = 0; i < tree.Count; ++i) { if (t[i] != null) { t[i].info = action(t[i].info); } } } else { OneNode <T> one = ((ListTree <T>)tree).Root; ForEachList(one, action); } }
//Специальная функция, на случай, если дерево представлено цепочно private static void ForEachList(OneNode <T> node, ActionDelegate <T> action) { if (node != null) { node.info = action(node.info); ForEachList(node.left, action); ForEachList(node.right, action); } }
//Конструктор с 1 обязательным параметром - информационной частью public OneNode(T info, TreeNode v = null) { this.info = info; left = right = null; if (v != null) { nodeview = v; } else { nodeview = new TreeNode(); } }
//Конструктор без обязательных параметров public ListTree(TreeView tree = null) { Root = null; finded = null; Count = 0; OrderNodes = new Stack <OneNode <T> >(); if (tree != null) { view = tree; } else { view = new TreeView(); } }
/// <summary> /// Реализация IEnumerable (обход дерева в ширину (Если дерево пусто - исключение)) /// </summary> /// <returns></returns> public IEnumerator <T> GetEnumerator() { if (IsEmpty) { throw new TryToGetEmptyTree(); } Queue <OneNode <T> > nodesTree = new Queue <OneNode <T> >(); nodesTree.Enqueue(Root); while (nodesTree.Count > 0) { OneNode <T> b = nodesTree.Dequeue(); yield return(b.info); if (b.left != null) { nodesTree.Enqueue(b.left); } if (b.right != null) { nodesTree.Enqueue(b.right); } } }
/// <summary> /// Добавление нового уникального элемента в дерево /// </summary> /// <param name="node"></param> public void Add(T node) { //если дерево пусто - просто добавляем в корень if (Root == null) { TreeNode rootNode = new TreeNode(node.ToString()); view.Nodes.Add(rootNode); Root = new OneNode <T>(node, rootNode); } else { if (!Contains(node)) { //Очередь из узлов по уровням Queue <OneNode <T> > nodes = new Queue <OneNode <T> >(); //Буфер для чтения след узла OneNode <T> buf; //Буфер для хранения узла с пустым правым поддеревом OneNode <T> bufForRight = null; nodes.Enqueue(Root); while (nodes.Count > 0) { //Определяем кол-во узлов на уровне int c = nodes.Count; //Проход по уровню for (int i = 0; i < c; ++i) { buf = nodes.Dequeue(); //если у узла левое поддерево пусто, то добавляем его и возвращаем из функции if (buf.left == null) { TreeNode NewNode = buf.nodeview.Nodes.Add(node.ToString()); buf.left = new OneNode <T>(node, NewNode); OrderNodes.Push(buf); ++Count; return; } else { //Если нет, то кладем в очередь и анализируем правое поддерево nodes.Enqueue(buf.left); //Если таких узлов еще не встречалось, а это первый - запоминаем его if (buf.right == null && bufForRight == null) { bufForRight = buf; } } //Иначе -также кладем в очередь if (buf.right != null) { nodes.Enqueue(buf.right); } } //Ессли нашли узел с пустым правым поддеревом - то создаем в правом поддереве новый узел и возвращаем его if (bufForRight != null) { TreeNode NewNode1 = bufForRight.nodeview.Nodes.Add(node.ToString()); bufForRight.right = new OneNode <T>(node, NewNode1); OrderNodes.Push(bufForRight); ++Count; return; } } } } }