亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

幾種常用排序算法的python實現(xiàn)

Original 2016-11-11 16:53:28 436
abstract:1:快速排序思想:任意選取一個數(shù)據(jù)(通常選用數(shù)組的第一個數(shù))作為關鍵數(shù)據(jù),然后將所有比它小的數(shù)都放到它前面,所有比它大的數(shù)都放到它后面,這個過程稱為一趟快速排序。一趟快速排序的算法是:1)設置兩個變量i、j,排序開始的時候:i=0,j=N-1;2)以第一個數(shù)組元素作為關鍵數(shù)據(jù),賦值給key,即key=A[0];3)從j開始向前搜索,即由后開始向前搜索(j--),找到第一個小于key的值A[j],將

1:快速排序

思想:

任意選取一個數(shù)據(jù)(通常選用數(shù)組的第一個數(shù))作為關鍵數(shù)據(jù),然后將所有比它小的數(shù)都放到它前面,所有比它大的數(shù)都放到它后面,這個過程稱為一趟快速排序。

一趟快速排序的算法是:

1)設置兩個變量i、j,排序開始的時候:i=0,j=N-1;

2)以第一個數(shù)組元素作為關鍵數(shù)據(jù),賦值給key,即key=A[0];

3)從j開始向前搜索,即由后開始向前搜索(j--),找到第一個小于key的值A[j],將A[j]賦給A[i];

4)從i開始向后搜索,即由前開始向后搜索(i++),找到第一個大于key的A[i],將A[i]賦給A[j];

5)重復第3、4步,直到i=j; (3,4步中,沒找到符合條件的值,即3中A[j]不小于key,4中A[i]不大于key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指針位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令循環(huán)結束)。

注意:快速排序不會直接得到最終結果,只會把比k大和比k小的數(shù)分到k的兩邊。(你可以想象一下i和j是兩個機器人,數(shù)據(jù)就是大小不一的石頭,先取走i前面的石頭留出回旋的空間,然后他們輪流分別挑選比k大和比k小的石頭扔給對面,最后在他們中間把取走的那塊石頭放回去,于是比這塊石頭大的全扔給了j那一邊,小的全扔給了i那一邊。只是這次運氣好,扔完一次剛好排整齊。)為了得到最后結果,需要再次對下標2兩邊的數(shù)組分別執(zhí)行此步驟,然后再分解數(shù)組,直到數(shù)組不能再分解為止(只有一個數(shù)據(jù)),才能得到正確結果。

python實現(xiàn)代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
    s.append(random.randint(1,100))
    print(s[i]),
#
print("\nbegin")
def partition(inlist,start,end):
    i = start
    j = end
    k = inlist[i]
    while i<j:
        while i<j and inlist[j]>=k:
            j = j-1
        inlist[i]=inlist[j]
        while i<j and inlist[i]<=k:
            i = i+1
        inlist[j]=inlist[i]
    inlist[i]=k
    return i

def quickSort(inlist,start,end):
    if start>=end:
        return
    middle = partition(inlist,start,end)
    quickSort(inlist,start,middle-1)
    quickSort(inlist,middle+1,end)

quickSort(s,0,len(s)-1)
for i in s:
    print "%d " %i,
print("done")

2:直接插入排序

思想:

每次從無序表中取出第一個元素,把它插入到有序表的合適位置,使有序表仍然有序。

第一趟比較前兩個數(shù),然后把第二個數(shù)按大小插入到有序表中; 第二趟把第三個數(shù)據(jù)與前兩個數(shù)從前向后掃描,把第三個數(shù)按大小插入到有序表中;依次進行下去,進行了(n-1)趟掃描以后就完成了整個排序過程。

python 代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
    s.append(random.randint(1,100))
    print(s[i]),
#
print("\nbegin")

j=0
for i in range(1,len(s)):
    if s[i]<s[i-1]:
        temp = s[i]
        j=i-1
        while j>=0 and s[j]>temp:
            s[j+1]=s[j]
            s[j]=temp
            j=j-1
for i in s:
    print "%d " %i,
print("\ndone")

3:冒泡排序

思想:

  • 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。

  • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。在這一點,最后的元素應該會是最大的數(shù)。

  • 針對所有的元素重復以上的步驟,除了最后一個。

  • 持續(xù)每次對越來越少的元素重復上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。

python 代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
    s.append(random.randint(1,100))
    print(s[i]),
#
print("\nbegin")

i = len(s)-1
while i>0:
    j=0
    for j in range(0,i):
        if s[j+1]<s[j]:
            temp = s[j]
            s[j]=s[j+1]
            s[j+1]=temp
            j = j+1
    i = i-1
for i in s:
    print "%d " %i,
print("\ndone")

4:桶排序

思想:

假定:輸入是由一個隨機過程產(chǎn)生的[0, 1)區(qū)間上均勻分布的實數(shù)。將區(qū)間[0, 1)劃分為n個大小相等的子區(qū)間(桶),每桶大小1/n:[0, 1/n), [1/n, 2/n), [2/n, 3/n),…,[k/n, (k+1)/n ),…將n個輸入元素分配到這些桶中,對桶中元素進行排序,然后依次連接桶輸入0 ≤A[1..n] <1輔助數(shù)組B[0..n-1]是一指針數(shù)組,指向桶(鏈表)。

太難懂了,舉個簡單的例子:

一年的全國高考考生人數(shù)為500 萬,分數(shù)使用標準分,最低100 ,最高900 ,沒有小數(shù),你把這500 萬元素的數(shù)組排個序。

我們發(fā)現(xiàn),這些數(shù)據(jù)都有特殊的條件: 100=<score<=900。那么我們就可以考慮桶排序這樣一個“投機取巧”的辦法、讓其在毫秒級別就完成500萬排序。

方法:創(chuàng)建801(900-100)個桶。將每個考生的分數(shù)丟進f(score)=score-100的桶中。這個過程從頭到尾遍歷一遍數(shù)據(jù)只需要500W次。然后根據(jù)桶號大小依次將桶中數(shù)值輸出,即可以得到一個有序的序列。而且可以很容易的得到100分有***人,501分有***人。

python代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
#10000 numbers,range in (0,100)
s = []
for i in range(0,10000):
    s.append(random.randint(0,100))
    #print(s[i]),
#
print("\nbegin")
r = {}
for i in range(0,101):
    r[i]=[]
for i in s:
    r[i].append(i)
f = file("r.txt","w")
for i in range(0,101):
    for j in r[i]:
        f.write(str(j)+',')
print("\ndone")

 5:歸并排序

思想:

歸并(Merge)排序法是將兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序序列分為若干個有序的子序列,再把有序的子序列合并為整體有序序列。

python代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
for i in range(0,100):
    s.append(random.randint(1,100))
    print(s[i]),print("\nbegin")

def spli(inlist):
    if len(inlist)<=1:
        return inlist
    num = len(inlist)/2
    left = spli(inlist[0:num])
    right = spli(inlist[num:])
    return sor(left,right)
def sor(left,right):
    #print(left)
    #print(right)
    l = 0
    r = 0
    result =[]
    while l<len(left) and r <len(right):
        if left[l]<right[r]:
            result.append(left[l])
            l =l+1
        else:
            result.append(right[r])
            r = r+1
    result = result+right[r:]
    result = result+left[l:]
    return result
s=spli(s)
for i in s:
    print "%d " %i,
print("\ndone")

6:堆排序

思想:

1.什么是堆?

  堆實際上是一棵完全二叉樹,其任何一非葉節(jié)點滿足性質(zhì):

  Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

  即任何一非葉節(jié)點的關鍵字不大于或者不小于其左右孩子節(jié)點的關鍵字。

  堆分為大頂堆和小頂堆,滿足Key[i]>=Key[2i+1]&&key>=key[2i+2]稱為大頂堆,滿足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]稱為小頂堆。由上述性質(zhì)可知大頂堆的堆頂?shù)年P鍵字肯定是所有關鍵字中最大的,小頂堆的堆頂?shù)年P鍵字是所有關鍵字中最小的。

2.堆排序的思想

   利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。

    其基本思想為(大頂堆):

    1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆為初始的無序區(qū);

    2)將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(qū)(R1,R2,......Rn-1)和新的有序區(qū)(Rn),且滿足R[1,2...n-1]<=R[n]; 

    3)由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對當前無序區(qū)(R1,R2,......Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個元素交換,得到新的無序區(qū)(R1,R2....Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復此過程直到有序區(qū)的元素個數(shù)為n-1,則整個排序過程完成。

    操作過程如下:

     1)初始化堆:將R[1..n]構造為堆;

     2)將當前無序區(qū)的堆頂元素R[1]同該區(qū)間的最后一個記錄交換,然后將新的無序區(qū)調(diào)整為新的堆。

python 代碼:

#*-* coding: utf-8 *-*
import random
# produce random numbers to be sorted
s = []
count=0
for i in range(0,100):
    s.append(random.randint(1,100))
    print(s[i]),
#
print("\nbegin")
def heap_sort(inlist):
    for start in range((len(inlist)-2)/2,-1,-1):#1:初始化堆:從最底層開始建樹,并且保證是堆
        sift_down(inlist,start,len(inlist)-1)
    for end in range(len(inlist)-1,0,-1):#2:將堆頂元素與最后一個元素交換,調(diào)整
        inlist[0],inlist[end]=inlist[end],inlist[0]
        sift_down(inlist,0,end-1)
    return inlist

def sift_down(inlist,start,end):
    """調(diào)整算法:從父節(jié)點、左孩子節(jié)點、右孩子節(jié)點三者中選擇最大者跟父節(jié)點進行交換
        (交換之后可能造成被交換的孩子節(jié)點不滿足堆的性質(zhì),
        因此每次交換之后要重新對被交換的孩子節(jié)點進行調(diào)整)"""
    root = start
    while True:
        global count
        count=count+1
        child = 2*root +1#左節(jié)點
        if child>end:
            break
        if child+1<=end and inlist[child]<inlist[child+1]:#左節(jié)點比右節(jié)點小
            child = child+1#保證child對應的是左右節(jié)點中最大的
        if inlist[root]<inlist[child]:#如果root不是最大,交換
            inlist[root],inlist[child]=inlist[child],inlist[root]
            root=child
        else:
            break
heap_sort(s)
for i in s:
    print (i),
print("\ndone")
print(count)

6種算法比較次數(shù)的比較

隨機生成10000的數(shù)據(jù)

  QQ截圖20161111165430.png

 很容易可以看出:

1:桶排序是最快的,但使用范圍有限,排序的標準和數(shù)據(jù)的屬性是一致的

2:快速排序、歸并排序和堆排序都是NlogN的,但具體還是差別的,隨機數(shù)據(jù)來看,比較次數(shù):歸并《堆《快速

有序序列的影響:

快速排序:有序》》》》(遠大于)無序

直接插入:有序《無序

冒泡:有序《無序

桶排序:無差別

歸并:有序《無序

堆排序:有序》無序


Release Notes

Popular Entries