摘要:然而對(duì)于它為什么要這樣實(shí)現(xiàn)我還不是很清楚,留待以后繼續(xù)探究。這里是我在上關(guān)于這個(gè)問(wèn)題的提問(wèn)。
問(wèn)題
在看 collections.OrderedDict 的源碼時(shí),對(duì)于它如何構(gòu)造有序的結(jié)構(gòu)這一部分不是很理解,代碼如下:
class OrderedDict(dict): "Dictionary that remembers insertion order" # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. # Big-O running times for all methods are the same as regular dictionaries. # The internal self.__map dict maps keys to links in a doubly linked list. # The circular doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted (this simplifies the algorithm). # Each link is stored as a list of length three: [PREV, NEXT, KEY]. def __init__(*args, **kwds): """Initialize an ordered dictionary. The signature is the same as regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. """ if not args: raise TypeError("descriptor "__init__" of "OrderedDict" object " "needs an argument") self = args[0] args = args[1:] if len(args) > 1: raise TypeError("expected at most 1 arguments, got %d" % len(args)) try: self.__root except AttributeError: self.__root = root = [] # sentinel node root[:] = [root, root, None] self.__map = {} self.__update(*args, **kwds) def __setitem__(self, key, value, dict_setitem=dict.__setitem__): "od.__setitem__(i, y) <==> od[i]=y" # Setting a new item creates a new link at the end of the linked list, # and the inherited dictionary is updated with the new key/value pair. if key not in self: root = self.__root last = root[0] last[1] = root[0] = self.__map[key] = [last, root, key] return dict_setitem(self, key, value) def __delitem__(self, key, dict_delitem=dict.__delitem__): "od.__delitem__(y) <==> del od[y]" # Deleting an existing item uses self.__map to find the link which gets # removed by updating the links in the predecessor and successor nodes. dict_delitem(self, key) link_prev, link_next, _ = self.__map.pop(key) link_prev[1] = link_next # update link_prev[NEXT] link_next[0] = link_prev # update link_next[PREV] def __iter__(self): "od.__iter__() <==> iter(od)" # Traverse the linked list in order. root = self.__root curr = root[1] # start at the first node while curr is not root: yield curr[2] # yield the curr[KEY] curr = curr[1] # move to next node def __reversed__(self): "od.__reversed__() <==> reversed(od)" # Traverse the linked list in reverse order. root = self.__root curr = root[0] # start at the last node while curr is not root: yield curr[2] # yield the curr[KEY] curr = curr[0] # move to previous node def clear(self): "od.clear() -> None. Remove all items from od." root = self.__root root[:] = [root, root, None] self.__map.clear() dict.clear(self)
主要是對(duì)于初始化里和set方法里的做法不清楚, wtf doing here…:
self.__root = root = [] # sentinel node root[:] = [root, root, None] self.__map = {} # 和 root = self.__root last = root[0] last[1] = root[0] = self.__map[key] = [last, root, key]
后來(lái)在網(wǎng)上提問(wèn)并且自己查詢了相關(guān)資料后明白這是個(gè)帶哨兵的雙向鏈表的實(shí)現(xiàn),關(guān)于雙向鏈表的知識(shí)自己補(bǔ)了下,可以參見(jiàn)這里 和 這里。
然而對(duì)于它為什么要這樣實(shí)現(xiàn)我還不是很清楚,留待以后繼續(xù)探究。
這里 是我在v2ex上關(guān)于這個(gè)問(wèn)題的提問(wèn)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/44296.html
摘要:線程不安全底層數(shù)據(jù)結(jié)構(gòu)是鏈表。的默認(rèn)初始化容量是,每次擴(kuò)容時(shí)候增加原先容量的一半,也就是變?yōu)樵瓉?lái)的倍刪除元素時(shí)不會(huì)減少容量,若希望減少容量則調(diào)用它不是線程安全的。 前言 聲明,本文用得是jdk1.8 前一篇已經(jīng)講了Collection的總覽:Collection總覽,介紹了一些基礎(chǔ)知識(shí)。 現(xiàn)在這篇主要講List集合的三個(gè)子類: ArrayList 底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組。線程不安全 ...
摘要:線性結(jié)構(gòu)數(shù)組與鏈表線性結(jié)構(gòu)線性數(shù)據(jù)結(jié)構(gòu)有兩端,有時(shí)被稱為左右,某些情況被稱為前后。將兩個(gè)線性數(shù)據(jù)結(jié)構(gòu)區(qū)分開(kāi)的方法是添加和移除項(xiàng)的方式,特別是添加和移除項(xiàng)的位置。相對(duì)于數(shù)組,鏈表的好處在于,添加或移除元素的時(shí)候不需要移動(dòng)其他元素。 線性結(jié)構(gòu) 數(shù)組與鏈表 線性結(jié)構(gòu) 線性數(shù)據(jù)結(jié)構(gòu)有兩端,有時(shí)被稱為左右,某些情況被稱為前后。你也可以稱為頂部和底部,名字都不重要。將兩個(gè)線性數(shù)據(jù)結(jié)構(gòu)區(qū)分開(kāi)的方法...
摘要:線性結(jié)構(gòu)數(shù)組與鏈表線性結(jié)構(gòu)線性數(shù)據(jù)結(jié)構(gòu)有兩端,有時(shí)被稱為左右,某些情況被稱為前后。將兩個(gè)線性數(shù)據(jù)結(jié)構(gòu)區(qū)分開(kāi)的方法是添加和移除項(xiàng)的方式,特別是添加和移除項(xiàng)的位置。相對(duì)于數(shù)組,鏈表的好處在于,添加或移除元素的時(shí)候不需要移動(dòng)其他元素。 線性結(jié)構(gòu) 數(shù)組與鏈表 線性結(jié)構(gòu) 線性數(shù)據(jù)結(jié)構(gòu)有兩端,有時(shí)被稱為左右,某些情況被稱為前后。你也可以稱為頂部和底部,名字都不重要。將兩個(gè)線性數(shù)據(jù)結(jié)構(gòu)區(qū)分開(kāi)的方法...
摘要:習(xí)慣在微信看技術(shù)文章,想要獲取更多的資源的同學(xué),可以關(guān)注微信公眾號(hào)。為了大家方便,剛新建了一下群,大家也可以去交流交流。謝謝支持了希望能多介紹給其他有需要的朋友 前言 聲明,本文用得是jdk1.8 前面已經(jīng)講了Collection的總覽和剖析List集合以及散列表、Map集合、紅黑樹(shù)還有HashMap基礎(chǔ)了: Collection總覽 List集合就這么簡(jiǎn)單【源碼剖析】 Map集合、...
閱讀 3103·2021-11-15 11:39
閱讀 1669·2021-08-19 10:56
閱讀 1219·2019-08-30 14:12
閱讀 3878·2019-08-29 17:29
閱讀 847·2019-08-29 16:21
閱讀 3543·2019-08-26 12:22
閱讀 1637·2019-08-23 16:30
閱讀 1178·2019-08-23 15:25