基本排序演算法總結

2021-08-30 07:42:20 字數 3055 閱讀 3806

排序演算法的評價

評價排序演算法的一般準則是:

▶ 平均情況下的排序速度

▶ 最優最劣情況下的速度

▶ 行為是否自然

▶ 是否以相等的關鍵字重排元素

陣列的排序速度直接與比較(comparison)次數和交換(exchange)次數相關,其中交換的作用更大,因為占用的時間多。

如果頻繁遭遇到最優最劣情況,則最優和最劣情況下的執行時間是重要的。

所謂自然(natural)行為的排序應該是,對已排序的表操作最容易,對失序越重的表操作越困難。

通常,如果有相等關鍵字的元素在排序前後,之間的相對位置並不改變,我們稱之為該排序是穩定的。

氣泡排序(bubble sort)

最著名(也最聲名狼藉)的排序是氣泡排序。

void bubble_sort(char *items, int count)

}

}

}

分析:

兩個 for 迴圈重複了比較的次數,所以比較的次數是恆定的:1 / 2(n平方 - n)

其中,外部迴圈執行 n - 1 次,內部迴圈執行 n/2 次,兩式相乘得到以上公式。

下面是氣泡排序的動畫演示:

氣泡排序動畫演示

選擇排序(selection sort)

選擇排序中,先選擇最小的元素並將其與第乙個元素進行交換。然後剩餘的 n - 1 個元素中選擇最小值者並與第二個元素交換等,如此直到最後兩個元素。

void select_sort(char *items, int count)

}

if(exchange)

}

}

分析:

和氣泡演算法一樣,選擇排序需要進行的比較次數同樣為 1/2 (n平方 - n) 。儘管如此,但在平均情況下,選擇排序的交換次數要少得多。

下面是選擇排序的動畫演示:

選擇排序動畫演示

插入排序(insertion sort)

插入排序中,先對前兩個元素進行排序,然後把第三個元素按序插入到已排好序的前兩個元素中。隨後是第四個插入到已排好序的前三個元素中,以此類推,直到所有元素都有序為止。

void insert_sort(char *items, int count)

items[j+1] = t;

}

}

分析:

與氣泡排序和選擇排序不同的是,插入排序的比較次數與被排表的初始排列有關。如果表是完全有序的,比較 n - 1 次,否則按 n 平方次進行。

因此,最劣情況下,與 氣泡排序和選擇排序一樣差,平均情況稍好一點。然而這種辦法的確有兩個優點:

1. 排序是自然的,即表已排序時工作量最少,反序時工作量最大。這樣,對基本已排序的表操作時,插入排序是最理想的。

2. 排序是穩定的,即相同關鍵字元素的相對位置,排序前後保持不變。

下面是插入排序的動畫演示:

插入排序動畫演示

前面幾個演算法,執行時間都是 n 平方級的,對於大量資料而言,排序速度非常慢,有時會完全不實用。

下面是兩個較快的演算法

希爾排序(shell sort)

希爾排序是根據其發明者的名字(d.l.shell)命名的。其一般方法是從插入排序匯出並基於增量減少 (diminishing increments)。例如,首先,對間隔三個位置的元素排序;然後,再對間隔兩個位置的元素排序;最後,對相鄰元素進行排序。

排序的每一遍涉及相對較少的元素或已恰當排序的元素。因此,希爾排序是高效的,每一遍都提高了有序性。

增量的準確序列可以變化,唯一規則是最後增量必須為 1 。例如:9 ,5, 3, 2, 1 。以 2 的冪為增量值的序列是不可取的,出於複雜的數學原理,這種序列降低了排序演算法的效率。

void shell_sort(char *items, int count)

items[j+gap] = t;

}

}

}

分析:

希爾排序的執行與 n 的1.2 次方 成比例,相對於 n 平方排序而言,這是重大改進。

下面是希爾排序動畫演示:

希爾排序動畫演示

快速排序(quick sort)

快速排序是又 c.a.r.hoare 發明的,一般被認為是目前最好的通用排序演算法。快速排序基於交換排序,與同樣基於交換排序的 氣泡排序相比,其效果是驚人的。

快速排序的基本思想是分割槽(partition)。一般過程是先選乙個比較數(comparand)的值,然後把陣列分成兩段。大於等於分割槽值的元素都放在一邊,小於分割槽值的元素放在另一邊。然後對陣列的另一段重複上述過程,直到該陣列完成排序。

排序的過程本質上遞迴的,而實際上,快速排序的最清晰實現就是遞迴演算法。

選擇比較數值的辦法有兩個,可以隨機選取也可以選取陣列中一組值求平均值得到。

void quick_sort(char *items, int count)

void qs(char *items, int left, int right)

}while(i <= j);

if(left < j)

qs(items, left, j);

if(i < right)

qs(items, i, right);

}

分析:

快速排序的平均比較次數為 n log n ,近似交換次數 n/6 log n 。這兩個數值遠小於前面各種排序的相應引數。

需要注意的乙個問題是,如果每個分割槽的比較數值選擇了最大值,快速排序退化成 n 平方操作時間的排序。

歸併排序(merge sort)(zz) 。

與歸併排序不同的是, 最劣情況下,快速排序的的時間複雜度為 n 平方,而歸併排序則是 nlogn 。

這裡的這個演算法寫的不夠清晰,請參看

尋找第k小的數 與 快速排序

基本排序演算法總結

1.插入排序 insertion sort o n2 對少量資料排序很有效,不需要額外的儲存空間。待排序列已經是從小到大,最壞就是逆序的時候了。且是穩定的。include include int exchange int a,int i,int j int insert int a,int s,in...

基本排序演算法總結

排序演算法很多,這裡做個總結,最重要的是記住演算法思想,而不是記住程式怎麼寫。程式過一段時間就會忘了,演算法原理熟悉了現場寫出來應該是很容易的。時間複雜度為o n 2 的三種排序演算法 插入排序 選擇排序 氣泡排序。插入排序 插入排序是選定元素找位置。對於位置為p上的元素,假定0 p 1的元素已經排...

基本排序演算法總結

參考部落格 傳送門 目錄 各排序時間複雜度 氣泡排序 選擇排序 插入排序 希爾演算法 堆排序 氣泡排序 比較相鄰的元素。如果第乙個比第二個大,就交換他們兩個。對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。針對所有的元素重複以上的步驟,除了最後乙個。...