python数据结构.docx
- 文档编号:25943182
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:11
- 大小:25.92KB
python数据结构.docx
《python数据结构.docx》由会员分享,可在线阅读,更多相关《python数据结构.docx(11页珍藏版)》请在冰豆网上搜索。
python数据结构
5数据结构潭州教育
本章详细讨论了你已经学过的一些知识,同样也添加了一些新内容。
5.1.关于列表更多的内容
Python的列表数据类型包含更多的方法。
这里是所有的列表对象方法:
list.append(x)
把一个元素添加到链表的结尾,相当于 a[len(a):
] = [x] 。
list.extend(L)
将一个给定列表中的所有元素都添加到另一个列表中,相当于 a[len(a):
] = L 。
list.insert(i, x)
在指定位置插入一个元素。
第一个参数是准备插入到其前面的那个元素的索引,例如a.insert(0, x) 会插入到整个链表之前,而 a.insert(len(a), x) 相当于 a.append(x) 。
list.remove(x)
删除链表中值为 x 的第一个元素。
如果没有这样的元素,就会返回一个错误。
list.pop([i])
从链表的指定位置删除元素,并将其返回。
如果没有指定索引, a.pop() 返回最后一个元素。
元素随即从链表中被删除。
(方法中 i 两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在Python库参考手册中遇到这样的标记。
)
list.index(x)
返回链表中第一个值为 x 的元素的索引。
如果没有匹配的元素就会返回一个错误。
list.count(x)
返回 x 在链表中出现的次数。
list.sort()
对链表中的元素就地进行排序。
list.reverse()
就地倒排链表中的元素。
下面这个示例演示了链表的大部分方法:
>>>a=[66.25,333,333,1,1234.5]>>>printa.count(333),a.count(66.25),a.count('x')210>>>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]
也许大家会发现像 insert, remove 或者 sort 这些修改列表的方法没有打印返回值–它们返回 None。
在python中对所有可变的数据类型这是统一的设计原则。
5.1.1.把链表当作堆栈使用
链表方法使得链表可以很方便的做为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。
用 append() 方法可以把一个元素添加到堆栈顶。
用不指定索引的pop() 方法可以把一个元素从堆栈顶释放出来。
例如:
>>>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]
5.1.2.把链表当作队列使用
你也可以把链表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。
不过,列表这样用效率不高。
相对来说从列表末尾添加和弹出很快;在头部插入和弹出很慢(因为,为了一个元素,要移动整个列表中的所有元素)。
要实现队列,使用 collections.deque ,它为在首尾两端快速插入和删除而设计。
例如:
>>>fromcollectionsimportdeque>>>queue=deque(["Eric","John","Michael"])>>>queue.append("Terry")#Terryarrives>>>queue.append("Graham")#Grahamarrives>>>queue.popleft()#Thefirsttoarrivenowleaves'Eric'>>>queue.popleft()#Thesecondtoarrivenowleaves'John'>>>queue#Remainingqueueinorderofarrivaldeque(['Michael','Terry','Graham'])
5.1.3.函数式编程工具
对于链表来讲,有三个内置函数非常有用:
filter(), map(),以及 reduce()。
filter(function, sequence) 返回一个sequence(序列),包括了给定序列中所有调用 function(item)后返回值为true的元素。
(如果可能的话,会返回相同的类型)。
如果该 序列 (sequence)是一个 string (字符串)或者 tuple (元组),返回值必定是同一类型,否则,它总是 list 。
例如,以下程序可以计算部分素数:
>>>deff(x):
returnx%2!
=0andx%3!
=0...>>>filter(f,range(2,25))[5,7,11,13,17,19,23]
map(function, sequence) 为每一个元素依次调用 function(item) 并将返回值组成一个链表返回。
例如,以下程序计算立方:
>>>defcube(x):
returnx*x*x...>>>map(cube,range(1,11))[1,8,27,64,125,216,343,512,729,1000]
可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上对应的元素来调用函数(如果某些序列比其它的短,就用 None 来代替)。
如果把 None 做为一个函数传入,则直接返回参数做为替代。
例如:
>>>seq=range(8)>>>defadd(x,y):
returnx+y...>>>map(add,seq,seq)[0,2,4,6,8,10,12,14]
reduce(function, sequence) 返回一个单值,它是这样构造的:
首先以序列的前两个元素调用函数function,再以返回值和第三个参数调用,依次执行下去。
例如,以下程序计算1到10的整数之和:
>>>defadd(x,y):
returnx+y...>>>reduce(add,range(1,11))55
如果序列中只有一个元素,就返回它,如果序列是空的,就抛出一个异常。
可以传入第三个参数作为初始值。
如果序列是空的,就返回初始值,否则函数会先接收初始值和序列的第一个元素,然后是返回值和下一个元素,依此类推。
例如:
>>>defsum(seq):
...defadd(x,y):
returnx+y...returnreduce(add,seq,0)...>>>sum(range(1,11))55>>>sum([])0
不要像示例中这样定义 sum() :
因为合计数值是一个通用的需求,早已有内置的 sum(sequence) 函数,非常好用。
5.1.4.列表推导式
列表推导式为从序列中创建列表提供了一个简单的方法。
普通的应用程序通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。
例如,假设我们创建一个squares列表,可以像下面方式:
>>>squares=[]>>>forxinrange(10):
...squares.append(x**2)...>>>squares[0,1,4,9,16,25,36,49,64,81]
我们同样能够达到目的采用下面的方式:
squares=[x**2forxinrange(10)]
这也相当于 squares = map(lambda x:
x**2, range(10)),但是上面的方式显得简洁以及具有可读性.
列表推导式由包含一个表达式的括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个for 或 if 子句。
结果是一个列表,由表达式依据其后面的 for 和 if 子句上下文计算而来的结果构成。
例如,如下的列表推导式结合两个列表的元素,如果元素之间不相等的话:
>>>[(x,y)forxin[1,2,3]foryin[3,1,4]ifx!
=y][(1,3),(1,4),(2,3),(2,1),(2,4),(3,1),(3,4)]
等同于:
>>>combs=[]>>>forxin[1,2,3]:
...foryin[3,1,4]:
...ifx!
=y:
...combs.append((x,y))...>>>combs[(1,3),(1,4),(2,3),(2,1),(2,4),(3,1),(3,4)]
值得注意的是在上面两个方法中的 for 和 if 语句的顺序。
如果想要得到一个元组,必须要加上括号:
>>>vec=[-4,-2,0,2,4]>>>#createanewlistwiththevaluesdoubled>>>[x*2forxinvec][-8,-4,0,4,8]>>>#filterthelisttoexcludenegativenumbers>>>[xforxinvecifx>=0][0,2,4]>>>#applyafunctiontoalltheelements>>>[abs(x)forxinvec][4,2,0,2,4]>>>#callamethodoneachelement>>>freshfruit=['banana','loganberry','passionfruit']>>>[weapon.strip()forweaponinfreshfruit]['banana','loganberry','passionfruit']>>>#createalistof2-tupleslike(number,square)>>>[(x,x**2)forxinrange(6)][(0,0),(1,1),(2,4),(3,9),(4,16),(5,25)]>>>#thetuplemustbeparenthesized,otherwiseanerrorisraised>>>[x,x**2forxinrange(6)]File"
[x,x**2forxinrange(6)]^SyntaxError:
invalidsyntax>>>#flattenalistusingalistcompwithtwo'for'>>>vec=[[1,2,3],[4,5,6],[7,8,9]]>>>[numforeleminvecfornuminelem][1,2,3,4,5,6,7,8,9]
列表推导式可使用复杂的表达式和嵌套函数:
>>>frommathimportpi>>>[str(round(pi,i))foriinrange(1,6)]['3.1','3.14','3.142','3.1416','3.14159']
5.1.4.1.嵌套的列表推导式
列表推导式可以嵌套。
考虑以下的3x4矩阵,一个列表中包含三个长度为4的列表:
>>>matrix=[...[1,2,3,4],...[5,6,7,8],...[9,10,11,12],...]
现在,如果你想交换行和列,可以用嵌套的列表推导式:
>>>[[row[i]forrowinmatrix]foriinrange(4)][[1,5,9],[2,6,10],[3,7,11],[4,8,12]]
像前面看到的,嵌套的列表推导式是对 for 后面的内容进行求值,所以上例就等价于:
>>>transposed=[]>>>foriinrange(4):
...transposed.append([row[i]forrowinmatrix])...>>>transposed[[1,5,9],[2,6,10],[3,7,11],[4,8,12]]
反过来说,如下也是一样的:
>>>transposed=[]>>>foriinrange(4):
...#thefollowing3linesimplementthenestedlistcomp...transposed_row=[]...forrowinmatrix:
...transposed_row.append(row[i])...transposed.append(transposed_row)...>>>transposed[[1,5,9],[2,6,10],[3,7,11],[4,8,12]]
在实际中,你应该更喜欢使用内置函数组成复杂流程语句。
对此种情况 zip() 函数将会做的更好:
>>>list(zip(*matrix))[(1,5,9),(2,6,10),(3,7,11),(4,8,12)]
更多关于本行中使用的星号的说明,参考 参数列表的分拆 。
5.2. del 语句
有个方法可以从列表中按给定的索引而不是值来删除一个子项:
del 语句。
它不同于有返回值的pop() 方法。
语句 del 还可以从列表中删除切片或清空整个列表(我们以前介绍过一个方法是将空列表赋值给列表的切片)。
例如:
>>>a=[-1,1,66.25,333,333,1234.5]>>>dela[0]>>>a[1,66.25,333,333,1234.5]>>>dela[2:
4]>>>a[1,66.25,1234.5]>>>dela[:
]>>>a[]
del 也可以删除整个变量:
>>>dela
此后再引用命名 a 会引发错误(直到另一个值赋给它为止)。
我们在后面的内容中可以看到 del的其它用法。
5.3.元组和序列
我们知道链表和字符串有很多通用的属性,例如索引和切割操作。
它们是序列类型(参见typesseq )中的两种。
因为Python是一个在不断进化的语言,也可能会加入其它的序列类型,这里介绍另一种标准序列类型:
元组 。
一个元组由数个逗号分隔的值组成,例如:
>>>t=12345,54321,'hello!
'>>>t[0]12345>>>t(12345,54321,'hello!
')>>>#Tuplesmaybenested:
...u=t,(1,2,3,4,5)>>>u((12345,54321,'hello!
'),(1,2,3,4,5))>>>#Tuplesareimmutable:
...t[0]=88888Traceback(mostrecentcalllast):
File"
'tuple'objectdoesnotsupportitemassignment>>>#buttheycancontainmutableobjects:
...v=([1,2,3],[3,2,1])>>>v([1,2,3],[3,2,1])Traceback(mostrecentcalllast):
File"
'tuple'objectdoesnotsupportitemassignment
如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。
在输入时可以有或没有括号,不过经常括号都是必须的(如果元组是一个更大的表达式的一部分)。
不能给元组的一个独立的元素赋值(尽管你可以通过联接和切割来模拟)。
还可以创建包含可变对象的元组,例如链表。
虽然元组和列表很类似,它们经常被用来在不同的情况和不同的用途。
元组有很多用途。
例如(x,y)坐标对,数据库中的员工记录等等。
元组就像字符串,不可改变。
一个特殊的问题是构造包含零个或一个元素的元组:
为了适应这种情况,语法上有一些额外的改变。
一对空的括号可以创建空元组;要创建一个单元素元组可以在值后面跟一个逗号(在括号中放入一个单值不够明确)。
丑陋,但是有效。
例如:
>>>empty=()>>>singleton='hello',#<--notetrailingcomma>>>len(empty)0>>>len(singleton)1>>>singleton('hello',)
语句 t = 12345, 54321, 'hello!
' 是 元组封装 (tuplepacking)的一个例子:
值 12345 , 54321 和'hello!
' 被封装进元组。
其逆操作可能是这样:
>>>x,y,z=t
这个调用等号右边可以是任何线性序列,称之为 序列拆封 非常恰当。
序列拆封要求左侧的变量数目与序列的元素个数相同。
要注意的是可变参数(multipleassignment)其实只是元组封装和序列拆封的一个结合。
5.4.集合
Python还包含了一个数据类型 set (集合)。
集合是一个无序不重复元素的集。
基本功能包括关系测试和消除重复元素。
集合对象还支持union(联合),intersection(交),difference(差)和sysmmetricdifference(对称差集)等数学运算。
大括号或 set() 函数可以用来创建集合。
注意:
想要创建空集合,你必须使用 set() 而不是 {} 。
后者用于创建空字典,我们在下一节中介绍的一种数据结构。
以下是一个简单的演示:
>>>basket=['apple','orange','apple','pear','orange','banana']>>>fruit=set(basket)#createasetwithoutduplicates>>>fruitset(['orange','pear','apple','banana'])>>>'orange'infruit#fastmembershiptestingTrue>>>'crabgrass'infruitFalse
>>>#Demonstratesetoperationsonuniquelettersfromtwowords...>>>a=set('abracadabra')>>>b=set('alacazam')>>>a#uniquelettersinaset(['a','r','b','c','d'])>>>a-b#lettersinabutnotinbset(['r','d','b'])>>>a|b#lettersineitheraorbset(['a','c','r','d','b','m','z','l'])>>>a&b#lettersinbothaandbset(['a','c'])>>>a^b#lettersinaorbbutnotbothset(['r','d','b','m','z','l'])
类似 forlists ,这里有一种集合推导式语法:
>>>a={xforxin'abracadabra'ifxnotin'abc'}>>>a{'r','d'}
5.5.字典
另一个非常有用的Python内建数据类型是 字典 (参见 typesmapping )。
字典在某些语言中可能称为联合内存(associativememories)或联合数组(associativearrays)。
序列是以连续的整数为索引,与此不同的是,字典以 关键字 为索引,关键字可以是任意不可变类型,通常用字符串或数值。
如果元组中只包含字符串和数字,它可以作为关键字,如果它直接或间接地包含了可变对象,就不能当做关键字。
不能用链表做关键字,因为链表可以用索引、切割或者 append() 和extend() 等方法改变。
理解字典的最佳方式是把它看做无序的键:
值对 (key:
valuepairs)集合,键必须是互不相同的(在同一个字典之内)。
一对大括号创建一个空的字典:
{} 。
初始化链表时,在大括号内放置一组逗号分隔的键:
值对,这也是字典输出的方式。
字典的主要操作是依据键来存储和析取值。
也可以用 del 来删除键:
值对(key:
value)。
如果你用一个已经存在的关键字存储值,以前为该关键字分配的值就会被遗忘。
试图从一个不存在的键中取值会导致错误。
对一个字典执行 keys() 将返回一个字典中所有关键字组成的无序列表(如果你想要排序,只需使用sorted())。
使用 in 关键字(指Python语法)可以检查字典中是否存在某个关键字(指字典)。
这里是使用字典的一个小示例:
>>>tel={'jack':
4098,'sape':
4139}>>>tel['guido']=4127>>>tel{'sape':
4139,'guido':
4127,'jack':
4098}>>>tel['jack']4098>>>deltel['sape']>>>tel['irv']=4127>>>tel{'guido':
4127,'irv':
4127,'jack':
4098}>>>tel.keys()['guido','irv','jack']>>>'guido'intelTrue
dict() 构造函数可以直接从key-value对中创建字典:
>>>dict([('sape',4139),('guido',4127),('jack',4098)]){'sape':
4139,'jack':
4098,'guido':
4127}
此外,字典推导式可以从任意的键值表达式中创建字典:
>>>{x:
x**2forxin(2,4,6)}{2:
4,4:
16,6:
36}
如果关键
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- python 数据结构