//一直插入是一个根列表 public virtual void Insert(FibonacciNode <T> newNode) { newNode.Degree = 0; newNode.Parent = null; newNode.Child = null; newNode.Left = newNode; newNode.Right = newNode; newNode.Mark = false; if (Peak == null) { Peak = newNode; } else { //insert to root list AddNode(Peak, newNode); if (_com(newNode.Key, Peak.Key)) { Peak = newNode; } } Length = Length + 1; }
//这么基本的操作都有点搞不清,只是交换值不会有什么影响 public void Exchange(ref FibonacciNode <T> x, ref FibonacciNode <T> y) { var temp = x; x = y; y = temp; }
public void Traverse(FibonacciNode <T> startNode, Action <FibonacciNode <T> > action) { foreach (var item in TraverseList(startNode)) { action(item); Traverse(item.Child, action); } }
public virtual FibonacciNode <T> Insert(T key) { var node = new FibonacciNode <T>(); node.Key = key; Insert(node); return(node); }
/// <summary> /// 将新节点插入到双向环形链表 /// </summary> /// <param name="root"></param> /// <param name="newNode"></param> private void AddNode(FibonacciNode <T> root, FibonacciNode <T> newNode) { //将新节点插入到根某节点的Left。 newNode.Left = root.Left; root.Left.Right = newNode; newNode.Right = root; root.Left = newNode; }
/// <summary> /// 合并两个双向环形链表 /// </summary> /// <param name="root"></param> /// <param name="newRoot"></param> private void LinkedIn(FibonacciNode <T> root, FibonacciNode <T> newRoot) { //交换两个链表的Right。 //因为是环形的保证可以合并成一个新的链表 var temp = root.Right; root.Right = newRoot.Right; newRoot.Right.Left = root; newRoot.Right = temp; temp.Left = newRoot; }
/// <summary> /// 不要在回修改引用的情况下使用这个方法 /// </summary> /// <param name="startNode"></param> /// <param name="action"></param> public IEnumerable <FibonacciNode <T> > TraverseList(FibonacciNode <T> node) { if (node == null) { yield break; } var temp = node; do { yield return(temp); temp = temp.Left; }while (temp != node); }
private void CascadingCut(FibonacciNode <T> node) { var parent = node.Parent; if (parent != null) { if (!node.Mark) { node.Mark = true; } else { Cut(node, parent); CascadingCut(parent); } } }
//不能使用 yield ,各种修改引用很容易出问题。 private IEnumerable <FibonacciNode <T> > GetList(FibonacciNode <T> node) { var result = new List <FibonacciNode <T> >(); if (node == null) { return(result); } var temp = node; do { result.Add(temp); temp = temp.Left; }while (temp != node); return(result); }
private void Link(FibonacciNode <T> child, FibonacciNode <T> parent) { DeleteNode(child); if (parent.Child == null) { parent.Child = child; child.Left = child; child.Right = child; } else { AddNode(parent.Child, child); } child.Parent = parent; parent.Degree += 1; child.Mark = false; }
private void Cut(FibonacciNode <T> node, FibonacciNode <T> parent) { //更新Child if (parent.Degree == 1) { parent.Child = null; } else if (parent.Child == node) { parent.Child = node.Right; } DeleteNode(node); parent.Degree = parent.Degree - 1; AddNode(Peak, node); node.Parent = null; node.Mark = false; }
/// <summary> /// Increase和Decrease /// </summary> /// <param name="oldKey"></param> /// <param name="newKey"></param> public void UpdateKey(FibonacciNode <T> node, T newKey) { if (_com(node.Key, newKey)) { return; } node.Key = newKey; var parent = node.Parent; if (parent != null && _com(node.Key, parent.Key)) { Cut(node, parent); CascadingCut(parent); } if (_com(node.Key, Peak.Key)) { Peak = node; } }
//双向环形链表有很多好处 private void DeleteNode(FibonacciNode <T> node) { node.Right.Left = node.Left; node.Left.Right = node.Right; }
/// <summary> /// 因为是泛型不能取最小值,所以暂时不提供删除 /// </summary> /// <param name="node"></param> public void Delete(FibonacciNode <T> node) { }
/// <summary> /// 连接跟节点,使每个度最多只有一个根节点 /// </summary> //使(成串地)连结[衔接]起来 private void Concatenate() { var degreeArray = new FibonacciNode <T> [DegreeCountBound]; var roots = GetList(Peak).ToList(); foreach (var root in roots) { var currentNode = root; var degree = currentNode.Degree; //将相同degree的Node合并成树。 while (degreeArray[degree] != null) { var oldNode = degreeArray[degree]; //构建一个有序树。 if (_com(oldNode.Key, currentNode.Key)) { Exchange(ref currentNode, ref oldNode); } Link(oldNode, currentNode); degreeArray[degree] = null; degree = degree + 1; } degreeArray[degree] = currentNode; } #region //new peak and root list Peak = null; foreach (var item in degreeArray) { if (item != null) { if (Peak == null) { //这个操作比较重要,新的root节点left和right都指向自己 item.Left = item; item.Right = item; Peak = item; } else { AddNode(Peak, item); if (_com(item.Key, Peak.Key)) { Peak = item; } } } } #endregion }