mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] TEngineServer
[+] TEngineServer
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
#pragma warning disable CS8602
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8625
|
||||
#pragma warning disable CS8604
|
||||
#pragma warning disable CS8600
|
||||
namespace TEngine.DataStructure
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳表升序版
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
public class SkipTable<TValue> : SkipTableBase<TValue>
|
||||
{
|
||||
public SkipTable(int maxLayer = 8) : base(maxLayer) { }
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94af5a03823f82246a24b4e5dfdc2be5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8603
|
||||
#pragma warning disable CS8625
|
||||
#pragma warning disable CS8604
|
||||
|
||||
namespace TEngine.DataStructure
|
||||
{
|
||||
public abstract class SkipTableBase<TValue> : IEnumerable<SkipTableNode<TValue>>
|
||||
{
|
||||
public readonly int MaxLayer;
|
||||
public readonly SkipTableNode<TValue> TopHeader;
|
||||
public SkipTableNode<TValue> BottomHeader;
|
||||
|
||||
public int Count => Node.Count;
|
||||
protected readonly Random Random = new Random();
|
||||
protected readonly Dictionary<long, SkipTableNode<TValue>> Node = new();
|
||||
protected readonly Stack<SkipTableNode<TValue>> AntiFindStack = new Stack<SkipTableNode<TValue>>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public TValue this[long key] => !TryGetValueByKey(key, out TValue value) ? default : value;
|
||||
|
||||
public int GetRanking(long key)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return node.Index;
|
||||
}
|
||||
|
||||
public int GetAntiRanking(long key)
|
||||
{
|
||||
var ranking = GetRanking(key);
|
||||
|
||||
if (ranking == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Count + 1 - ranking;
|
||||
}
|
||||
|
||||
public bool TryGetValueByKey(long key, out TValue value)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
value = node.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetNodeByKey(long key, out SkipTableNode<TValue> node)
|
||||
{
|
||||
if (Node.TryGetValue(key, out node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public bool Remove(long key)
|
||||
{
|
||||
if (!Node.TryGetValue(key, out var node))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Remove(node.SortKey, node.ViceKey, key, out _);
|
||||
}
|
||||
|
||||
public abstract void Add(long sortKey, long viceKey, long key, TValue value);
|
||||
public abstract bool Remove(long sortKey, long viceKey, long key, out TValue value);
|
||||
|
||||
public IEnumerator<SkipTableNode<TValue>> GetEnumerator()
|
||||
{
|
||||
var cur = BottomHeader.Right;
|
||||
while (cur != null)
|
||||
{
|
||||
yield return cur;
|
||||
cur = cur.Right;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3dacacc147f7c8499e328284a0542ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,166 @@
|
||||
#pragma warning disable CS8602
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8625
|
||||
#pragma warning disable CS8604
|
||||
#pragma warning disable CS8600
|
||||
namespace TEngine.DataStructure
|
||||
{
|
||||
/// <summary>
|
||||
/// 跳表降序版
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
public class SkipTableDesc<TValue> : SkipTableBase<TValue>
|
||||
{
|
||||
public SkipTableDesc(int maxLayer = 8) : base(maxLayer) { }
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dd291e3d391b8842a15ea93f72e4771
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
namespace TEngine.DataStructure
|
||||
{
|
||||
public class SkipTableNode<TValue>
|
||||
{
|
||||
public int Index;
|
||||
public long Key;
|
||||
public long SortKey;
|
||||
public long ViceKey;
|
||||
public TValue Value;
|
||||
public SkipTableNode<TValue> Left;
|
||||
public SkipTableNode<TValue> Right;
|
||||
public SkipTableNode<TValue> Down;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dcae58948d93a74bb7234d2a88fee46
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user