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

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


// 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;
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值