⑴ python中sorted函数的空间复杂度是多少
sorted(iterable,cmp,key,reverse)
参数:iterable可以是list或者iterator;
cmp是带两个参数的比较函数;
key
是带一个参数的函数;
reverse为False或者True;
举例说明
(1)用cmp函数排序
>>>
list1
=
[('david',
90),
('mary',90),
('sara',80),('lily',95)]
>>>
sorted(list1,cmp
=
lambda
x,y:
cmp(x[0],y[0]))
[('david',
90),
('lily',
95),
('mary',
90),
('sara',
80)]
>>>
sorted(list1,cmp
=
lambda
x,y:
cmp(x[1],y[1]))
[('sara',
80),
('david',
90),
('mary',
90),
('lily',
95)]
(2)用key函数排序
>>>
list1
=
[('david',
90),
('mary',90),
('sara',80),('lily',95)]
>>>
sorted(list1,key
=
lambda
list1:
list1[0])
[('david',
90),
('lily',
95),
('mary',
90),
('sara',
80)]
>>>
sorted(list1,key
=
lambda
list1:
list1[1])
[('sara',
80),
('david',
90),
('mary',
90),
('lily',
95)]
(3)用reverse排序
>>>
sorted(list1,reverse
=
True)
[('sara',
80),
('mary',
90),
('lily',
95),
('david',
90)]
(4)用operator.itemgetter函数排序
>>>
from
operator
import
itemgetter
>>>
sorted(list1,
key=itemgetter(1))
[('sara',
80),
('david',
90),
('mary',
90),
('lily',
95)]
>>>
sorted(list1,
key=itemgetter(0))
[('david',
90),
('lily',
95),
('mary',
90),
('sara',
80)]
介绍operator.itemgetter函数
>>>
import
operator
>>>
a
=
[1,2,3]
>>>
b
=
operator.itemgetter(0)
>>>
b(a)
1
operator.itemgetter函数获取的不是值,而是定义了一个函数。
(5)多级排序
>>>
sorted(list1,
key=itemgetter(0,1))
[('david',
90),
('lily',
95),
('mary',
90),
('sara',
80)]
空间复杂度是O(n)
⑵ python几种经典排序方法的实现
class SortMethod:
'''
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。
插入算法把要排序的数组分成两部分:
第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置)
第二部分就只包含这一个元素(即待插入元素)。
在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
'''
def insert_sort(lists):
# 插入排序
count = len(lists)
for i in range(1, count):
key = lists[i]
j = i - 1
while j >= 0:
if lists[j] > key:
lists[j + 1] = lists[j]
lists[j] = key
j -= 1
return lists
'''
希尔排序 (Shell Sort) 是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 DL.Shell 于 1959 年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。
'''
def shell_sort(lists):
# 希尔排序
count = len(lists)
step = 2
group = count / step
while group > 0:
for i in range(0, group):
j = i + group
while j < count:
k = j - group
key = lists[j]
while k >= 0:
if lists[k] > key:
lists[k + group] = lists[k]
lists[k] = key
k -= group
j += group
group /= step
return lists
'''
冒泡排序重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
'''
def bubble_sort(lists):
# 冒泡排序
count = len(lists)
for i in range(0, count):
for j in range(i + 1, count):
if lists[i] > lists[j]:
temp = lists[j]
lists[j] = lists[i]
lists[i] = temp
return lists
'''
快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
'''
def quick_sort(lists, left, right):
# 快速排序
if left >= right:
return lists
key = lists[left]
low = left
high = right
while left < right:
while left < right and lists[right] >= key:
right -= 1
lists[left] = lists[right]
while left < right and lists[left] <= key:
left += 1
lists[right] = lists[left]
lists[right] = key
quick_sort(lists, low, left - 1)
quick_sort(lists, left + 1, high)
return lists
'''
直接选择排序
第 1 趟,在待排序记录 r[1] ~ r[n] 中选出最小的记录,将它与 r[1] 交换;
第 2 趟,在待排序记录 r[2] ~ r[n] 中选出最小的记录,将它与 r[2] 交换;
以此类推,第 i 趟在待排序记录 r[i] ~ r[n] 中选出最小的记录,将它与 r[i] 交换,使有序序列不断增长直到全部排序完毕。
'''
def select_sort(lists):
# 选择排序
count = len(lists)
for i in range(0, count):
min = i
for j in range(i + 1, count):
if lists[min] > lists[j]:
min = j
temp = lists[min]
lists[min] = lists[i]
lists[i] = temp
return lists
'''
堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即 A[PARENT[i]] >= A[i]。
在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
'''
# 调整堆
def adjust_heap(lists, i, size):
lchild = 2 * i + 1
rchild = 2 * i + 2
max = i
if i < size / 2:
if lchild < size and lists[lchild] > lists[max]:
max = lchild
if rchild < size and lists[rchild] > lists[max]:
max = rchild
if max != i:
lists[max], lists[i] = lists[i], lists[max]
adjust_heap(lists, max, size)
# 创建堆
def build_heap(lists, size):
for i in range(0, (size/2))[::-1]:
adjust_heap(lists, i, size)
# 堆排序
def heap_sort(lists):
size = len(lists)
build_heap(lists, size)
for i in range(0, size)[::-1]:
lists[0], lists[i] = lists[i], lists[0]
adjust_heap(lists, 0, i)
'''
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法 (Divide and Conquer) 的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
归并过程为:
比较 a[i] 和 a[j] 的大小,若 a[i]≤a[j],则将第一个有序表中的元素 a[i] 复制到 r[k] 中,并令 i 和 k 分别加上 1;
否则将第二个有序表中的元素 a[j] 复制到 r[k] 中,并令 j 和 k 分别加上 1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到 r 中从下标 k 到下标 t 的单元。归并排序的算法我们通常用递归实现,先把待排序区间 [s,t] 以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间 [s,t]。
'''
def merge(left, right):
i, j = 0, 0
result = []
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
def merge_sort(lists):
# 归并排序
if len(lists) <= 1:
return lists
num = len(lists) / 2
left = merge_sort(lists[:num])
right = merge_sort(lists[num:])
return merge(left, right)
'''
基数排序 (radix sort) 属于“分配式排序” (distribution sort),又称“桶子法” (bucket sort) 或 bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,借以达到排序的作用,基数排序法是属于稳定性的排序。
其时间复杂度为 O (nlog(r)m),其中 r 为所采取的基数,而 m 为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
'''
import math
def radix_sort(lists, radix=10):
k = int(math.ceil(math.log(max(lists), radix)))
bucket = [[] for i in range(radix)]
for i in range(1, k+1):
for j in lists:
bucket[j/(radix**(i-1)) % (radix**i)].append(j)
del lists[:]
for z in bucket:
lists += z
del z[:]
return lists
---------------------
作者:CRazyDOgen
来源:CSDN
原文:https://blog.csdn.net/jipang6225/article/details/79975312
版权声明:本文为博主原创文章,转载请附上博文链接!
⑶ python 排序,sort和sorted的区别是什么
Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列。
sorted(iterable,key=None,reverse=False),返回新的列表,对所有可迭代的对象均有效
sort(key=None,reverse=False) 就地改变列表 reverse:True反序;False 正序
⑷ 什么是python内置函数sorted
Python对容器内数据的排序有两种,一种是容器自己的sort函数,一种是内建的sorted函数。
sort函数和sorted函数唯一的不同是,sort是在容器内排序,sorted生成一个新的排好序的容器。
对于一个简单的数组 L=[5,2,3,1,4].
sort: L.sort()
sorted(...)
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
iterable:待排序的可迭代类型的容器;
cmp:用于比较的函数,比较什么由key决定,有默认值,迭代集合中的一项;
key:用列表元素的某个已命名的属性或函数(只有一个参数并且返回一个用于排序的值)作为关键字,有默认值,迭代集合中的一项;
reverse:排序规则. reverse = True 或者 reverse = False,有默认值。
返回值:是一个经过排序的可迭代类型,与iterable一样。
如果是一个多维的列表 L=[(‘b’,2),(‘a’,1),(‘c’,3),(‘d’,4)].
有三种选择对这个多维列表进行排序
利用cmp函数
sorted(L, cmp=lambda x,y:cmp(x[1],y[1]))
L.sort(cmp=lambda x,y:cmp(x[1],y[1]))
利用key
sorted(L, key=lambda x:x[1]);
L.sort(key=lambda x:x[1]);
反序
以上几种排序均可加上参数reverse.
例如 sorted(reverse=True), L.sort(reverse=True). 或者改成False
OrderedDict是collections中的一个包,能够记录字典元素插入的顺序,常常和排序函数一起使用来生成一个排序的字典。
比如,比如一个无序的字典
d = {‘banana’:3,’apple’:4,’pear’:1,’orange’:2}
通过排序来生成一个有序的字典,有以下几种方式
collections.OrderedDict(sorted(d.items(),key = lambda t:t[0]))
或者
collections.OrderedDict(sorted(d.items(),key = lambda t:t[1]))
或者
collections.OrderedDict(sorted(d.items(),key = lambda t:len(t[0])))
⑸ Python判断列表是否已排序的各种方法及其性能
本节判断列表排序的函数名格式为IsListSorted_XXX()。为简洁起见,除代码片段及其输出外,一律以_XXX()指代。
2.1 guess
def IsListSorted_guess(lst):
listLen = len(lst) if listLen <= 1: return True
#由首个元素和末尾元素猜测可能的排序规则
if lst[0] == lst[-1]: #列表元素相同
for elem in lst: if elem != lst[0]: return False
elif lst[0] < lst[-1]: #列表元素升序
for i, elem in enumerate(lst[1:]): if elem < lst[i]: return False
else: #列表元素降序
for i, elem in enumerate(lst[1:]): if elem > lst[i]: return False
return True
_guess()是最通用的实现,几乎与语言无关。值得注意的是,该函数内会猜测给定列表可能的排序规则,因此无需外部调用者指明排序规则。
2.2 sorted
def IsListSorted_sorted(lst):
return sorted(lst) == lst or sorted(lst, reverse=True) == lst
_sorted()使用Python内置函数sorted()。由于sorted()会对未排序的列表排序,_sorted()函数主要适用于已排序列表。
若想判断列表未排序后再对其排序,不如直接调用列表的sort()方法,因为该方法内部会判断列表是否排序。对于已排序列表,该方法的时间复杂度为线性阶O(n)——判断为O(n)而排序为O(nlgn)。
2.3 for-loop
def IsListSorted_forloop(lst, key=lambda x, y: x <= y):
for i, elem in enumerate(lst[1:]): #注意,enumerate默认迭代下标从0开始
if not key(lst[i], elem): #if elem > lst[i]更快,但通用性差
return False
return True
无论列表是否已排序,本函数的时间复杂度均为线性阶O(n)。注意,参数key表明缺省的排序规则为升序。
2.4 all
def IsListSorted_allenumk(lst, key=lambda x, y: x <= y):
return all(key(lst[i], elem) for i, elem in enumerate(lst[1:]))import operatordef IsListSorted_allenumo(lst, oCmp=operator.le):
return all(oCmp(lst[i], elem) for i, elem in enumerate(lst[1:]))def IsListSorted_allenumd(lst):
return all((lst[i] <= elem) for i, elem in enumerate(lst[1:]))def IsListSorted_allxran(lst, key=lambda x,y: x <= y):
return all(key(lst[i],lst[i+1]) for i in xrange(len(lst)-1))def IsListSorted_allzip(lst, key=lambda x,y: x <= y):
from itertools import izip #Python 3中zip返回生成器(generator),而izip被废弃
return all(key(a, b) for (a, b) in izip(lst[:-1],lst[1:]))
lambda表达式与operator运算符速度相当,前者简单灵活,后者略为高效(实测并不一定)。但两者速度均不如列表元素直接比较(可能存在调用开销)。亦即,_allenumd()快于_allenumo()快于_allenumk()。
若使用lambda表达式指示排序规则,更改规则时只需要改变x和y之间的比较运算符;若使用operator模块指示排序规则,更改规则时需要改变对象比较方法。具体地,lt(x, y)等效于x < y,le(x, y)等效于x <= y,eq(x, y)等效于x == y,ne(x, y)等效于x != y,gt(x, y)等效于x > y,ge(x, y)等效于x >= y。例如,_allenumo()函数若要严格升序可设置oCmp=operator.lt。
此外,由all()函数的帮助信息可知,_allenumk()其实是_forloop()的等效形式。
2.5 numpy
def IsListSorted_numpy(arr, key=lambda dif: dif >= 0):
import numpy try: if arr.dtype.kind == 'u': #无符号整数数组执行np.diff时存在underflow风险
arr = numpy.int64(lst) except AttributeError: pass #无dtype属性,非数组
return (key(numpy.diff(arr))).all() #numpy.diff(x)返回相邻数组元素的差值构成的数组
NumPy是用于科学计算的Python基础包,可存储和处理大型矩阵。它包含一个强大的N维数组对象,比Python自身的嵌套列表结构(nested list structure)高效得多。第三节的实测数据表明,_numpy()处理大型列表时性能非常出色。
在Windows系统中可通过pip install numpy命令安装NumPy包,不建议登录官网下载文件自行安装。
2.6 rece
def IsListSorted_rece(iterable, key=lambda x, y: x <= y):
cmpFunc = lambda x, y: y if key(x, y) else float('inf') return rece(cmpFunc, iterable, .0) < float('inf')
rece实现是all实现的变体。累加器(accumulator)中仅存储最后一个检查的列表元素,或者Infinity(若任一元素小于前个元素值)。
前面2.1~2.5小节涉及下标操作的函数适用于列表等可迭代对象(Iterable)。对于通用迭代器(Iterator)对象,即可以作用于next()函数或方法的对象,可使用_rece()及后面除_rand()外各小节的函数。迭代器的计算是惰性的,只有在需要返回下一个数据时才会计算,以避免不必要的计算。而且,迭代器方式无需像列表那样切片为两个迭代对象。
2.7 imap
def IsListSorted_itermap(iterable, key=lambda x, y: x <= y):
from itertools import imap, tee
a, b = tee(iterable) #为单个iterable创建两个独立的iterator
next(b, None) return all(imap(key, a, b))
2.8 izip
def IsListSorted_iterzip(iterable, key=lambda x, y: x <= y):
from itertools import tee, izip
a, b = tee(iterable) next(b, None) return all(key(x, y) for x, y in izip(a, b))def pairwise(iterable):
from itertools import tee, izip
a, b = tee(iterable) next(b, None) return izip(a, b) #"s -> (s0,s1), (s1,s2), (s2, s3), ..."def IsListSorted_iterzipf(iterable, key=lambda x, y: x <= y):
return all(key(a, b) for a, b in pairwise(iterable))
第三节的实测数据表明,虽然存在外部函数调用,_iterzipf()却比_iterzip()略为高效。
2.9 fast
def IsListSorted_fastd(lst):
it = iter(lst) try:
prev = it.next() except StopIteration: return True
for cur in it: if prev > cur: return False
prev = cur return Truedef IsListSorted_fastk(lst, key=lambda x, y: x <= y):
it = iter(lst) try:
prev = it.next() except StopIteration: return True
for cur in it: if not key(prev, cur): return False
prev = cur return True
_fastd()和_fastk()是Stack Overflow网站回答里据称执行最快的。实测数据表明,在列表未排序时,它们的性能表现确实优异。
2.10 random
import randomdef IsListSorted_rand(lst, randNum=3, randLen=100):
listLen = len(lst) if listLen <= 1: return True
#由首个元素和末尾元素猜测可能的排序规则
if lst[0] < lst[-1]: #列表元素升序
key = lambda dif: dif >= 0
else: #列表元素降序或相等
key = lambda dif: dif <= 0
threshold, sortedFlag = 10000, True
import numpy if listLen <= threshold or listLen <= randLen*2 or not randNum: return (key(numpy.diff(numpy.array(lst)))).all() from random import sample for i in range(randNum):
sortedRandList = sorted(sample(xrange(listLen), randLen))
flag = (key(numpy.diff(numpy.array([lst[x] for x in sortedRandList])))).all()
sortedFlag = sortedFlag and flag return sortedFlag
_rand()借助随机采样降低运算规模,并融入其他判断函数的优点。例如,猜测列表可能的排序规则,并在随机采样不适合时使用相对快速的判断方式,如NumPy。
通过line_profiler分析可知,第20行和第21行与randLen有关,但两者耗时接近。因此randLen应小于listLen的一半,以抵消sorted开销。除内部限制外,用户可以调节随机序列个数和长度,如定制单个但较长的序列。
注意,_rand()不适用于存在微量异常数据的长列表。因为这些数据很可能被随机采样遗漏,从而影响判断结果的准确性。
⑹ 求python中,自定义的复杂数据结构,快速排序的方法
应该是你sorted的使用方式不对吧,它可以对name.key这样的形式进行排序的。
classm:
def__init__(self,name,id):
self.name=name
self.id=id
@property
defkey(self):
returnself.name
deflen(self):
returnlen(self.name)
def__str__(self):
return'{{'name':'{0}','id':{1}}}'
.format(self.name,self.id)
__repr__=__str__
s=[m('zzzz',1),m('aaa',4)]
l=[('source',s),
]
#直接属性排序
l.append(('byname',sorted(s,key=lambdax:x.name)))
l.append(('byid',sorted(s,key=lambdax:x.id)))
#属性函数排序
l.append(('bykey',sorted(s,key=lambdax:x.key)))
#函数排序
l.append(('bylen()',sorted(s,key=lambdax:x.len())))
foreinl:
print(e[0])
print(e[1])
这是输出的结果:
source
[{'name':'zzzz','id':1},{'name':'aaa','id':4}]
byname
[{'name':'aaa','id':4},{'name':'zzzz','id':1}]
byid
[{'name':'zzzz','id':1},{'name':'aaa','id':4}]
bykey
[{'name':'aaa','id':4},{'name':'zzzz','id':1}]
bylen()
[{'name':'aaa','id':4},{'name':'zzzz','id':1}]
上述四种用法都是没问题的,至于name[key]的形式同样是OK的。
sorted的参数key,它是一个函数,简单的话可以直接用lambda,复杂点的可以定义成有一个参数的函数,比如:
defsorted_other(item):
ifhasattr(item,'name'):
returnitem.name
else:
returnNone
l.append(('byotherfunc',sorted(s,key=sorted_other)))
⑺ python中sort和sorted的问题
james.sort()是直接在原来james上排序,执行后james已经排好序,但sort()函数返回None,print(james.sort())输出的是sort()的返回值,james.sort() ,print(james)才会打印排序好的james
sorted(james)是返回一个新的排序好的列表 ,原来的james没有变
⑻ python的sorted排序问题
test = [6,1,2,3,4,5]
a = sorted(test,reverse=True)
print a
结果如下:
[6, 5, 4, 3, 2, 1]
你可以参考下sorted,里面是可以接收reverse参数的
def sorted(iterable, cmp=None, key=None, reverse=False): # real signature unknown; restored from __doc__
""" sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list """
pass
⑼ python 为什么sorted()会出现这样的情况
我来回答你这个python问题。
其实python的内置函数list.sort()和sorted(),他们都用来对序列进行排序,但是有区别:
list.sort()是对列表in-place排序(你可以这么理解,就是所有操作都在内存中完成,基于内存地址的排序),注意,返回值是None;
sorted()返回排好序的新列表,原列表不变。
还有一点你可能也要知道,list.sort()只适用于列表,sorted()适用于任意可迭代对象。
所以,你明白了吗?你图中的列表a不变。
⑽ 关于python的sorted函数的问题
实际上sorted()后面跟着的内容,是一个列表生成式,相当于一个列表。
列表生成式格式就是 ... for ... in ... if .......,具体请在网上搜索。
比如 [x for x in range(100) if x%3==0],意思就是 1到100内所有3的倍数的列表。