算法(10):排序

??偶然間發(fā)現(xiàn)了自己以前寫的十種排序算法的代碼折欠,現(xiàn)粘貼上來醇蝴,方便自己日后查閱~ (里面還附贈了A^n_nA^m_n的實現(xiàn)方法)



小伙子我心腸好诈火,再送倆非遞歸實現(xiàn)~

快速排序的非遞歸實現(xiàn)
歸并排序的非遞歸實現(xiàn)


#python3
'''
插入排序:插入排序的基本操作就是將一個數(shù)據(jù)插入到已經(jīng)排好序的有序數(shù)據(jù)中昼钻,從而得到一個新的魔种、個數(shù)加一的有序數(shù)據(jù)析二,
算法適用于少量數(shù)據(jù)的排序;首先將第一個作為已經(jīng)排好序的节预,然后每次從后的取出插入到前面并排序叶摄;
'''
def insert_sort(ilist):
    for i in range(len(ilist)):
        for j in range(i):
            if ilist[i] < ilist[j]:
                # ilist[i], ilist[j] = ilist[j], ilist[i]
                ilist.insert(j, ilist.pop(i))
                break
    return ilist


'''
希爾排序是第一個突破O(n^2)的排序算法;是簡單插入排序的改進版安拟;是把記錄按下標(biāo)的一定增量分組蛤吓,
對每組使用直接插入排序算法排序;隨著增量逐漸減少糠赦,每組包含的關(guān)鍵詞越來越多会傲,當(dāng)增量減至1時,
整個文件恰被分成一組拙泽,算法便終止
'''
def shell_sort(ilist):
    gap=len(ilist)
    while gap>1:
        gap=gap//2
        for i in range(gap,len(ilist)):
            for j in range(i%gap,i,gap):
                if ilist[i]<ilist[j]:
                    ilist[i],ilist[j]=ilist[j],ilist[i]
    return ilist


'''
冒泡排序:它重復(fù)地走訪過要排序的數(shù)列淌山,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來顾瞻。
走訪數(shù)列的工作是重復(fù)地進行直到?jīng)]有再需要交換泼疑,也就是說該數(shù)列已經(jīng)排序完成
'''
def bubble_sort(ilist):
    flag=len(ilist)-1
    for i in range(len(ilist)):
        for j in range(flag):
            if ilist[j]>ilist[j+1]:
                flag=j
                ilist[j], ilist[j+1] = ilist[j+1], ilist[j]
    return ilist


'''
快速排序:通過一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨立的兩部分,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小荷荤,
然后再按此方法對這兩部分?jǐn)?shù)據(jù)分別進行快速排序退渗,整個排序過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列
'''
def quick_sort(ilist):
    if ilist==[]:
        return []

    qfirst=ilist[0]
    qsmall=quick_sort([s for s in ilist[1:] if s < qfirst])
    qlarge=quick_sort([l for l in ilist[1:] if l >=qfirst])

    return qsmall +[qfirst] +qlarge

'''
選擇排序:第1趟梅猿,在待排序記錄r1 ~ r[n]中選出最小的記錄氓辣,將它與r1交換;第2趟袱蚓,在待排序記錄r2 ~ r[n]中選出最小的記錄,
將它與r2交換几蜻;以此類推喇潘,第i趟在待排序記錄r[i] ~ r[n]中選出最小的記錄体斩,將它與r[i]交換,使有序序列不斷增長直到全部排序完畢
'''
def select_sort(ilist):
    for i in range(len(ilist)):
        a=i
        for j in range(i+1,len(ilist)):
            if ilist[j]<ilist[a]:
                a=j
        ilist[i],ilist[a]=ilist[a],ilist[i]
    return ilist


'''
歸并排序:采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用颖低。將已有序的子序列合并絮吵,得到完全有序的序列;
即先使每個子序列有序忱屑,再使子序列段間有序蹬敲。若將兩個有序表合并成一個有序表,稱為二路歸并
'''
def merge_sort(ilist):
    def recursive(ilist):
        if len(ilist)==1:
            return ilist
        mid=len(ilist)//2
        left=recursive(ilist[:mid])
        right=recursive(ilist[mid:])
        return merge(left,right)

    def merge(left,right):
        ans=[]
        while len(left) and len(right):
            if left[0]<= right[0]:
                ans.append(left.pop(0))
            else:
                ans.append(right.pop(0))
        ans.extend(left)
        ans.extend(right)
        return ans

    return recursive(ilist)


'''
基數(shù)排序是按照低位先排序莺戒,然后收集伴嗡;再按照高位排序,然后再收集从铲;依次類推瘪校,直到最高位。有時候有些屬性是有優(yōu)先級順序的名段,
先按低優(yōu)先級排序阱扬,再按高優(yōu)先級排序。最后的次序就是高優(yōu)先級高的在前伸辟,高優(yōu)先級相同的低優(yōu)先級高的在前麻惶。
基數(shù)排序基于分別排序,分別收集信夫,所以是穩(wěn)定的用踩。
'''
def radix_sort(ilist):
    bucket,digit=[[]],0
    while len(bucket[0])!=len(ilist):
        bucket=[[] for x in range(10)]
        for i in ilist:
            num=(i//10**digit)%10
            bucket[num].append(i)
        ilist=[a for b in bucket for a in b]
        digit+=1
    return ilist


'''
計數(shù)排序(Counting sort)是一種穩(wěn)定的排序算法。計數(shù)排序使用一個額外的數(shù)組C忙迁,其中第i個元素是待排序數(shù)組A中值等于i的元素的個數(shù)脐彩。
然后根據(jù)數(shù)組C來將A中的元素排到正確的位置。它只能對整數(shù)進行排序姊扔。
'''
def counting_sort(ilist):
    n = len(ilist)
    b = [0 for i in range(n)]
    c = [0 for i in range(max(ilist)+1)]
    for j in ilist:
        c[j] = c[j] + 1
    for i in range(1, len(c)):
        c[i] = c[i] + c[i-1]
    for j in ilist:
        b[c[j] - 1] = j
        c[j] = c[j] - 1
    return b


'''
桶排序 (Bucket sort)的工作的原理:假設(shè)輸入數(shù)據(jù)服從均勻分布惠奸,將數(shù)據(jù)分到有限數(shù)量的桶里,每個桶再分別排序
(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進行排序)
桶劃分的越小恰梢,各個桶之間的數(shù)據(jù)越少佛南,排序所用的時間也會越少。但相應(yīng)的空間消耗就會增大嵌言。
該例子中嗅回,設(shè)置桶的數(shù)量為(max(ilist) - min(ilist)) + 1),跟計數(shù)排序很像
'''
def bucket_sort(ilist):
    buckets = [0] * ((max(ilist) - min(ilist)) + 1)  # 初始化桶元素為0
    for i in range(len(ilist)):
        buckets[ilist[i] - min(ilist)] += 1  # 遍歷數(shù)組a摧茴,在桶的相應(yīng)位置累加值
    b = []
    for i in range(len(buckets)):
        if buckets[i] != 0:
            b += [i + min(ilist)] * buckets[i]
    return b


'''
堆排序:它是選擇排序的一種绵载。可以利用數(shù)組的特點快速定位指定索引的元素。堆分為大根堆和小根堆娃豹,是完全二叉樹焚虱。
大根堆的要求是每個節(jié)點的值都不大于其父節(jié)點的值,即A[PARENT[i]] >= A[i]懂版。在數(shù)組的非降序排序中鹃栽,
需要使用的就是大根堆,因為根據(jù)大根堆的要求可知躯畴,最大的值一定在堆頂
lchild=parent*2+1 rchild=parent*2+2
'''
def heap_sort(ilist):
    def heap_adjust(parent):
        child=parent*2+1
        while child<len(heap):
            if child +1<len(heap):
                if heap[child +1]>heap[child]:
                    child=child+1
            if heap[parent]>=heap[child]:
                break
            heap[parent],heap[child]=heap[child],heap[parent]
            parent, child = child, 2 * child + 1

    heap, ilist = ilist.copy(), []
    for i in range(len(heap)//2,-1,-1):
        heap_adjust(i)
    while len(heap)!=0:
        heap[0],heap[-1]=heap[-1],heap[0]
        ilist.insert(0,heap.pop())
        heap_adjust(0)
    return ilist

#Ann = n!
def Ann(arr):
    def first(ans,arr):
        if len(arr)==0:
            return print(ans)
        arr_t=arr.copy()
        num=arr_t.pop(0)
        for i in range(len(ans)+1):
            temp=ans.copy()
            temp.insert(i,num)
            first(temp,arr_t)

    return first([],arr)

#Anm = n! / (n-m)!
#Cnm = n! / ( m! * (n-m)! )
def Cnm(lis,m,start=0):
    if m==0:
        for i in range(start-1):
            if lis[i]>lis[i+1]:   # 只取從小到大的那種排列方式民鼓,去掉這句就是Anm的實現(xiàn)
                break
        else:
            print(lis[:start])
            global count
            count += 1
        return 0

    for i in range(start,len(lis)):
        lis[start],lis[i]=lis[i],lis[start]
        Cnm(lis,m-1,start+1)
        lis[start], lis[i] = lis[i], lis[start]


if __name__=="__main__":
    # Ann(['a', 'b', 'c', 'd', 'e'])
    ilist=[4,5,6,7,3,2,6,9,8]
    print(bubble_sort(ilist))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蓬抄,隨后出現(xiàn)的幾起案子丰嘉,更是在濱河造成了極大的恐慌,老刑警劉巖倡鲸,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件供嚎,死亡現(xiàn)場離奇詭異,居然都是意外死亡峭状,警方通過查閱死者的電腦和手機克滴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來优床,“玉大人劝赔,你說我怎么就攤上這事〉ǔǎ” “怎么了着帽?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長移层。 經(jīng)常有香客問我仍翰,道長,這世上最難降的妖魔是什么观话? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任予借,我火速辦了婚禮,結(jié)果婚禮上频蛔,老公的妹妹穿的比我還像新娘灵迫。我一直安慰自己,他們只是感情好晦溪,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布瀑粥。 她就那樣靜靜地躺著,像睡著了一般三圆。 火紅的嫁衣襯著肌膚如雪狞换。 梳的紋絲不亂的頭發(fā)上避咆,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音哀澈,去河邊找鬼牌借。 笑死度气,一個胖子當(dāng)著我的面吹牛割按,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播磷籍,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼适荣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了院领?” 一聲冷哼從身側(cè)響起弛矛,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎比然,沒想到半個月后丈氓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡强法,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年万俗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饮怯。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡闰歪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蓖墅,到底是詐尸還是另有隱情库倘,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布论矾,位于F島的核電站教翩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贪壳。R本人自食惡果不足惜饱亿,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寥袭。 院中可真熱鬧路捧,春花似錦、人聲如沸传黄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膘掰。三九已至章姓,卻和暖如春佳遣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凡伊。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工零渐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人系忙。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓诵盼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親银还。 傳聞我的和親對象是個殘疾皇子风宁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354