您的位置:首页 > 其它

漫画算法:什么是跳跃表?

2017-09-01 10:27 483 查看


漫画算法:什么是跳跃表?

// Copyright (C) 2017
// 版权所有。
//
// 文件名:SkipList
// 文件功能描述: 跳跃表的实现 增删查改
// 创建者:zhaoguanghui
// 时间:2017/9/1
// 版本:V1.0.0
//----------------------------------------------------------------*/

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 跳跃表
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class SkipList<TKey, TValue> : IDictionary<TKey, TValue> where TKey : IComparable
{
private SkipListNode<TKey, TValue> head;
private int count;

public int Count { get { return count; } }

public bool IsReadOnly { get { return false; } }

public TValue this[TKey key]
{
get
{
return Get(key);
}
set
{
Add(key, value);
}
}

public ICollection<TKey> Keys
{
get
{
List<TKey> keys = new List<TKey>(count);
WalkEntries(n => keys.Add(n.key));
return keys;
}
}

public ICollection<TValue> Values
{
get
{
List<TValue> values = new List<TValue>(count);
WalkEntries(n => values.Add(n.value));
return values;
}
}

private struct SkipListKVPair<W, X>
{
private W key;

public W Key
{
get { return key; }
}

public X Value;

public SkipListKVPair(W key, X value)
{
this.key = key;
this.Value = value;
}
}

private class SkipListNode<TNKey, TNValue>
{
public SkipListNode<TNKey, TNValue> forward, back, up, down;
public SkipListKVPair<TNKey, TNValue> keyValue;
public bool isFront = false;

public TNKey key
{
get { return keyValue.Key; }
}

public TNValue value
{
get { return keyValue.Value; }
set { keyValue.Value = value; }
}

public SkipListNode()
{
this.keyValue = new SkipListKVPair<TNKey, TNValue>(default(TNKey), default(TNValue));
this.isFront = true;
}

public SkipListNode(SkipListKVPair<TNKey, TNValue> keyValue)
{
this.keyValue = keyValue;
}

public SkipListNode(TNKey key, TNValue value)
{
this.keyValue = new SkipListKVPair<TNKey, TNValue>(key, value);
}
}

public SkipList()
{
this.head = new SkipListNode<TKey, TValue>();
count = 0;
}

public void Add(TKey key, TValue value)
{
SkipListNode<TKey, TValue> position;
bool found = Search(key, out position);
if (found)
position.value = value;
else
{
SkipListNode<TKey, TValue> newEntry = new SkipListNode<TKey, TValue>((TKey)key, value);
count++;

//类似双链表
newEntry.back = position;
if (position.forward != null)
{
newEntry.forward = position.forward;
position.forward.back = newEntry;
}
position.forward = newEntry;

Promote(newEntry);
}
}

public void Add(KeyValuePair<TKey, TValue> keyValue)
{
Add(keyValue.Key, keyValue.Value);
}

public void Clear()
{
head = new SkipListNode<TKey, TValue>();
count = 0;
}

public bool ContainsKey(TKey key)
{
SkipListNode<TKey, TValue> notused;
return Search(key, out notused);
}

public bool Contains(KeyValuePair<TKey, TValue> keyValue)
{
return ContainsKey(keyValue.Key);
}

public bool Remove(TKey key)
{
SkipListNode<TKey, TValue> position;
bool found = Search(key, out position);
if (!found)
return false;
else
{
SkipListNode<TKey, TValue> old = position;
do
{
old.back.forward = old.forward;
if (old.forward != null)
old.forward.back = old.back;
old = old.up;
} while (old != null);
count--;
while (head.forward == null)
{
head = head.down;
}
return true;
}
}

public bool Remove(KeyValuePair<TKey, TValue> keyValue)
{
return Remove(keyValue.Key);
}

public bool TryGetValue(TKey key, out TValue value)
{
try
{
value = Get(key);
return true;
}
catch (KeyNotFoundException)
{
value = default(TValue);
return false;
}
}

public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
{
if (array == null)
throw new ArgumentNullException("array");
if (index < 0)
throw new ArgumentOutOfRangeException("index");
if (array.IsReadOnly)
throw new ArgumentException("The array argument is Read Only and new items cannot be added to it.");
if (array.IsFixedSize && array.Length < count + index)
throw new ArgumentException("The array argument does not have sufficient space for the SkipList entries.");

int i = index;
WalkEntries(n => array[i++] = new KeyValuePair<TKey, TValue>(n.key, n.value));
}

public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
SkipListNode<TKey, TValue> position = head;
while (position.down != null)
position = position.down;
while (position.forward != null)
{
position = position.forward;
yield return new KeyValuePair<TKey, TValue>(position.key, position.value);
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}

private TValue Get(TKey key)
{
SkipListNode<TKey, TValue> position;
bool found = Search(key, out position);
if (!found)
throw new KeyNotFoundException("Unable to find entry with key \"" + key.ToString() + "\"");
return position.value;
}

private void WalkEntries(Action<SkipListNode<TKey, TValue>> lambda)
{
SkipListNode<TKey, TValue> node = head;
while (node.down != null)
node = node.down;
while (node.forward != null)
{
node = node.forward;
lambda(node);
}
}

private bool Search(TKey key, out SkipListNode<TKey, TValue> position)
{
if (key == null)
throw new ArgumentNullException("key");

SkipListNode<TKey, TValue> current;
position = current = head;
int num = 0;
while ((current.isFront || key.CompareTo(current.key) >= 0) && (current.forward != null || current.down != null))
{
position = current;
if (key.CompareTo(current.key) == 0)
return true;

if (current.forward == null || key.CompareTo(current.forward.key) < 0)
{
if (current.down == null)
return false;
else
current = current.down;
}
else
{
current = current.forward;
}

num++;
}
Debug.Log(num);
position = current;

if (key.CompareTo(position.key) == 0)
return true;
else
return false;
}

private void Promote(SkipListNode<TKey, TValue> node)
{
SkipListNode<TKey, TValue> back = node.back;
SkipListNode<TKey, TValue> last = node;

for (int levels = this.Levels(); levels > 0; levels--)
{
while (back.up == null && !back.isFront)
{
back = back.back;
}

if (back.isFront && back.up == null)
{
back.up = new SkipListNode<TKey, TValue>();
head = back.up;
}

back = back.up;

SkipListNode<TKey, TValue> newNode = new SkipListNode<TKey, TValue>(node.keyValue);
//前
newNode.forward = back.forward;
if (newNode.forward != null)
{
newNode.forward.back = newNode;
}
//后
newNode.back = back;
back.forward = newNode;
//下
newNode.down = last;
last.up = newNode;

last = newNode;
}
}

private int Levels()
{
int levels = 0;
while (UnityEngine.Random.Range(0, 1f) < 0.5)
levels++;
return levels;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法