直接插入排序是指將r[i]~r[n]插入到已經有序的r[1]~r[i-1]序列中。r[0]是乙個哨兵,起到作為邊界條件並作為暫存單元的作用。
實際上,一切為簡化邊界條件而引入的附加節點(元素)均可稱為哨兵。例如單鏈表中的頭結點。
對於有n個記錄的集合,要進行n-1趟排序。
其最優時間複雜度是o(n),平均時間複雜度是o(n*n)。當檔案初始有序的狀態和排序的要求一致時可以達到最優時間複雜度。
**片段如下:
/*****************************************
*****************插入排序*****************
*****************************************/
void insert_sort(vector&v)
v[j + 1] = v[0]; //插入
}}
希爾排序是將待排記錄進行分組。首先設定乙個增量d,然後將增量為d的元素分為一組。對於每一組中的元素,對它們進行直接插入排序。
當增量k=1時,希爾排序和直接插入基本一致,只是在希爾排序中沒有設定哨兵而需要判斷陣列下標是否為負越界。
希爾排序的時間和增量的選取有關,好的增量應該有如下特性:
(1)最後乙個增量必須為1.
(2)應盡量避免序列中的值互為倍數(尤其是相鄰的值)的情況。
希爾排序的時間效能優於直接插入排序:
(1)當檔案初態基本有序時,直接插入排序所需的比較和移動次數均較少。
(2)當n值較小時,n和n*n的差別也較小,即直接插入排序的最優時間複雜度和最壞時間複雜度差別不大。
(3)在希爾排序開始時的增量較大,分組較多,每組中的記錄少,故各組內直接插入排序較快;
後來增量d(i)逐漸減小,分組數也逐漸減小,各組中的記錄數逐漸增多,但由於已經以d(i-1)作為距離排過序,使檔案接近有序狀態,所以新的一趟排序也較快。
所以希爾排序在效率上相對於直接插入排序有很大的改進。
希爾排序是不穩定的。
其平均時間複雜度是o(n的1.3次方)
**片段如下(r[0]不是哨兵,它只是乙個暫存單元):
/*****************************************
*****************希爾排序*****************
*****************************************/
void shell_pass(vector&v, int d)
while (j>0 && v[0]&v)
while (increment > 1);
}
氣泡排序的過程與「氣泡從水底往上公升的過程非常類似」。從最後乙個記錄開始,依次向前比較相鄰的兩個記錄,當不滿足排序要求時交換這兩個記錄。
第一趟排序是對r[n]~r[1]進行冒泡;第二趟排序是對r[n-1]~r[1]進行冒泡;...;最後一趟排序是對r[2]~r[1]進行冒泡。
對於有n個記錄的集合,需要進行n-1趟排序。
其平均時間複雜度是o(n*n)。
**片段如下(r[0]不是哨兵,它只是乙個暫存單元):
/*****************************************
*****************氣泡排序*****************
*****************************************/
void bubble_sort(vector&v)
} if (exchange == 0)
exchange = 0;
}}
快速排序主要分為3步:
(1)分解
對於待排區間r[low]~r[high],任選其中的乙個記錄作為基準pivot。
對當前區間進行排序,使得pivot左邊的記錄都小於基準r[pivot];pivot右邊的記錄都大於基準r[pivot]。
該過程的主要做法是(以公升序排枚舉例):
分別設定兩個指標i和j指向low和high。
首先比較r[j]和r[pivot],找到第乙個小於r[pivot]的r[j],然後將r[i]的值設定成r[j],i的值加一;如果沒找到則進行j--,直到找到為止(這一過程i的值不變)。
然後比較r[i]和r[pivot],找到第乙個大於r[pivot]的r[i],然後將r[j]的值設定成r[i],j的值減一;如果沒找到則進行i++,直到找到為止(這一過程j的值不變)。
上述過程要滿足i小於j。
重複進行上述過程直到i和j相等,此時的位置i即為基準應該插入的位置。
(2)求解
通過遞迴呼叫快速排序演算法,對左區間r[low]~r[pivot-1]和右區間r[pivot+1]~r[high]進行快速排序。
(3)組合
這個操作不需要再做什麼,因為「求解」步驟中的兩個遞迴呼叫結束時,其左右兩個區間已經有序。
快速排序的最壞時間複雜度是o(n*n),此時每次選取的基準都是當前無序區內的最小或最大記錄;最好時間複雜度是o(n*(log以2為底n的對數)),此時每次劃分選取的基準都是當前無序區的「中值」記錄。
快速排序在系統內部需要乙個棧來實現遞迴,若每次的劃分較為均勻,則其遞迴樹的高度為o(log以2為底n的對數),故遞迴後需要棧空間為o(log以2為底n的對數)。最壞情況下遞迴樹的高度為o(n),所需的棧空間為o(n)。
快速排序不是穩定的。
快速排序中基準的選取:
(1)三者取中法。在最低、中間、最高位置的記錄中取其中的中值記錄。
(2)取low和high中乙個隨機位置k上的記錄作為基準,這相當於強制low和high之間的記錄是隨機分布的。——隨機的快速排序。
劃分前將基準與該區間第乙個記錄進行交換。
**片段如下:
/*****************************************
*****************快速排序*****************
*****************************************/
int partition(vector&v, int i, int j)
if (i < j)
while (i < j && pivot > v[i])
if (i < j)
} v[i] = pivot;
return i;
}void quick_sort(vector&v, int low, int high)
}
直接選擇排序是指在每一趟排序中,從當前的無序區中選出最小或最大的那個記錄。
對於有n個記錄的集合需要n-1趟排序。
直接選擇排序是不穩定的。
其平均時間複雜度為o(n*n)。
直接選擇排序是就地排序。
**片段如下:
/*****************************************
*****************選擇排序*****************
*****************************************/
void select_sort(vector&v)
if (troot < v[j])
else
v[i] = tmp; }}
void build_heap(vector& v)
}void heap_sort(vector& v)
}
資料結構 排序演算法
include include define maxitem 100 typedef char keytype 5 typedef int elemtype typedef struct rec elemnode maxitem 氣泡排序演算法 void bubblesort elemnode r,...
資料結構 排序演算法
排序演算法分為內部排序和外部排序兩大類。內部排序 在計算機記憶體中完成的排序演算法 外部排序 不能再記憶體中文完成,必須在磁碟或者磁帶上完成的排序演算法 內部排序是研究的重點問題,通常我們講的八大排序演算法也主要是講的內部排序演算法。排序演算法的穩定性和時間空間複雜度 本文重點介紹以下幾種排序演算法...
資料結構排序演算法
include using namespace std 輸入一組關鍵字序列分別實現下列排序 1.實現簡單選擇排序 直接插入排序和氣泡排序。2.實現希爾排序演算法。3.實現快速排序演算法。4.實現堆排序演算法。define maxsize 100 using namespace std typedef...