穩定排序:排序前後相同key值的元素之間的位置關係保持不變。
非穩定排序:排序前後相同key值的元素之間的位置關係可能發生變化。
內排序:待排序的序列完全放在記憶體中進行排序,適合不太大的元素序列。
外排序:排序過程中序列存放在外儲存器,需要訪問外儲存器獲得序列資料。
在本文中,預設的是公升序排序。
思想:兩兩比較元素的key值,如果是逆序則交換元素位置,直到全部元素都排好序。
主要有氣泡排序(bubble sort)和快排(quick sort)
演算法流程
1. 第1趟排序,從r[1]到r[n],兩兩比較,如果逆序,交換兩個元素的位置,最後最大的元素會到達r[n]
2. 第2趟排序,從r[1]到r[n-1],兩兩比較,如果逆序,交換兩個元素的位置,最後次大的元素會到達r[n-1]
3. 直到有序元素個數已經為n-1,一般要執行n-1趟,但是如果某一趟過程中沒有發生任何交換,表明序列已經是有序的,排序演算法可以提前終止。
時間複雜度
最好:序列已經有序,不需移動
最差:每次比較之後都要發生交換
平均:o(n2
n 2)
空間複雜度
只需乙個輔助單元
穩定性
是穩定排序
**
void bubble_sort(int nums, int n)
}if (!exchange)//當某一趟過程中完全沒有交換時,序列已經是有序的,可以提前終止迴圈
}}
基本思想
以某個元素為界(稱為支點),將序列分成兩部分,一部分元素的key值小於等於支點key值,另一部分元素的key值大於支點key值,這個過程稱為一次劃分,劃分之後再在兩部分分別劃分,直到整個序列有序。
演算法流程
一次劃分的流程:
1. 設定left和right,分別代表序列第乙個和最後乙個元素,支點的key值記為pivotkey
2. 從right往左搜尋,找到第乙個key值比pivotkey小的元素,和支點元素交換位置
3. 然後從left往右搜尋,找到第乙個key值比pivotkey大的元素,和支點元素交換位置
4. 依次重複以上步驟,直到left=right
快排流程:
1. 對整個序列進行依次劃分,將序列分成兩部分,一部分的key值小於支點的key值,另一部分的key值大於支點key值
2. 對這兩部分分別再進行劃分,分別得到兩個部分
3. 一直執行,直到整個序列有序
時間複雜度
最好:理想情況下每次劃分得到兩個等長子序列,時間複雜度為o(nlog(n))
最差:每次劃分後只能得到乙個子串行,複雜度為o(n2
n 2)
當初始序列有序或基本有序時,快排會退化成氣泡排序,應對辦法是採用「三者取中法」來得到支點,即取首尾以及中間3個元素中key值居中的元素作為支點。
平均:o(n2
n 2)
空間複雜度
快排是遞迴地,每層呼叫都要用棧來存放呼叫引數和指標,遞迴呼叫層次數與二叉樹深度一致,因此理想情況下輔助空間為o(log(n)),即數的高度,最壞情況下得到乙個單鏈數,此時空間複雜度為o(n)。
穩定性
是不穩定排序
**
void quick_sort(int nums, int n,int
left,int
right)
}int partion(int nums, int n, int
left, int
right)
if (i < j)
while (iif (i < j)
}return i;
}
基本插入排序的思想是把未排序元素逐一插入到序列有序部分對應的位置,直到整個序列有序為止。
演算法流程
1. 從序列第1個元素開始
2. 該元素向前比較,遇到比該元素大的,交換位置,遇到與該元素小的或者相等的,停止,或者達到序列第0個位置時終止。
3. 直到整個序列最後乙個元素。
時間複雜度
最壞:序列剛好完全倒序,複雜度o(
n2) o(n
2)
最好:序列剛好有序,複雜度o(
n)o (n
)平均:o(
n2) o(n
2)
空間複雜度
僅用乙個輔助單元,空間複雜度o(
1)o (1
)穩定性
是穩定排序
適用性
插入排序適合待排序序列部分有序或接近有序
易實現,當n很小時,是一種很好的排序方法,當n很大時,時間效能不好
**
void base_insertion_sort(int nums, int n)
else
j--;}}
}
二分插入排序與基本插入排序的區別是在尋找每個待插入元素的插入位置時的方法不一樣,二分插入排序在搜尋插入位置時採用的是二分比較的方式。
演算法流程
1. 從序列第1個元素開始,i=1…n-1
2. low=0,high=i-1,標定有序區間,若low>high,則得到插入位置,轉5
3. low<=high,mid=(low+high)/2
4. 如果nums[mid]<=nums[i],low=mid+1
如果nums[mid]>nums[i],high=mid-1
轉2 5. 得到插入位置high+1,nums[high+1]到high[i-1]的元素全部後移,令nums[high+1]=nums[i]
時間複雜度 仍為o
(n2)
o (n
2)
穩定性
是穩定排序
**
void binary_insertion_sort(int nums, int n)
else
}temp = nums[i];
for (j = i; j >high+1; j--)
nums[high + 1] = temp;
}}
思想
因為插入排序在序列接近有序時效率比較高,所以想法是設定乙個遞減的步長序列,按步長進行直接插入排序,使待排序序列逐漸接近有序。
演算法流程
1. 設定乙個遞減的步長序列,t1
,t2,
...t
k,ti
,i,tk=
1 t1,
t2,.
..tk
,t
i ,i ,tk= 12. 按照步長序列進行k趟直接插入排序,每趟排序是按照步長ti t i將序列分成t_i個子序列,分別對子序列進行直接插入排序。例如第乙個子串行是nums[0],nums[ti],nums[2ti]…第2個子序列是nums[1],nums[ti+1],nums[2ti+1]… 3. 當進行到最後一趟,步長為1時,就是對整個序列進行直接插入排序,此時由於整個序列已經接近有序,直接插入排序的效率會高很多。 時間複雜度 介於o (n1.25 ) o(n 1.25 )到o( n1.65 ) o(n 1.65)之間 ** } while (increment > 1); }void insertion_sort_interval(int nums, int n,int start,int increment) else j-=increment;}} } include include define maxitem 100 typedef char keytype 5 typedef int elemtype typedef struct rec elemnode maxitem 氣泡排序演算法 void bubblesort elemnode r,... 排序演算法分為內部排序和外部排序兩大類。內部排序 在計算機記憶體中完成的排序演算法 外部排序 不能再記憶體中文完成,必須在磁碟或者磁帶上完成的排序演算法 內部排序是研究的重點問題,通常我們講的八大排序演算法也主要是講的內部排序演算法。排序演算法的穩定性和時間空間複雜度 本文重點介紹以下幾種排序演算法... 直接插入排序是指將r i r n 插入到已經有序的r 1 r i 1 序列中。r 0 是乙個哨兵,起到作為邊界條件並作為暫存單元的作用。實際上,一切為簡化邊界條件而引入的附加節點 元素 均可稱為哨兵。例如單鏈表中的頭結點。對於有n個記錄的集合,要進行n 1趟排序。其最優時間複雜度是o n 平均時間複...void shell_sort(int nums, int n)
資料結構 排序演算法
資料結構 排序演算法
資料結構 排序演算法