您的位置:首页 > 理论基础 > 数据结构算法

python数据结构

2017-08-21 09:53 148 查看
本文译自https://docs.python.org/2.7/tutorial/。完全是出于个人兴趣翻译的,请勿追究责任。另外,谢绝商业牟利。刊印请与本人和原作者联系,无授权不得刊印,违者必究其责任。如需转发,请注明来源,并保留此行,尊重本人的劳动成果,谢谢。

来源:CSDN博客

作者:奔跑的QQEE

python 版本:2.7.13

(本文有删改)

python 数据结构

一、列表

列表结构有一些方法。如下所示:

方法作用
list.
append(x)
在列表尾追加新项,相当于 a[len(a):]=[x]
list.extend
(L)
用给定的列表扩展另一个列表。相当于a[len(a):]=L
list.insert(i,x)在给定位置插入项。i 表示要插入的位置。如 a.insert(0,x)表示将x插入到列表的第一个位置,此时x为第一项。a.insert(len(a),x) 相当于 a.append(x)
list.remove(x)移除列表中值为x的项。若没有此项返回错误。
list.pop([i])移除列表中指定位置的项,例a.pop(0)。若不指定索引值,例a.pop() 将移除并返回列表中最后一项。(方括号表示此项是可选的)
list.index(x)返回第一个值为x的项的索引值。若无此项,则返回错误。
list.count(x)返回x出现的次数
list.sort()对列表排序
list.reverse()逆置列表元素
例:

>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.25), a.count('x')
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
>>> a.pop()
1234.5
>>> a
[-1, 1, 66.25, 333, 333]


或许你已注意到像 insert,remove,sort 这类方法仅仅是修改了列表而并没有输出返回值。其实并非没有返回值,而是返回了默认值,None 。

二、将列表用作栈

栈的特点是“先进后出”。利用列表定义的方法,很容易实现栈的特性。例:

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]


三、将列表用作队列

队列的特点是“先进先出”。但是,用list定义的方法实现队列特性并不像实现栈的特性一样简单。原因是在表尾追加删除元素很快速,而在表头插入或删除元素很慢(其它所有元素都需要重新调整位置)。

python专门设计了快速在表两端追加删除元素的方法,从而实现了队列。只需调用collections.deque 即可。例:

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # 尾部追加元素 Terry
>>> queue.append("Graham")          # 尾部追加元素 Graham
>>> queue.popleft()                 # 移除并返回左侧元素
'Eric'
>>> queue.popleft()                 # 移除并返回左侧元素
'John'
>>> queue
deque(['Michael', 'Terry', 'Graham'])


四、三个常用的函数

有三个常用的函数经常和列表配合使用。它们是 filter(),map(),reduce()。

filter(function,sequence)方法接收一个目标函数和原始序列作参数;结果返回一个使function 函数为真的,包含于原始序列的子序列。如果原始序列是 str,unicode或tuple类型,那么子序列也是这种类型;否则子序列总是list 类型。例:

>>> def f(x): return x % 3 == 0 or x % 5 == 0   # x除以3或5后结果为0就是真
...
>>> filter(f, range(2, 25)) # 返回[2,25)范围内能满足f为真的序列
[3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]


map(function,sequence)方法为原始序列中每一项都调用一次function函数,并将所有子返回值整理成一个列表返回。例:

>>> def cube(x): return x*x*x
...
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]


若function函数需要多个参数,那么map方法需要传递多个原始序列。例:

>>> seq = range(8)
>>> def add(x, y): return x+y
...
>>> map(add, seq, seq)
[0, 2, 4, 6, 8, 10, 12, 14]


再看一个错误的例子:

>>>seq=range(8)
>>>sep=range(7)
>>>def add(x,y):return x+y
...
>>>map(add,seq,sep)

Trackback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in add
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'


因为sep序列长度为7,seq序列长度为8 。因此seq[7] 将与None类型数据计算。而 ‘+’ 运算符无法用于int 类型数据与None类型数据的计算。所以出现类型错误。

reduce(function,sequence)方法先将原始序列中的前两个项一起计算,将结果返回。随后再将结果与下一个项一起计算,将结果返回。直到原始序列中无项为止。例:

>>> def add(x,y): return x+y
...
>>> reduce(add, range(1, 11))
55


如果目标序列仅有一项,那么reduce() 的计算结果便是此值;如果目标序列是空,那么将抛出异常。

reduce()方法也可传递三个参数。其中第三个参数表示起始值。如果目标序列是空便返回起始值。目标函数首先应用于起始值和序列中的第一个值;然后应用于上一步的结果和下一个序列值。例:

>>> def sum(seq):
...     def add(x,y): return x+y
...     return reduce(add, seq, 0)
...
>>> sum(range(1, 11))
55
>>> sum([])
0


python内置函数已经提供了求和方法,sum( sequence )。

五、递推列表

使用递推列表可以简洁地来创建列表。列表中的每个元素都满足一定的规律。例:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]    # 一般方法得到的列表

>>>ListSquares = [x**2 for x in range(10)]
>>>ListSquares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]    # 递推列表方法得到的列表

>>>NewSquares = map(lambda x: x**2, range(10))
>>>NewSquares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]    # map 方法得到的列表


用此方法(递推列表)创建列表,可以包含若干 for 语句或 if 语句。例:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]


这相当于:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]


再看个综合例子:

>>> vec = [-4, -2, 0, 2, 4]
>>> # 以 vec 列表元素的 2 倍构造新列表
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]

>>> # 去除 vec 列表中的负数
>>> [x for x in vec if x >= 0]
[0, 2, 4]

>>> # vec 列表中的每个元素都执行 abs(x)函数,以求其绝对值。
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]

>>> # freshfruit 列表中每个元素都执行 strip()方法,以去除多余空格。
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']

>>> # 创建形如 (number, square) 的二维元组
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

>>> # 元组必须用括号括起来,否则会抛出语法错误
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1, in <module>
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax

>>> # 用两个 for 创建列表
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]


递推列表还可包含更加复杂的表达式和内置函数。

六、嵌套的递推列表

递推列表还可以包含递推列表。

有一列表如下:

>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]


下例将颠倒行列:

>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]


这相当于:

>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]




>>> transposed = []
>>> for i in range(4):
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]


或使用内置的zip() 函数,也能得到相同的效果。

>>> zip(*matrix)
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]


七、del语句

del 语句可通过指定索引值或索引范围来删除列表中的项。例:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]


del 也可用于删除变量:例:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined  # 未定义名称 a


八、元组和序列

列表和字符串有许多相同的特性,如它们都支持索引和切片操作;它们是两种不同的序列(字符串,unicode字符,列表,元组,二进制数组,buffer 和 xrange)。

如上所示,python支持元组序列。

元组由一系列逗号隔开的值构成。输出的结果总以括号包括,但输入时可不加括号。例:

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')

>>> # 元组也可被嵌套
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

>>> # 元组元素是不可被修改的
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment


元组和列表相似,但用处不同。元组元素不可变,且可包含不同的序列元素。而列表元素可变。

空元组和仅有一个元素的元组有特殊的表达方式,如:

>>> empty = ()
>>> singleton = 'hello',    # 一个元素的元组(值后跟一逗号)
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)


语句
t = 12345, 54321, 'hello!'
是元组打包的例子。三个元素被打包成一个元组元素 t。另外,解包也是可以的。例:

>>> x, y, z = t # 将 元组 t 解包,各个元素值依次赋给 x,y,z


九、集合

python支持集合操作。集合是无序的且无重复元素的。集合的基本操作包括关系检测,清除重复元素。另外,集合还支持并,交,差,对称差的数学运算。

用括号或set() 方法可以创建集合。

注意:如要创建空集合,应当使用set() 方法,而不应使用{} 括号。因为后者创建空字典。

例:

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> fruit = set(basket)               # 创建一无重复元素的集合
>>> fruit
set(['orange', 'pear', 'apple', 'banana'])

>>> 'orange' in fruit                 # 关系检测,'orange'是否在fruit集合内
True
>>> 'crabgrass' in fruit
False

>>> # 挑出非重复元素分别赋给 a,b
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # 集合 a
set(['a', 'r', 'b', 'c', 'd'])

>>> a - b                              # 在 a 中而不在 b 中的元素
set(['r', 'd', 'b'])

>>> a | b                              # 在 a 中或在 b 中的元素
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])

>>> a & b                              # 在 a 中且在 b 中的元素
set(['a', 'c'])

>>> a ^ b                              # 公共元素外的元素
set(['r', 'd', 'b', 'm', 'z', 'l'])


python 除了支持递推列表外,也支持递推集合。例:

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
set(['r', 'd'])


十、字典

python 支持字典类型。字典在其它语言中又被称作关联内存,或关联数组

序列是通过一系列数字进行索引操作的,而字典则通过键。任何不可变的类型都可当键。如,字符串,数字,元组(当元组只包含字符串,数字或元组时才可当键;若直接或间接包含了可变的对象,则不能当键。例如,列表就不能当键。因为列表可被修改)。

字典是键值对的集合。 所以字典中键值是唯一的。创建空字典用{}。向 {} 内添加多个用逗号隔开的 键:值 来增加字典元素;这也是字典元素输出的形式。

字典的基本操作是用键存值和给键查值。可用 del 语句删除某键值对。如果用已存在的键存对应的值,那么已存在的旧值将被覆盖。如果用不存在的键查值将出现错误提示。

keys() 方法返回包含所有字典中的键的无序列表。若要使结果有序,使用 sorted() 方法就行了。若要检测某键是否在字典中,使用关键字 in 。例:

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}

>>> tel['jack']
4098

>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}

>>> tel.keys()
['guido', 'irv', 'jack']

>>> 'guido' in tel
True


dict() 方法直接将键值对序列构造成字典。例:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}


相当于

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}


用递推的方式创建字典也是可以的。例:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}


十一、循环技术

使用enumerate() 方法,可在循环某个序列的同时检出索引和其对应的值。例:

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print i, v
...
0 tic
1 tac
2 toe


同时循环多个序列时,可通过zip() 方法将多个实体元素配对。例:

>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print 'What is your {0}?  It is {1}.'.format(q, a)
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.


反向循环某序列时,首先应指定序列的方向,然后再调用 reversed() 方法。例:

>>> for i in reversed(xrange(1,10,2)):
...     print i
...
9
7
5
3
1


按序循环某序列,应使用sorted() 方法。此方法将返回一新的序列且不改变原序列。例:

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print f
...
apple
banana
orange
pear


循环字典时,调用iteritems() 方法可同时返回键值对。例:

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
...     print k, v
...
gallahad the pure
robin the brave


偶尔在循环列表的同时需要直接对列表修改。然而,并不推荐这样做。更简单,更安全的做法是使用一新的空列表代替直接修改原列表。例:

>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
...     if not math.isnan(value):
...         filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]


十二、条件

while 和 if 语句可包含任何,而不仅仅是比较运算符。

比较运算符 in 和 not in 检测序列中是否有某值。 is 和 is not 比较两个对象是否是相同的。所有的比较运算符都有相同的优先级,其优先级都比所有的数字运算符低。

可连做比较运算。例:
a < b == c
表示检测 a 是否比 b 小,b 又是否等于 c 。

比较运算也可结合布尔运算符
and
or
进行。比较的结果或是其它布尔表达式都可用
not
修饰。布尔运算符比比较运算符的优先级更低。在布尔运算符之间,
not
的优先级最高,
or
的优先级最低。所以
A and not B or C
相当于
(A and (not B)) or C


布尔运算符
and
or
也叫作短路运算符。从左到右依次计算各参数的运算结果。只要结果确定就停止计算。例,如果
A
c
是true,
B
是false,
A and B and C
将不和
C
式计算。若将布尔运算符用于非布尔运算,计算的结果将是最后一个参与了计算的参数的值。例:

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim' # string1 和 string2 运算后得到了结果,因此不再和 string3 一起运算


十三、序列比较

序列对象可与同类型的序列作比较。比较方法是字典排序:首先前两项作比较,若这两项一样,则比较接下来的两项,直到某个序列无项可比。若待比两项是相同的序列类型,则递归执行字典排序。如果两序列所有项都相同,那么这两个序列就相等;如果某序列是另一序列的子序列,那么该序列比另一序列小,反之则大。对字符串的字典排序是从左到右依次比较各个字符的 ASCII 码值,码值大的字符串大于码值小的。例:

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: