框架更新
This commit is contained in:
@@ -1,190 +0,0 @@
|
||||
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
namespace Fantasy.DataStructure.SkipTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳表数据结构(升序版)
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">跳表中存储的值的类型。</typeparam>
|
||||
public class SkipTable<TValue> : SkipTableBase<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建一个新的跳表实例。
|
||||
/// </summary>
|
||||
/// <param name="maxLayer">跳表的最大层数。</param>
|
||||
public SkipTable(int maxLayer = 8) : base(maxLayer) { }
|
||||
|
||||
/// <summary>
|
||||
/// 向跳表中添加一个新节点。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">节点的主排序键。</param>
|
||||
/// <param name="viceKey">节点的副排序键。</param>
|
||||
/// <param name="key">节点的唯一键。</param>
|
||||
/// <param name="value">要添加的值。</param>
|
||||
public override void Add(long sortKey, long viceKey, long key, TValue value)
|
||||
{
|
||||
var rLevel = 1;
|
||||
|
||||
while (rLevel <= MaxLayer && Random.Next(3) == 0)
|
||||
{
|
||||
++rLevel;
|
||||
}
|
||||
|
||||
SkipTableNode<TValue> cur = TopHeader, last = null;
|
||||
|
||||
for (var layer = MaxLayer; layer >= 1; --layer)
|
||||
{
|
||||
// 节点有next节点,且 (next主键 < 插入主键) 或 (next主键 == 插入主键 且 next副键 < 插入副键)
|
||||
while (cur.Right != null && ((cur.Right.SortKey < sortKey) ||
|
||||
(cur.Right.SortKey == sortKey && cur.Right.ViceKey < viceKey)))
|
||||
{
|
||||
cur = cur.Right;
|
||||
}
|
||||
|
||||
if (layer <= rLevel)
|
||||
{
|
||||
var currentRight = cur.Right;
|
||||
|
||||
// 在当前层插入新节点
|
||||
cur.Right = new SkipTableNode<TValue>(sortKey, viceKey, key, value, layer == 1 ? cur.Index + 1 : 0, cur, cur.Right, null);
|
||||
|
||||
if (currentRight != null)
|
||||
{
|
||||
currentRight.Left = cur.Right;
|
||||
}
|
||||
|
||||
if (last != null)
|
||||
{
|
||||
last.Down = cur.Right;
|
||||
}
|
||||
|
||||
if (layer == 1)
|
||||
{
|
||||
// 更新索引信息
|
||||
cur.Right.Index = cur.Index + 1;
|
||||
Node.Add(key, cur.Right);
|
||||
|
||||
SkipTableNode<TValue> v = cur.Right.Right;
|
||||
|
||||
while (v != null)
|
||||
{
|
||||
v.Index++;
|
||||
v = v.Right;
|
||||
}
|
||||
}
|
||||
|
||||
last = cur.Right;
|
||||
}
|
||||
|
||||
cur = cur.Down;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从跳表中移除一个节点。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">节点的主排序键。</param>
|
||||
/// <param name="viceKey">节点的副排序键。</param>
|
||||
/// <param name="key">节点的唯一键。</param>
|
||||
/// <param name="value">被移除的节点的值。</param>
|
||||
/// <returns>如果成功移除节点,则为 true;否则为 false。</returns>
|
||||
public override bool Remove(long sortKey, long viceKey, long key, out TValue value)
|
||||
{
|
||||
value = default;
|
||||
var seen = false;
|
||||
var cur = TopHeader;
|
||||
|
||||
for (var layer = MaxLayer; layer >= 1; --layer)
|
||||
{
|
||||
// 先按照主键查找 再 按副键查找
|
||||
while (cur.Right != null && cur.Right.SortKey < sortKey && cur.Right.Key != key) cur = cur.Right;
|
||||
while (cur.Right != null && (cur.Right.SortKey == sortKey && cur.Right.ViceKey <= viceKey) &&
|
||||
cur.Right.Key != key) cur = cur.Right;
|
||||
|
||||
var isFind = false;
|
||||
var currentCur = cur;
|
||||
SkipTableNode<TValue> removeCur = null;
|
||||
// 如果当前不是要删除的节点、但主键和副键都一样、需要特殊处理下。
|
||||
if (cur.Right != null && cur.Right.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = cur.Right;
|
||||
currentCur = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 先向左查找下
|
||||
var currentNode = cur.Left;
|
||||
while (currentNode != null && currentNode.SortKey == sortKey && currentNode.ViceKey == viceKey)
|
||||
{
|
||||
if (currentNode.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = currentNode;
|
||||
currentCur = currentNode.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
currentNode = currentNode.Left;
|
||||
}
|
||||
|
||||
// 再向右查找下
|
||||
if (!isFind)
|
||||
{
|
||||
currentNode = cur.Right;
|
||||
while (currentNode != null && currentNode.SortKey == sortKey && currentNode.ViceKey == viceKey)
|
||||
{
|
||||
if (currentNode.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = currentNode;
|
||||
currentCur = currentNode.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
currentNode = currentNode.Right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isFind && currentCur != null)
|
||||
{
|
||||
value = removeCur.Value;
|
||||
currentCur.Right = removeCur.Right;
|
||||
|
||||
if (removeCur.Right != null)
|
||||
{
|
||||
removeCur.Right.Left = currentCur;
|
||||
removeCur.Right = null;
|
||||
}
|
||||
|
||||
removeCur.Left = null;
|
||||
removeCur.Down = null;
|
||||
removeCur.Value = default;
|
||||
|
||||
if (layer == 1)
|
||||
{
|
||||
var tempCur = currentCur.Right;
|
||||
while (tempCur != null)
|
||||
{
|
||||
tempCur.Index--;
|
||||
tempCur = tempCur.Right;
|
||||
}
|
||||
|
||||
Node.Remove(removeCur.Key);
|
||||
}
|
||||
|
||||
seen = true;
|
||||
}
|
||||
|
||||
cur = cur.Down;
|
||||
}
|
||||
|
||||
return seen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8603
|
||||
#pragma warning disable CS8625
|
||||
#pragma warning disable CS8604
|
||||
|
||||
namespace Fantasy.DataStructure.SkipTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 抽象的跳表基类,提供跳表的基本功能和操作。
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">跳表中存储的值的类型。</typeparam>
|
||||
public abstract class SkipTableBase<TValue> : IEnumerable<SkipTableNode<TValue>>
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳表的最大层数
|
||||
/// </summary>
|
||||
public readonly int MaxLayer;
|
||||
/// <summary>
|
||||
/// 跳表的顶部头节点
|
||||
/// </summary>
|
||||
public readonly SkipTableNode<TValue> TopHeader;
|
||||
/// <summary>
|
||||
/// 跳表的底部头节点
|
||||
/// </summary>
|
||||
public SkipTableNode<TValue> BottomHeader;
|
||||
/// <summary>
|
||||
/// 跳表中节点的数量,使用了 Node 字典的计数
|
||||
/// </summary>
|
||||
public int Count => Node.Count;
|
||||
/// <summary>
|
||||
/// 用于生成随机数的随机数生成器
|
||||
/// </summary>
|
||||
protected readonly Random Random = new Random();
|
||||
/// <summary>
|
||||
/// 存储跳表节点的字典
|
||||
/// </summary>
|
||||
protected readonly Dictionary<long, SkipTableNode<TValue>> Node = new();
|
||||
/// <summary>
|
||||
/// 用于辅助反向查找的栈
|
||||
/// </summary>
|
||||
protected readonly Stack<SkipTableNode<TValue>> AntiFindStack = new Stack<SkipTableNode<TValue>>();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化一个新的跳表实例。
|
||||
/// </summary>
|
||||
/// <param name="maxLayer">跳表的最大层数,默认为 8。</param>
|
||||
protected SkipTableBase(int maxLayer = 8)
|
||||
{
|
||||
MaxLayer = maxLayer;
|
||||
var cur = TopHeader = new SkipTableNode<TValue>(long.MinValue, 0, 0, default, 0, null, null, null);
|
||||
|
||||
for (var layer = MaxLayer - 1; layer >= 1; --layer)
|
||||
{
|
||||
cur.Down = new SkipTableNode<TValue>(long.MinValue, 0, 0, default, 0, null, null, null);
|
||||
cur = cur.Down;
|
||||
}
|
||||
|
||||
BottomHeader = cur;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定键的节点的值,若不存在则返回默认值。
|
||||
/// </summary>
|
||||
/// <param name="key">要查找的键。</param>
|
||||
public TValue this[long key] => !TryGetValueByKey(key, out TValue value) ? default : value;
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定键的节点在跳表中的排名。
|
||||
/// </summary>
|
||||
/// <param name="key">要查找的键。</param>
|
||||
/// <returns>节点的排名。</returns>
|
||||
public int GetRanking(long key)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return node.Index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定键的反向排名,即在比该键更大的节点中的排名。
|
||||
/// </summary>
|
||||
/// <param name="key">要查找的键。</param>
|
||||
/// <returns>反向排名。</returns>
|
||||
public int GetAntiRanking(long key)
|
||||
{
|
||||
var ranking = GetRanking(key);
|
||||
|
||||
if (ranking == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Count + 1 - ranking;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试通过键获取节点的值。
|
||||
/// </summary>
|
||||
/// <param name="key">要查找的键。</param>
|
||||
/// <param name="value">获取到的节点的值,如果键不存在则为默认值。</param>
|
||||
/// <returns>是否成功获取节点的值。</returns>
|
||||
public bool TryGetValueByKey(long key, out TValue value)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
value = node.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试通过键获取节点。
|
||||
/// </summary>
|
||||
/// <param name="key">要查找的键。</param>
|
||||
/// <param name="node">获取到的节点,如果键不存在则为 <c>null</c>。</param>
|
||||
/// <returns>是否成功获取节点。</returns>
|
||||
public bool TryGetNodeByKey(long key, out SkipTableNode<TValue> node)
|
||||
{
|
||||
if (Node.TryGetValue(key, out node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在跳表中查找节点,返回从起始位置到结束位置的节点列表。
|
||||
/// </summary>
|
||||
/// <param name="start">起始位置的排名。</param>
|
||||
/// <param name="end">结束位置的排名。</param>
|
||||
/// <param name="list">用于存储节点列表的 <see cref="ListPool{T}"/> 实例。</param>
|
||||
public void Find(int start, int end, ListPool<SkipTableNode<TValue>> list)
|
||||
{
|
||||
var cur = BottomHeader;
|
||||
var count = end - start;
|
||||
|
||||
for (var i = 0; i < start; i++)
|
||||
{
|
||||
cur = cur.Right;
|
||||
}
|
||||
|
||||
for (var i = 0; i <= count; i++)
|
||||
{
|
||||
if (cur == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
list.Add(cur);
|
||||
cur = cur.Right;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在跳表中进行反向查找节点,返回从结束位置到起始位置的节点列表。
|
||||
/// </summary>
|
||||
/// <param name="start">结束位置的排名。</param>
|
||||
/// <param name="end">起始位置的排名。</param>
|
||||
/// <param name="list">用于存储节点列表的 <see cref="ListPool{T}"/> 实例。</param>
|
||||
public void AntiFind(int start, int end, ListPool<SkipTableNode<TValue>> list)
|
||||
{
|
||||
var cur = BottomHeader;
|
||||
start = Count + 1 - start;
|
||||
end = start - end;
|
||||
|
||||
for (var i = 0; i < start; i++)
|
||||
{
|
||||
cur = cur.Right;
|
||||
|
||||
if (cur == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < end)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AntiFindStack.Push(cur);
|
||||
}
|
||||
|
||||
while (AntiFindStack.TryPop(out var node))
|
||||
{
|
||||
list.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取跳表中最后一个节点的值。
|
||||
/// </summary>
|
||||
/// <returns>最后一个节点的值。</returns>
|
||||
public TValue GetLastValue()
|
||||
{
|
||||
var cur = TopHeader;
|
||||
|
||||
while (cur.Right != null || cur.Down != null)
|
||||
{
|
||||
while (cur.Right != null)
|
||||
{
|
||||
cur = cur.Right;
|
||||
}
|
||||
|
||||
if (cur.Down != null)
|
||||
{
|
||||
cur = cur.Down;
|
||||
}
|
||||
}
|
||||
|
||||
return cur.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除跳表中指定键的节点。
|
||||
/// </summary>
|
||||
/// <param name="key">要移除的节点的键。</param>
|
||||
/// <returns>移除是否成功。</returns>
|
||||
public bool Remove(long key)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Remove(node.SortKey, node.ViceKey, key, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向跳表中添加节点。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">节点的排序键。</param>
|
||||
/// <param name="viceKey">节点的副键。</param>
|
||||
/// <param name="key">节点的键。</param>
|
||||
/// <param name="value">节点的值。</param>
|
||||
public abstract void Add(long sortKey, long viceKey, long key, TValue value);
|
||||
|
||||
/// <summary>
|
||||
/// 从跳表中移除指定键的节点。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">节点的排序键。</param>
|
||||
/// <param name="viceKey">节点的副键。</param>
|
||||
/// <param name="key">节点的键。</param>
|
||||
/// <param name="value">被移除的节点的值。</param>
|
||||
/// <returns>移除是否成功。</returns>
|
||||
public abstract bool Remove(long sortKey, long viceKey, long key, out TValue value);
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个枚举器,用于遍历跳表中的节点。
|
||||
/// </summary>
|
||||
/// <returns>一个可用于遍历跳表节点的枚举器。</returns>
|
||||
public IEnumerator<SkipTableNode<TValue>> GetEnumerator()
|
||||
{
|
||||
var cur = BottomHeader.Right;
|
||||
while (cur != null)
|
||||
{
|
||||
yield return cur;
|
||||
cur = cur.Right;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个非泛型枚举器,用于遍历跳表中的节点。
|
||||
/// </summary>
|
||||
/// <returns>一个非泛型枚举器,可用于遍历跳表节点。</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
namespace Fantasy.DataStructure.SkipTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳表降序版,用于存储降序排列的数据。
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">存储的值的类型。</typeparam>
|
||||
public class SkipTableDesc<TValue> : SkipTableBase<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化跳表降序版的新实例。
|
||||
/// </summary>
|
||||
/// <param name="maxLayer">跳表的最大层数,默认为 8。</param>
|
||||
public SkipTableDesc(int maxLayer = 8) : base(maxLayer) { }
|
||||
|
||||
/// <summary>
|
||||
/// 向跳表中添加一个节点,根据降序规则进行插入。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">排序主键。</param>
|
||||
/// <param name="viceKey">副键。</param>
|
||||
/// <param name="key">键。</param>
|
||||
/// <param name="value">值。</param>
|
||||
public override void Add(long sortKey, long viceKey, long key, TValue value)
|
||||
{
|
||||
var rLevel = 1;
|
||||
|
||||
while (rLevel <= MaxLayer && Random.Next(3) == 0)
|
||||
{
|
||||
++rLevel;
|
||||
}
|
||||
|
||||
SkipTableNode<TValue> cur = TopHeader, last = null;
|
||||
|
||||
for (var layer = MaxLayer; layer >= 1; --layer)
|
||||
{
|
||||
// 节点有next节点,且 (next主键 > 插入主键) 或 (next主键 == 插入主键 且 next副键 > 插入副键)
|
||||
while (cur.Right != null && ((cur.Right.SortKey > sortKey) ||
|
||||
(cur.Right.SortKey == sortKey && cur.Right.ViceKey > viceKey)))
|
||||
{
|
||||
cur = cur.Right;
|
||||
}
|
||||
|
||||
if (layer <= rLevel)
|
||||
{
|
||||
var currentRight = cur.Right;
|
||||
cur.Right = new SkipTableNode<TValue>(sortKey, viceKey, key, value,
|
||||
layer == 1 ? cur.Index + 1 : 0, cur, cur.Right, null);
|
||||
|
||||
if (currentRight != null)
|
||||
{
|
||||
currentRight.Left = cur.Right;
|
||||
}
|
||||
|
||||
if (last != null)
|
||||
{
|
||||
last.Down = cur.Right;
|
||||
}
|
||||
|
||||
if (layer == 1)
|
||||
{
|
||||
cur.Right.Index = cur.Index + 1;
|
||||
Node.Add(key, cur.Right);
|
||||
|
||||
SkipTableNode<TValue> v = cur.Right.Right;
|
||||
|
||||
while (v != null)
|
||||
{
|
||||
v.Index++;
|
||||
v = v.Right;
|
||||
}
|
||||
}
|
||||
|
||||
last = cur.Right;
|
||||
}
|
||||
|
||||
cur = cur.Down;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从跳表中移除一个节点,根据降序规则进行移除。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">排序主键。</param>
|
||||
/// <param name="viceKey">副键。</param>
|
||||
/// <param name="key">键。</param>
|
||||
/// <param name="value">移除的节点值。</param>
|
||||
/// <returns>如果成功移除节点,则返回 true,否则返回 false。</returns>
|
||||
public override bool Remove(long sortKey, long viceKey, long key, out TValue value)
|
||||
{
|
||||
value = default;
|
||||
var seen = false;
|
||||
var cur = TopHeader;
|
||||
|
||||
for (var layer = MaxLayer; layer >= 1; --layer)
|
||||
{
|
||||
// 先按照主键查找 再 按副键查找
|
||||
while (cur.Right != null && cur.Right.SortKey > sortKey && cur.Right.Key != key) cur = cur.Right;
|
||||
while (cur.Right != null && (cur.Right.SortKey == sortKey && cur.Right.ViceKey >= viceKey) &&
|
||||
cur.Right.Key != key) cur = cur.Right;
|
||||
|
||||
var isFind = false;
|
||||
var currentCur = cur;
|
||||
SkipTableNode<TValue> removeCur = null;
|
||||
// 如果当前不是要删除的节点、但主键和副键都一样、需要特殊处理下。
|
||||
if (cur.Right != null && cur.Right.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = cur.Right;
|
||||
currentCur = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 先向左查找下
|
||||
var currentNode = cur.Left;
|
||||
while (currentNode != null && currentNode.SortKey == sortKey && currentNode.ViceKey == viceKey)
|
||||
{
|
||||
if (currentNode.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = currentNode;
|
||||
currentCur = currentNode.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
currentNode = currentNode.Left;
|
||||
}
|
||||
|
||||
// 再向右查找下
|
||||
if (!isFind)
|
||||
{
|
||||
currentNode = cur.Right;
|
||||
while (currentNode != null && currentNode.SortKey == sortKey && currentNode.ViceKey == viceKey)
|
||||
{
|
||||
if (currentNode.Key == key)
|
||||
{
|
||||
isFind = true;
|
||||
removeCur = currentNode;
|
||||
currentCur = currentNode.Left;
|
||||
break;
|
||||
}
|
||||
|
||||
currentNode = currentNode.Right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isFind && currentCur != null)
|
||||
{
|
||||
value = removeCur.Value;
|
||||
currentCur.Right = removeCur.Right;
|
||||
|
||||
if (removeCur.Right != null)
|
||||
{
|
||||
removeCur.Right.Left = currentCur;
|
||||
removeCur.Right = null;
|
||||
}
|
||||
|
||||
removeCur.Left = null;
|
||||
removeCur.Down = null;
|
||||
removeCur.Value = default;
|
||||
|
||||
if (layer == 1)
|
||||
{
|
||||
var tempCur = currentCur.Right;
|
||||
while (tempCur != null)
|
||||
{
|
||||
tempCur.Index--;
|
||||
tempCur = tempCur.Right;
|
||||
}
|
||||
|
||||
Node.Remove(removeCur.Key);
|
||||
}
|
||||
|
||||
seen = true;
|
||||
}
|
||||
|
||||
cur = cur.Down;
|
||||
}
|
||||
|
||||
return seen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
namespace Fantasy.DataStructure.SkipTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳跃表节点。
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">节点的值的类型。</typeparam>
|
||||
public class SkipTableNode<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点在跳跃表中的索引。
|
||||
/// </summary>
|
||||
public int Index;
|
||||
/// <summary>
|
||||
/// 节点的主键。
|
||||
/// </summary>
|
||||
public long Key;
|
||||
/// <summary>
|
||||
/// 节点的排序键。
|
||||
/// </summary>
|
||||
public long SortKey;
|
||||
/// <summary>
|
||||
/// 节点的副键。
|
||||
/// </summary>
|
||||
public long ViceKey;
|
||||
/// <summary>
|
||||
/// 节点存储的值。
|
||||
/// </summary>
|
||||
public TValue Value;
|
||||
/// <summary>
|
||||
/// 指向左侧节点的引用。
|
||||
/// </summary>
|
||||
public SkipTableNode<TValue> Left;
|
||||
/// <summary>
|
||||
/// 指向右侧节点的引用。
|
||||
/// </summary>
|
||||
public SkipTableNode<TValue> Right;
|
||||
/// <summary>
|
||||
/// 指向下一层节点的引用。
|
||||
/// </summary>
|
||||
public SkipTableNode<TValue> Down;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化跳跃表节点的新实例。
|
||||
/// </summary>
|
||||
/// <param name="sortKey">节点的排序键。</param>
|
||||
/// <param name="viceKey">节点的副键。</param>
|
||||
/// <param name="key">节点的主键。</param>
|
||||
/// <param name="value">节点存储的值。</param>
|
||||
/// <param name="index">节点在跳跃表中的索引。</param>
|
||||
/// <param name="l">指向左侧节点的引用。</param>
|
||||
/// <param name="r">指向右侧节点的引用。</param>
|
||||
/// <param name="d">指向下一层节点的引用。</param>
|
||||
public SkipTableNode(long sortKey, long viceKey, long key, TValue value, int index,
|
||||
SkipTableNode<TValue> l,
|
||||
SkipTableNode<TValue> r,
|
||||
SkipTableNode<TValue> d)
|
||||
{
|
||||
Left = l;
|
||||
Right = r;
|
||||
Down = d;
|
||||
Value = value;
|
||||
Key = key;
|
||||
Index = index;
|
||||
SortKey = sortKey;
|
||||
ViceKey = viceKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user