跳跃表(C#代码)

AVL 树和红黑树在数据搜索和排序方面都是有效的数据结构,但是这两种数据结构都需要重新平衡操作来保持树的平衡,这就导致大量费用和复杂性。还有另外一种数据结构可以使用,它特别适用于查找。这种数据结构提供了树的功效且不需要担心重新平衡问题。这种数据结构叫做跳跃表。

跳跃表提供了一种基于树结构的可替换选择。大多数程序员发现它们更容易实现且效率和类树结构相当。如果
在处理一个完全或几乎有序的数据集合,那么跳跃表可能是比树更好的一种选择。

跳跃表的原理推荐一篇文章:https://blog.csdn.net/qpzkobe/article/details/80056807

代码实现:

public class SkipNode
{
    public int key;
    public Object value;
    public SkipNode[] link;
    public SkipNode(int level, int key, Object value)
    {
        this.key = key;
        this.value = value;
        link = new SkipNode[level];
    }
}

public class SkipList
{
    private int maxLevel;//存贮跳跃表所允许的最大层次数。
    private int level;//存储当前层次
    private SkipNode header;//提供进入跳跃表的起始节点
    private float probability;//存储当前链层的概率分布
    private const int NIL = Int32.MaxValue;//一个表示跳跃表末尾的特殊数值
    private const int PROB = 0.5F;//链层的概率分布

    public SkipList(long maxNodes)
    {
        this.SkipList2(PROB, (int)(Math.Ceiling(Math.Log(maxNodes) / Math.Log(1 / PROB) -     1)));
    }  

    private void SkipList2(float probable, int maxLevel)
    {
        this.probability = probable;
        this.maxLevel = maxLevel;
        level = 0;
        header = new SkipNode(maxLevel, 0, null);
        SkipNode nilElement = new SkipNode(maxLevel, NIL, null);
        for (int i = 0; i <= maxLevel - 1; i++)
        header.link[i] = nilElement;
    }

    private int GenRandomLevel()
    {
        int newLevel = 0;
        Random r = new Random();
        int ran = 0;
        while (newLevel < maxLevel)
        {
            ran = r.Next(1);
            if(ran < probability)
            {
                newLevel++;
            }
            else
            {
                break;
            }
        }
            
        return newLevel;
    }

    public void Insert(int key, Object value)
    {
        SkipNode[] update = new SkipNode[maxLevel];
        SkipNode cursor = header;
        for (int i = level; i >= level; i--)//从当前最高层到最底层
        {
            while (cursor.link[i].key < key)
                cursor = cursor.link[i];
            update[i] = cursor;//用update[i]来接收每一层需要指向新节点的节点
        }

        cursor = cursor.link[0];
        if (cursor.key == key)//如果存在,那就覆盖
            cursor.value = value;
        else
        {
            int newLevel = GenRandomLevel();
            if (newLevel > level)//如果随机出来的链层比当前链层高的情况
            {
                for (int i = level + 1; i <= newLevel - 1; i++)
                    update[i] = header;
                level = newLevel;
            }

            cursor = new SkipNode(newLevel, key, value);// 插入
            for (int i = 0; i <= newLevel - 1; i++)//插入后改变自己的链指向的节点,和前面节点的链指向的节点变成自己
            {
                cursor.link[i] = update[i].link[i];
                update[i].link[i] = cursor;
            }
        }
    }

    /*如同 Insert 方法一样,这个方法也分为两个部分。第一部分就是第一个 for 循环突显出来的内容, 
     *它会找到表
     *中要删除的数据项。第二部分是 if 语句突出表示的内容,它会调整删除的 SkipNode 周围的链并且重 
     *新调整层次。
     */
    public void Delete(int key)
    {
        SkipNode[] update = new SkipNode[maxLevel + 1];
        SkipNode cursor = header;
        for (int i = level; i >= level; i--)
        {
            while (cursor.link[i].key < key)
                cursor = cursor.link[i];
            update[i] = cursor;
        }
        cursor = cursor.link[0];
        if (cursor.key == key)
        {
            for (int i = 0; i < level - 1; i++)
            {
                if (update[i].link[i] == cursor)
                    update[i].link[i] = cursor.link[i];
                while ((level > 0) && (header.link[level].key == NIL))
                    level--;
            }          
        }
    }

    /*现在准备来讨论 Search 方法了。这个方法首先从最高层开始,接着是其他链直到找到一个关键字的数    
    *值大于要
    *查找的关键字为止。然后,方法会降到下一个最低层继续查找,直到找到一个较高的关键字为止。随后再        
    *次降低层
    *次并且继续查找。这个方法最终会停止在第 0 层,远离问题中数据项的一个正确的节点
    */
    public Object Search(int key)
    {
        SkipNode cursor = header;
        for (int i = level; i > 0<= level - 1; i--)
        {
            SkipNode nextElement = cursor.link[i];
            while (nextElement.key < key)
            {
                cursor = nextElement;
                nextElement = cursor.link[i];
            }
        }
        cursor = cursor.link[0];
        if (cursor.key == key)
            return cursor.value;
        else
            return "Object not found";
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值