IndieGame/client/Assets/Ether/Scripts/Module/DataStructure/MultiList.cs

221 lines
6.9 KiB
C#
Raw Normal View History

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>>();
public int Count
{
get { return allMultiListNode.Count; }
}
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;
}
}
}
}
}
}