2024-10-11 10:12:15 +08:00
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace Ether
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 多重链表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="Key"></typeparam>
|
|
|
|
|
/// <typeparam name="Value"></typeparam>
|
|
|
|
|
[Serializable]
|
|
|
|
|
public class MultiList<Key, Value>
|
|
|
|
|
{
|
|
|
|
|
public Dictionary<Key, MultListNode<Key, Value>> allMultiListNode = new Dictionary<Key, MultListNode<Key, Value>>();
|
|
|
|
|
|
2024-11-04 18:43:40 +08:00
|
|
|
|
public int Count => allMultiListNode.Count;
|
2024-10-11 10:12:15 +08:00
|
|
|
|
|
|
|
|
|
public Dictionary<Key, MultListNode<Key, Value>> Root { get; private set; } = new Dictionary<Key, MultListNode<Key, Value>>();
|
|
|
|
|
|
|
|
|
|
private Dictionary<Key, List<MultListNode<Key, Value>>> disperseNode = new Dictionary<Key, List<MultListNode<Key, Value>>>(); //用于存储子节点先加入父节点没有加入的情况,没法连上的节点先塞到这个列表里
|
|
|
|
|
|
|
|
|
|
public bool AddNode(Key key, Value data, params Key[] parentKeys)
|
|
|
|
|
{
|
|
|
|
|
MultListNode<Key, Value> node;
|
|
|
|
|
if (parentKeys.Length == 0)
|
|
|
|
|
{
|
|
|
|
|
node = new MultListNode<Key, Value>()
|
|
|
|
|
{
|
|
|
|
|
Id = key,
|
|
|
|
|
Data = data,
|
|
|
|
|
IsRoot = true,
|
|
|
|
|
multiList = this,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Root.Add(key, node);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (allMultiListNode.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"多重链表重复添加同一数据,请检查数据!Key:{key}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node = new MultListNode<Key, Value>()
|
|
|
|
|
{
|
|
|
|
|
Id = key,
|
|
|
|
|
Data = data,
|
|
|
|
|
multiList = this,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var parentKey in parentKeys)
|
|
|
|
|
{
|
|
|
|
|
node.parentList.Add(parentKey);
|
|
|
|
|
if (!allMultiListNode.TryGetValue(parentKey, out var parentNode))
|
|
|
|
|
{
|
|
|
|
|
//Debug.LogError($"多重链表重复父节点失败,没有该父节点,请检查数据!当前节点Key:{key},父节点Key:{parentKey}");
|
|
|
|
|
if (!disperseNode.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
disperseNode.Add(key, new List<MultListNode<Key, Value>>());
|
|
|
|
|
}
|
|
|
|
|
disperseNode[key].Add(node);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
parentNode.childList.Add(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//接上之前没有父节点的离散节点
|
|
|
|
|
if (disperseNode.TryGetValue(key, out var disperseNodeList))
|
|
|
|
|
{
|
|
|
|
|
for (int i = disperseNodeList.Count - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
if (!node.childList.Contains(key))
|
|
|
|
|
{
|
|
|
|
|
node.childList.Add(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isNodeConnected = true;
|
|
|
|
|
foreach (var parentKey in node.parentList)
|
|
|
|
|
{
|
|
|
|
|
if (!allMultiListNode.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
isNodeConnected = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isNodeConnected)
|
|
|
|
|
{
|
|
|
|
|
disperseNodeList.RemoveAt(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
allMultiListNode.Add(key, node);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 删除节点,删除时注意,如果该节点下有唯一父节点是该节点那么会删除后面所有对应的子节点
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="key"></param>
|
|
|
|
|
public bool RemoveNode(Key key)
|
|
|
|
|
{
|
|
|
|
|
if (!allMultiListNode.TryGetValue(key, out var curNode))
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"多重链表删除数据失败,不存在当前节点!Key:{key}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var childNodeKey in curNode.childList)
|
|
|
|
|
{
|
|
|
|
|
if (allMultiListNode.TryGetValue(childNodeKey, out var childNode))
|
|
|
|
|
{
|
|
|
|
|
if (childNode.parentList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
childNode.parentList.Remove(childNodeKey);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (childNode.parentList.Contains(key))
|
|
|
|
|
{
|
|
|
|
|
RemoveNode(childNodeKey); //递归遍历子节点删除
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var parentNodeKey in curNode.parentList)
|
|
|
|
|
{
|
|
|
|
|
if (allMultiListNode.TryGetValue(parentNodeKey, out var parentNode))
|
|
|
|
|
{
|
|
|
|
|
if (parentNode.childList.Contains(key))
|
|
|
|
|
{
|
|
|
|
|
parentNode.childList.Remove(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
allMultiListNode.Remove(key);
|
|
|
|
|
if (curNode.IsRoot)
|
|
|
|
|
{
|
|
|
|
|
Root.Remove(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MultListNode<Key, Value> GetNode(Key key)
|
|
|
|
|
{
|
|
|
|
|
if (allMultiListNode.ContainsKey(key))
|
|
|
|
|
{
|
|
|
|
|
return allMultiListNode[key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MultListNode<Key, Value> this[Key key] => GetNode(key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public IEnumerator<MultListNode<Key, Value>> GetEnumerator()
|
|
|
|
|
{
|
|
|
|
|
foreach (var rootNodePair in Root)
|
|
|
|
|
{
|
|
|
|
|
yield return rootNodePair.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
|
|
|
|
allMultiListNode.Clear();
|
|
|
|
|
Root.Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 多重链表节点
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="Key"></typeparam>
|
|
|
|
|
/// <typeparam name="Value"></typeparam>
|
|
|
|
|
[Serializable]
|
|
|
|
|
public class MultListNode<Key, Value>
|
|
|
|
|
{
|
|
|
|
|
public Key Id; //唯一key值
|
|
|
|
|
public Value Data; //节点数据
|
|
|
|
|
public bool IsRoot; //是否是根节点,如果不是根节点父节点不能为空
|
|
|
|
|
public List<Key> parentList = new List<Key>(); //多个父节点
|
|
|
|
|
public List<Key> childList = new List<Key>(); //多个子节点
|
|
|
|
|
[NonSerialized]
|
|
|
|
|
public MultiList<Key, Value> multiList;
|
|
|
|
|
|
|
|
|
|
public IEnumerator<MultListNode<Key, Value>> GetEnumerator()
|
|
|
|
|
{
|
|
|
|
|
if (multiList == null)
|
|
|
|
|
{
|
|
|
|
|
yield return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var childKey in childList)
|
|
|
|
|
{
|
|
|
|
|
var childNode = multiList[childKey];
|
|
|
|
|
if (childNode != null)
|
|
|
|
|
{
|
|
|
|
|
yield return multiList[childKey];
|
|
|
|
|
foreach (var node in childNode)
|
|
|
|
|
{
|
|
|
|
|
yield return node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|