⑴ 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的倍數的列表。