亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python實現(xiàn)跳表SkipList的示例代碼

 更新時間:2021年07月25日 12:10:07   作者:von Libniz  
這篇文章主要介紹了python實現(xiàn)跳表SkipList的示例代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

跳表

跳表,又叫做跳躍表、跳躍列表,在有序鏈表的基礎(chǔ)上增加了“跳躍”的功能,由William Pugh于1990年發(fā)布,設(shè)計的初衷是為了取代平衡樹(比如紅黑樹)。
Redis、LevelDB 都是著名的 Key-Value 數(shù)據(jù)庫,而Redis中 的 SortedSet、LevelDB 中的 MemTable 都用到了跳表。
對比平衡樹,跳表的實現(xiàn)和維護會更加簡單,跳表的搜索、刪除、添加的平均時間復雜度是 O(logn)。
跳表的結(jié)構(gòu)如圖所示:

在這里插入圖片描述

可以發(fā)現(xiàn),對于一個節(jié)點Node,其含有多個next指針,不同索引的next分別代表不同層次的下一個節(jié)點,下次是節(jié)點類Node的python定義:

class Node():
     def __init__(self,key,value,level):
         '''
         :param level:每個node對應(yīng)的nexts層數(shù)不同
         '''
         self.key=key
         self.value=value
         self.nexts=[None]*level#節(jié)點類型next指針,初始值為空

     def __str__(self):
         #return "[key:"+str(self.key)+", value:"+str(self.value)+" len:"+str(len(self.nexts))+"]"
         return "["+str(self.key)+","+str(self.value)+","+str(len(self.nexts))+"]"

關(guān)于添加、刪除、查找見一下完整代碼:

'''
跳表 Skip List ,其初衷是為了替代紅黑樹
'''
import random

import mkl_random
import time

class SkipList():
    def __init__(self):
        #頭節(jié)點不存儲任何數(shù)據(jù)
        self.MAX_LEVEL = 32  # 最大level層數(shù)
        self.__first=SkipList.Node(None, None, self.MAX_LEVEL)#頭節(jié)點
        self.__level=0#實際的level層數(shù)
        self.__size=0#Jiedian個數(shù)
        self.__p=0.25#用于生成添加節(jié)點時的隨機level
        return

    class Node():
        def __init__(self,key,value,level):
            '''
            :param level:每個node對應(yīng)的nexts層數(shù)不同
            '''
            self.key=key
            self.value=value
            self.nexts=[None]*level

        def __str__(self):
            #return "[key:"+str(self.key)+", value:"+str(self.value)+" len:"+str(len(self.nexts))+"]"
            return "["+str(self.key)+","+str(self.value)+","+str(len(self.nexts))+"]"

    def get(self,key):
        '''
        :param key:
        :return: key對應(yīng)的value
        '''
        self.keyCheck(key)
        node=self.__first
        for level in range(self.__level - 1,-1,-1):
            #在該層查找,key大于節(jié)點的key向前查找
            while node.nexts[level] and node.nexts[level].key<key:
                node=node.nexts[level]
            if node.nexts[level] and node.nexts[level].key==key:#相等則找到,否則向下尋找
                return node.nexts[level].value
        return None

    def put(self,key,value):
        '''
        return:原來的value,原來不存在key則為空
        '''
        self.keyCheck(key)
        prev=[None]*self.__level
        node=self.__first
        for i in range(self.__level - 1, -1, -1):
            while node.nexts[i] and node.nexts[i].key<key:
                node=node.nexts[i]
            if node.nexts[i] and node.nexts[i].key==key:
                oldValue=node.nexts[i].value
                node.nexts[i].value=value
                return oldValue
            prev[i]=node#保存當前l(fā)evel小于key的node

        newLevel=self.randomLevel()
        newNode=SkipList.Node(key,value,newLevel)
        for i in range(newLevel):
            if i<self.__level:
                newNode.nexts[i]=prev[i].nexts[i]
                prev[i].nexts[i]=newNode
            else:
                self.__first.nexts[i]=newNode
        self.__size+=1
        self.__level=max(self.__level, newLevel)
        return None

    def remove(self,key):
        '''
        :return: 節(jié)點對應(yīng)的value值,不存在則返回None
        '''
        self.keyCheck(key)
        prev=[None]*self.__level
        node=self.__first
        flag=False#該節(jié)點是否被查找到
        for i in range(self.__level - 1, -1, -1):
            while node.nexts[i] and node.nexts[i].key<key:
                node=node.nexts[i]
            if node.nexts[i].key==key:
                flag=True
            prev[i]=node
        if not flag:
            return None
        removedNode=node.nexts[0]#需要被刪除的節(jié)點
        for i in range(len(removedNode.nexts)):#該nexts一定小于等于prev的長度
            prev[i].next[i]=removedNode.nexts[i]
        self.__size-=1
        newLevel=self.__level
        while newLevel>0 and not self.__first.nexts[newLevel - 1]:
            newLevel-=1
        self.__level=newLevel
        return removedNode.value

    def keyCheck(self, key):
        '''
        限制傳入key不能為空
        '''
        if key!=0 and not key:
            raise AttributeError("key can not be None")

    def size(self):
        return self.__size

    def isEmpty(self):
        return self.__size == 0

    def randomLevel(self):#生成一個隨機的層數(shù)
        level=1
        while mkl_random.rand()<self.__p and level<self.MAX_LEVEL:
            level+=1
        return level

    def __str__(self):
        result=""
        for i in range(self.__level - 1, -1, -1):
            result+=str(i)
            node = self.__first
            while node.nexts[i]:
                result+=str(node.nexts[i])
                node=node.nexts[i]
            result+='\n'
        print("level:"+str(self.__level))
        return result

    def showFirst(self):
        for item in self.__first.nexts:
            print(item,end=' ')
        print()

def timeCalculate(container, size:int):
    begin=time.time()
    for i in range(size):
        if isinstance(container,dict):
            container[i]= i * 3
        else:
            container.put(i, i * 3)
    error_count = 0
    for i in range(size):
        if container.get(i) != i * 3:
            #print("wrong " + str(i) + ":" + str(skipList.get(i)))
            error_count+=1
    end=time.time()
    print(type(container))
    print(f'error rate:{float(error_count) / size:0.5f}')
    print(f'time cost:{float(end-begin)*1000:0.3f} ms')


if __name__=='__main__':
    timeCalculate({},1000000)
    timeCalculate(SkipList(),10000)

到此這篇關(guān)于python實現(xiàn)跳表SkipList的文章就介紹到這了,更多相關(guān)python 跳表SkipList內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python utc datetime轉(zhuǎn)換為時間戳的方法

    python utc datetime轉(zhuǎn)換為時間戳的方法

    今天小編就為大家分享一篇python utc datetime轉(zhuǎn)換為時間戳的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python matplotlib庫的基本使用

    python matplotlib庫的基本使用

    這篇文章主要介紹了python matplotlib庫的基本使用,幫助大家繪制圖表,進行數(shù)據(jù)可視化分析,感興趣的朋友可以了解下
    2020-09-09
  • python實現(xiàn)五子棋人機對戰(zhàn)游戲

    python實現(xiàn)五子棋人機對戰(zhàn)游戲

    這篇文章主要為大家詳細介紹了python實現(xiàn)五子棋之人機對戰(zhàn)游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Python入門篇之函數(shù)

    Python入門篇之函數(shù)

    本篇文章將介紹如何將語句組織成函數(shù),以及參數(shù)概念以及在程序中的用途,需要的朋友可以參考下
    2014-10-10
  • Python圖像運算之圖像點運算與灰度化處理詳解

    Python圖像運算之圖像點運算與灰度化處理詳解

    這篇文章主要介紹了圖像點運算的灰度化處理的相關(guān)知識,包括各種灰度算法的實現(xiàn),以及灰度線性變換和灰度非線性變換。需要的可以參考一下
    2022-02-02
  • python用字典統(tǒng)計單詞或漢字詞個數(shù)示例

    python用字典統(tǒng)計單詞或漢字詞個數(shù)示例

    這篇文章主要介紹了python用字典統(tǒng)計單詞或漢字詞個數(shù)示例,需要的朋友可以參考下
    2014-04-04
  • python使用NumPy文件的讀寫操作

    python使用NumPy文件的讀寫操作

    這篇文章主要介紹了python使用NumPy讀寫文本文件。想了解第三方庫文件操作的同學,來看一下吧
    2021-04-04
  • python中使用多線程改進flask案例

    python中使用多線程改進flask案例

    這篇文章主要介紹了使用多線程改進flask案例,線程是指進程內(nèi)的一個執(zhí)行單元,也是進程內(nèi)的可調(diào)度實體.線程的劃分尺度小于進程,使得多線程程序的并發(fā)性高,更多具體內(nèi)容,需要的小伙伴可以參考下面文章相關(guān)資料,希望對你有所幫助
    2022-03-03
  • Python文檔生成工具pydoc使用介紹

    Python文檔生成工具pydoc使用介紹

    這篇文章主要介紹了Python文檔生成工具pydoc使用介紹,本文講解了基本用法、獲取幫助的方法、生成的文檔效果圖等內(nèi)容,需要的朋友可以參考下
    2015-06-06
  • Python判斷字符串是否為字母或者數(shù)字(浮點數(shù))的多種方法

    Python判斷字符串是否為字母或者數(shù)字(浮點數(shù))的多種方法

    本文給大家?guī)砣N方法基于Python判斷字符串是否為字母或者數(shù)字(浮點數(shù)),非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08

最新評論