天天看點

八大排序算法的 Python 實作

八大排序算法的 Python 實作

<a target="_blank"></a>

插入排序的基本操作就是将一個資料插入到已經排好序的有序資料中,進而得到一個新的、個數加一的有序資料,算法适用于少量資料的排序,時間複雜度為o(n^2)。是穩定的排序方法。插入算法把要排序的數組分成兩部分:第一部分包含了這個數組的所有元素,但将最後一個元素除外(讓數組多一個空間才有插入的位置),而第二部分就隻包含這一個元素(即待插入元素)。在第一部分排序完成後,再将這個最後元素插入到已排好序的第一部分中。

<code>def insert_sort(lists):</code>

<code># 插入排序</code>

<code>count = len(lists)</code>

<code>for i in range(1, count):</code>

<code>key = lists[i]</code>

<code>j = i - 1</code>

<code>while j &gt;= 0:</code>

<code>if lists[j] &gt; key:</code>

<code>lists[j + 1] = lists[j]</code>

<code>lists[j] = key</code>

<code>j -= 1</code>

<code>return lists</code>

希爾排序shell sort是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因dl.shell于1959年提出而得名。 希爾排序是把記錄按下标的一定增量分組,對每組使用直接插入排序算法排序;随着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,算法便終止。

<code>def shell_sort(lists):</code>

<code># 希爾排序</code>

<code>step = 2</code>

<code>group = count / step</code>

<code>while group &gt; 0:</code>

<code>for i in range(0, group):</code>

<code>j = i + group</code>

<code>while j &lt; count:</code>

<code>k = j - group</code>

<code>key = lists[j]</code>

<code>while k &gt;= 0:</code>

<code>if lists[k] &gt; key:</code>

<code>lists[k + group] = lists[k]</code>

<code>lists[k] = key</code>

<code>k -= group</code>

<code>j += group</code>

<code>group /= step</code>

它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。

<code>def bubble_sort(lists):</code>

<code># 冒泡排序</code>

<code>for i in range(0, count):</code>

<code>for j in range(i + 1, count):</code>

<code>if lists[i] &gt; lists[j]:</code>

<code>lists[i], lists[j] = lists[j], lists[i]</code>

通過一趟排序将要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分别進行快速排序,整個排序過程可以遞歸進行,以此達到整個資料變成有序序列。

<code>def quick_sort(lists, left, right):</code>

<code># 快速排序</code>

<code>if left &gt;= right:</code>

<code>key = lists[left]</code>

<code>low = left</code>

<code>high = right</code>

<code>while left &lt; right:</code>

<code>while left &lt; right and lists[right] &gt;= key:</code>

<code>right -= 1</code>

<code>lists[left] = lists[right]</code>

<code>while left &lt; right and lists[left] &lt;= key:</code>

<code>left += 1</code>

<code>lists[right] = lists[left]</code>

<code>lists[right] = key</code>

<code>quick_sort(lists, low, left - 1)</code>

<code>quick_sort(lists, left + 1, high)</code>

基本思想:第1趟,在待排序記錄r1 ~ r[n]中選出最小的記錄,将它與r1交換;第2趟,在待排序記錄r2 ~ r[n]中選出最小的記錄,将它與r2交換;以此類推,第i趟在待排序記錄r[i] ~ r[n]中選出最小的記錄,将它與r[i]交換,使有序序列不斷增長直到全部排序完畢。

<code>def select_sort(lists):</code>

<code># 選擇排序</code>

<code>min = i</code>

<code>if lists[min] &gt; lists[j]:</code>

<code>min = j</code>

<code>lists[min], lists[i] = lists[i], lists[min]</code>

堆排序heapsort是指利用堆積樹(堆)這種資料結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大于其父節點的值,即a[parent[i]] &gt;= a[i]。在數組的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。

<code># 調整堆</code>

<code>def adjust_heap(lists, i, size):</code>

<code>lchild = 2 * i + 1</code>

<code>rchild = 2 * i + 2</code>

<code>max = i</code>

<code>if i &lt; size / 2:</code>

<code>if lchild &lt; size and lists[lchild] &gt; lists[max]:</code>

<code>max = lchild</code>

<code>if rchild &lt; size and lists[rchild] &gt; lists[max]:</code>

<code>max = rchild</code>

<code>if max != i:</code>

<code>lists[max], lists[i] = lists[i], lists[max]</code>

<code>adjust_heap(lists, max, size)</code>

<code></code>

<code># 建立堆</code>

<code>def build_heap(lists, size):</code>

<code>for i in range(0, (size/2))[::-1]:</code>

<code>adjust_heap(lists, i, size)</code>

<code># 堆排序</code>

<code>def heap_sort(lists):</code>

<code>size = len(lists)</code>

<code>build_heap(lists, size)</code>

<code>for i in range(0, size)[::-1]:</code>

<code>lists[0], lists[i] = lists[i], lists[0]</code>

<code>adjust_heap(lists, 0, i)</code>

歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法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]。

<code>def merge(left, right):</code>

<code>i, j = 0, 0</code>

<code>result = []</code>

<code>while i &lt; len(left) and j &lt; len(right):</code>

<code>if left[i] &lt;= right[j]:</code>

<code>result.append(left[i])</code>

<code>i += 1</code>

<code>else:</code>

<code>result.append(right[j])</code>

<code>j += 1</code>

<code>result += left[i:]</code>

<code>result += right[j:]</code>

<code>return result</code>

<code>def merge_sort(lists):</code>

<code># 歸并排序</code>

<code>if len(lists) &lt;= 1:</code>

<code>num = len(lists) / 2</code>

<code>left = merge_sort(lists[:num])</code>

<code>right = merge_sort(lists[num:])</code>

<code>return merge(left, right)</code>

基數排序radix sort屬于“配置設定式排序”distribution sort,又稱“桶子法”bucket sort或bin sort,顧名思義,它是透過鍵值的部份資訊,将要排序的元素配置設定至某些“桶”中,藉以達到排序的作用,基數排序法是屬于穩定性的排序,其時間複雜度為o (nlog(r)m),其中r為所采取的基數,而m為堆數,在某些時候,基數排序法的效率高于其它的穩定性排序法。

<code>import math</code>

<code>def radix_sort(lists, radix=10):</code>

<code>k = int(math.ceil(math.log(max(lists), radix)))</code>

<code>bucket = [[] for i in range(radix)]</code>

<code>for i in range(1, k+1):</code>

<code>for j in lists:</code>

<code>bucket[j/(radix**(i-1)) % (radix**i)].append(j)</code>

<code>del lists[:]</code>

<code>for z in bucket:</code>

<code>lists += z</code>

<code>del z[:]</code>

<code> </code>

<code>return lists本文來自雲栖社群合作夥伴“linux中國”,原文釋出日期:2015-10-03</code>