成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Python 列表(List)的底層實現原理分析

瀏覽:5日期:2022-06-25 16:42:43
Python 列表的數據結構是怎么樣的?

列表實際上采用的就是數據結構中的順序表,而且是一種采用分離式技術實現的動態順序表

但這是不是Python的列表?

我的結論是順序表是列表的一種實現方式。

書上說的是:列表實現可以是數組和鏈表。

順序表是怎么回事?順序表一般是數組。

列表是一個線性的集合,它允許用戶在任何位置插入、刪除、訪問和替換元素。

列表實現是基于數組或基于鏈表結構的。當使用列表迭代器的時候,雙鏈表結構比單鏈表結構更快。

有序的列表是元素總是按照升序或者降序排列的元素。

實現細節

python中的列表的英文名是list,因此很容易和其它語言(C++, Java等)標準庫中常見的鏈表混淆。事實上CPython的列表根本不是列表(可能換成英文理解起來容易些:python中的list不是list)。在CPython中,列表被實現為長度可變的數組。

可參考《Python高級編程(第2版)》

從細節上看,Python中的列表是由對其它對象的引用組成的連續數組。指向這個數組的指針及其長度被保存在一個列表頭結構中。

這意味著,每次添加或刪除一個元素時,由引用組成的數組需要該標大小(重新分配)。

幸運的是,Python在創建這些數組時采用了指數分配,所以并不是每次操作都需要改變數組的大小。但是,也因為這個原因添加或取出元素的平攤復雜度較低。

不幸的是,在普通鏈表上“代價很小”的其它一些操作在Python中計算復雜度相對過高。

利用 list.insert(i,item) 方法在任意位置插入一個元素——復雜度O(N)

利用 list.pop(i) 或 list.remove(value) 刪除一個元素——復雜度O(N)

列表的算法效率

可以采用時間復雜度來衡量:

index() O(1)

append O(1)

pop() O(1)

pop(i) O(n)

insert(i,item) O(n)

del operator O(n)

iteration O(n)

contains(in) O(n)

get slice[x:y] O(k)

del slice O(n)

set slice O(n+k)

reverse O(n)

concatenate O(k)

sort O(nlogn)

multiply O(nk)

O括號里面的值越大代表效率越低

列表和元組

列表和元組的區別是顯然的:

列表是動態的,其大小可以該標 (重新分配);

而元組是不可變的,一旦創建就不能修改。

list和tuple在c實現上是很相似的,對于元素數量大的時候,

都是一個數組指針,指針指向相應的對象,找不到tuple比list快的理由。

但對于小對象來說,tuple會有一個對象池,所以小的、重復的使用tuple還有益處的。

為什么要有tuple,還有很多的合理性。

實際情況中的確也有不少大小固定的列表結構,例如二維地理坐標等;

另外tuple也給元素天然地賦予了只讀屬性。

認為tuple比list快的人大概是把python的tuple和list類比成C++中的數組和列表了。

補充:python list, tuple, dictionary, set的底層細節

list, tuple, dictionary, set是python中4中常見的集合類型。在筆者之前的學習中,只是簡單了學習它們4者的使用,現記錄一下更深底層的知識。

列表和元組

列表和元組的區別是顯然的:列表是動態的,其大小可以該標;而元組是不可變的,一旦創建就不能修改。

實現細節

python中的列表的英文名是list,因此很容易和其它語言(C++, Java等)標準庫中常見的鏈表混淆。事實上CPython的列表根本不是列表(可能換成英文理解起來容易些:python中的list不是list)。在CPython中,列表被實現為長度可變的數組。

從細節上看,Python中的列表是由對其它對象的引用組成的連續數組。指向這個數組的指針及其長度被保存在一個列表頭結構中。這意味著,每次添加或刪除一個元素時,由引用組成的數組需要該標大小(重新分配)。幸運的是,Python在創建這些數組時采用了指數過分配,所以并不是每次操作都需要改變數組的大小。但是,也因為這個原因添加或取出元素的平攤復雜度較低。

不幸的是,在普通鏈表上“代價很小”的其它一些操作在Python中計算復雜度相對過高。

利用 list.insert方法在任意位置插入一個元素——復雜度O(N)

利用 list.delete或del刪除一個元素——復雜度O(N)

操作 復雜度 復制 O(N) 添加元素(在尾部添加) O(1) 插入元素(在指定位置插入) O(N) 獲取元素 O(1) 修改元素 O(1) 刪除元素 O(N) 遍歷 O(N) 獲取長度為k的切片 O(k) 刪除切片 O(N) 列表擴展 O(k) 測試是否在列表中 O(N) min()/max() O(n) 獲取列表長度 O(1) 列表推導

要習慣用列表推導,因為這更加高效和簡短,涉及的語法元素少。在大型的程序中,這意味著更少的錯誤,代碼也更容易閱讀。

>>>[i for i in range(10) if i % 2 == 0] [0, 2, 4, 6, 8]其它習語

1.使用enumerate.在循環使用序列時,這個內置函數可以方便的獲取其索引:

for i, element in enumerate([’one’, ’two’, ’three’]): print(i, element)

result:

0 one1 two2 three

2.如果需要一個一個合并多個列表中的元素,可以使用zip()。對兩個大小相等的可迭代對象進行均勻遍歷時,這是一個非常常用的模式:

for item in zip([1, 2, 3], [4, 5, 6]): print(item)

(1, 4)(2, 5)(3, 6)

3.序列解包

#帶星號的表達式可以獲取序列的剩余部分>>>first, second, *reset = 0, 1, 2, 3>>>first0>>>second1>>>reset[2, 3]字典

字典是python中最通用的數據結構之一。dict可以將一組唯一的鍵映射到相應的值。

我們也可以用前面列表推導的方式來創建一個字典。

squares = {number: number**2 for number in range(10)}print(squares)

result:

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

在遍歷字典元素時,有一點需要特別注意。字典里的keys(), values()和items()3個方法的返回值不再是列表,而是視圖對象(view objects)。

keys(): 返回dict_keys對象,可以查看字典所有鍵

values():返回dict_values對象,可以查看字典的所有值

items():返回dict_items對象,可以查看字典所有的{key, value}二元元組。

視圖對象可以動態查看字典的內容,因此每次字典發生變化的時候,視圖都會相應的改變,見下面這個例子:

words = {’foo’: ’bar’, ’fizz’: ’bazz’}items= words.items()words[’spam’] = ’eggs’print(items)

result:

dict_items([(’foo’, ’bar’), (’fizz’, ’bazz’), (’spam’, ’eggs’)])

視圖無需冗余的將所有值都保存在內存中,像列表那樣。但你仍然可以獲取其長度(使用len),也可以測試元素是否包含在其中(使用in子句)。當然,視圖是迭代的。

實現細節

CPython使用偽隨機探測(pseudo-random probing)的散列表(hash table)作為字典的底層數據結構。由于這個實現細節,只有可哈希的對象才能作為字典的鍵。

Python中所有不可變的內置類型都是可哈希的。可變類型(如列表,字典和集合)就是不可哈希的,因此不能作為字典的鍵。

字典的三個基本操作(添加元素,獲取元素和刪除元素)的平均事件復雜度為O(1),但是他們的平攤最壞情況復雜度要高得多,為O(N).

操作 平均復雜度 平攤最壞情況復雜度 獲取元素 O(1) O(n) 修改元素 O(1) O(n) 刪除元素 O(1) O(n) 復制 O(n) O(n) 遍歷 O(n) O(n)

還有一點很重要,在復制和遍歷字典的操作中,最壞的復雜度中的n是字典曾經達到的最大元素數目,而不是當前的元素數目。換句話說,如果一個字典曾經元素個數很多,后來又大大減小了,那么遍歷這個字典可能會花費相當長的事件。

因此在某些情況下,如果需要頻繁的遍歷某個詞典,那么最好創建一個新的字典對象,而不是僅在舊字典中刪除元素。

字典的缺點和替代方案

使用字典的常見陷阱就是,它并不會按照鍵的添加順序來保存元素的順序。在某些情況下,字典的鍵是連續的,對應的散列值也是連續值(例如整數),那么由于字典的內部實現,元素的實現可能和添加的順序相同:

keys = {num: None for num in range(5)}.keys()print(keys)

result:

dict_keys([0, 1, 2, 3, 4])

但是,如果散列方法不同的其它數據類型,那么字典就不會保存元素順序。

age = {str(i): i for i in range(100)}keys = age.keys()print(keys)

result:

dict_keys([’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’, ’8’, ’9’, ’10’, ’11’, ’12’, ’13’, ’14’, ’15’, ’16’, ’17’, ’18’, ’19’, ’20’, ’21’, ’22’, ’23’, ’24’, ’25’, ’26’, ’27’, ’28’, ’29’, ’30’, ’31’, ’32’, ’33’, ’34’, ’35’, ’36’, ’37’, ’38’, ’39’, ’40’, ’41’, ’42’, ’43’, ’44’, ’45’, ’46’, ’47’, ’48’, ’49’, ’50’, ’51’, ’52’, ’53’, ’54’, ’55’, ’56’, ’57’, ’58’, ’59’, ’60’, ’61’, ’62’, ’63’, ’64’, ’65’, ’66’, ’67’, ’68’, ’69’, ’70’, ’71’, ’72’, ’73’, ’74’, ’75’, ’76’, ’77’, ’78’, ’79’, ’80’, ’81’, ’82’, ’83’, ’84’, ’85’, ’86’, ’87’, ’88’, ’89’, ’90’, ’91’, ’92’, ’93’, ’94’, ’95’, ’96’, ’97’, ’98’, ’99’])

理論上,鍵的順序不應該是這樣的,應該是亂序。。。具體為什么這樣,等以后明白了再補充

如果我們需要保存添加順序怎么辦?python 標準庫的collections模塊提供了名為OrderedDicr的有序字典。

集合

集合是一種魯棒性很好的數據結構,當元素順序的重要性不如元素的唯一性和測試元素是否包含在集合中的效率時,大部分情況下這種數據結構極其有用。

python的內置集合類型有兩種:

set(): 一種可變的、無序的、有限的集合,其元素是唯一的、不可變的(可哈希的)對象。

frozenset(): 一種不可變的、可哈希的、無序的集合,其元素是唯一的,不可變的哈希對象。

set([set([1, 2, 3]), set([2, 3, 4])])

result:

Traceback (most recent call last): File '/pycharm_project/LearnPython/Part1/demo.py', line 1, in <module> set([set([1, 2, 3]), set([2, 3, 4])])TypeError: unhashable type: ’set’

set([frozenset([1, 2, 3]), frozenset([2, 3, 4])])

result:不會報錯

set里的元素必須是唯一的,不可變的。但是set是可變的,所以set作為set的元素會報錯。

實現細節

CPython中集合和字典非常相似。事實上,集合被實現為帶有空值的字典,只有鍵才是實際的集合元素。此外,集合還利用這種沒有值的映射做了其它的優化。

由于這一點,可以快速的向集合中添加元素、刪除元素、檢查元素是否存在。平均時間復雜度為O(1),最壞的事件復雜度是O(n)。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。如有錯誤或未考慮完全的地方,望不吝賜教。

標簽: Python 編程
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
在线观看亚洲一区| 农村妇女精品| 一区二区久久| 免费亚洲一区二区| 91精品国产综合久久小美女| 国产精品视频第一区| 日韩精品成人一区二区在线| 成年人午夜久久久| 色综合久久久久久久久久久| 一色桃子久久精品亚洲| 国产美女精品人人做人人爽| 亚洲精品1区| 久久亚洲综合色一区二区三区 | 免费高清在线一区| 精品亚洲porn| 亚洲一区二区三区四区中文| 欧美激情艳妇裸体舞| 国产精品综合一区二区三区| 91精品福利在线| 午夜精品久久久久久久蜜桃app| 最新日韩在线视频| 欧美日韩免费一区二区三区视频| 在线观看不卡视频| 色综合中文字幕国产| 国产日产精品一区二区三区四区的观看方式 | 亚洲欧美中日韩| 欧美精品一二三区| 国产成人免费在线| 欧美一区在线视频| 免费不卡在线观看| ●精品国产综合乱码久久久久| 欧美日韩亚洲一区| 正在播放一区二区| 新67194成人永久网站| 欧美一区网站| 成人激情免费电影网址| 久久国产精品免费| 欧美精品一二三| 亚洲欧美日韩另类精品一区二区三区| 亚洲欧洲国产日本综合| 欧美精品国产精品| 色八戒一区二区三区| 亚洲一区不卡| 国产精品毛片va一区二区三区| 日本韩国一区二区| 亚洲人人精品| 伊人成年综合电影网| 亚洲欧洲成人精品av97| 精品国产乱码久久久久久影片| 亚洲色图另类专区| 国精品一区二区| 亚洲午夜精品17c| 色丁香久综合在线久综合在线观看| 国产欧美一区二区色老头| 午夜在线视频一区二区区别| 日韩免费电影一区| 一区二区欧美在线观看| 成人免费看片app下载| 亚洲第一狼人社区| 一区二区三区精品国产| 成人激情视频网站| 国产成人aaa| 亚洲日本va午夜在线电影| 国产精品久久久久桃色tv| 中国成人亚色综合网站| 亚洲激情国产| 国产精品有限公司| 色婷婷久久久综合中文字幕 | 久久久久久久免费视频了| 91亚洲资源网| 久久亚洲捆绑美女| 国产精品日韩一区二区| 亚洲夂夂婷婷色拍ww47| 成人av网站在线观看| 欧美日韩国产一区| 免费成人在线观看| 狠狠色狠狠色综合日日91app| 欧美精品日本| 亚洲夂夂婷婷色拍ww47| 午夜精品视频在线观看| 国产又粗又猛又爽又黄91精品| 日本一区二区三区电影| av成人免费观看| 国产精品一区一区三区| 国产·精品毛片| 色综合色综合色综合色综合色综合| 亚洲综合成人在线| 午夜精品福利视频网站| 国产成人在线观看免费网站| 91天堂素人约啪| 国产乱码精品一区二区三区不卡| 99久久久精品免费观看国产蜜| 欧美三级视频在线观看| 6080日韩午夜伦伦午夜伦| 久久人人97超碰com| 亚洲一区二区在线视频| 奇米色一区二区| 国产91精品一区二区麻豆网站| 日本伊人色综合网| 国产精品欧美精品| 日产国产高清一区二区三区| av中文字幕在线不卡| 激情av综合网| 亚洲无吗在线| 91看片淫黄大片一级在线观看| 美女看a上一区| 国产精品不卡在线| 午夜视频在线观看一区| 国产一区二区伦理| 亚洲人妖在线| 欧美mv日韩mv国产网站| 欧美伊人久久久久久午夜久久久久| 日韩**一区毛片| 国产精品亚洲专一区二区三区 | 国产麻豆午夜三级精品| 国产一区视频观看| 日韩一级成人av| 欧美性受xxxx黑人xyx性爽| 久久久亚洲欧洲日产国码αv| 欧美老年两性高潮| 国产精品福利影院| 国产久卡久卡久卡久卡视频精品| 看片的网站亚洲| 国内精品**久久毛片app| 欧美午夜电影在线播放| 一区二区三区视频在线观看| 国产91丝袜在线观看| 在线一区日本视频| 国产喂奶挤奶一区二区三区| 欧美疯狂做受xxxx富婆| 亚洲欧美自拍偷拍色图| 国产91丝袜在线18| 欧美情侣在线播放| 青青草97国产精品免费观看 | 欧美成人官网二区| 日韩一区欧美二区| 国产视频一区在线观看一区免费| 免费在线观看成人av| 久久久亚洲精品一区二区三区 | 国产一区二区三区视频在线播放| 国产在线不卡一卡二卡三卡四卡| 免费视频一区| 国产精品视频福利| 欧美日本韩国一区二区三区| 欧美变态口味重另类| 国产一区美女| 97精品超碰一区二区三区| 欧美日一区二区在线观看| 国产精品推荐精品| 正在播放亚洲一区| 亚洲欧洲一区二区三区| 日产国产高清一区二区三区| 伊人色综合久久天天五月婷| 亚洲天堂中文字幕| 一本色道久久综合| 亚洲电影一级黄| 久色成人在线| 色天使色偷偷av一区二区| 午夜欧美2019年伦理| 久久午夜激情| 韩国精品主播一区二区在线观看 | 国产精品最新自拍| 一区二区亚洲| 56国语精品自产拍在线观看| 91久久久久| 国产成人av一区二区三区在线 | 91偷拍与自偷拍精品| 国内外成人在线视频| 久久综合激情| 久久国产日韩欧美精品| 欧美精品三级在线观看| 一区二区三区成人在线视频| 亚洲精品v日韩精品| 欧美先锋影音| 精品国产乱码久久久久久夜甘婷婷 | 中文字幕一区二| 久久综合九色综合久99| 99国产精品国产精品久久| 亚洲1区2区3区4区| 久久色成人在线| 日本大香伊一区二区三区| 91网页版在线| 秋霞影院一区二区| 国产精品久久久久久妇女6080| av成人激情| 国产成人综合亚洲91猫咪| 一区二区三区日韩精品| 精品盗摄一区二区三区| 久久激情久久| 国产精品美女久久久久久2018| 欧美喷水视频| 免费精品视频在线| 综合自拍亚洲综合图不卡区| 宅男在线国产精品| 国产精品一区在线播放| 欧美91视频| 国产福利视频一区二区三区| 亚洲精品乱码久久久久久日本蜜臀| 久久综合九色综合久99| 欧美日韩在线观看一区二区三区|