下列所有排序都默認是升序,從小到大。
插入排序
有一個已經有序的數據序列,要求在這個已經排好的數據序列中插入一個數,但要求插入後此數據序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,算法適用於少量數據的排序,時間複雜度爲O(n^2)。是穩定的排序方法。插入算法把要排序的數組分成兩部分:第一部分包含了這個數組的所有元素,但將最後一個元素除外(讓數組多一個空間纔有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。
直接插入排序
插入排序的過程
插入排序就像有的人打撲克一樣,每次摸起來一張牌後,在手中已經排序好的撲克中插入當前摸起的這張牌。問題的關鍵點就是:如何在已經排好序的序列中,找到當前元素該插入的位置。
當序列中只有一個元素時,不需要排序,因爲一個元素已經有序。
現在來考慮有多個元素的過程:
循環內:我們可以先把當前把插入的元素先保存起來,然後分別將剛纔保存起來的元素與有序序列中的每一個元素比較,那麼比較到什麼時候才停下來?a. 出現一個比保存的元素小的元素(saveNum < array[ i ] );b.以序隊列已經比較完畢(i >=0 )。因爲以序隊列的範圍是從 0 .. 當前插入元素位置 -1 , 所以我們需要一個循環來完成比較和搬遷元素。當循環條件不滿足時,即找到插入位置。直接插入即可。
參考代碼:
void InsertSort(int* array, int size)
{
if (array == NULL || size <= 0)
return;
// 從數組第二個元素開始處理,因爲一個元素已經有序
for (int i = 1; i < size; i++)
{
int temp = array[i];
int end = i - 1;
// 插入array[i] 到已序序列中 array[0.. i-1]
while (end >= 0 && temp < array[end])
{
array[end + 1] = array[end];
end--;
}
// 插入 array[i]
array[end + 1] = temp;
}
}
// 打印數組
void PrintfArray(string info , int* array, int size)
{
cout << info << ":";
for (int i = 0; i < size - 1; ++i)
cout << array[i] << " ";
cout << endl;
}
int main()
{
int array[] = {5, 9, 1, 6, 2, 4, 7, 8, 0 , 2, 0};
int size = sizeof(array) / sizeof(array[0]);
PrintfArray("排序前", array, size);
InsertSort(array, size);
PrintfArray("排序後", array, size);
return 0;
}
排序前:5 9 1 6 2 4 7 8 0 2
排序後:0 0 1 2 2 4 5 6 7 8
二分插入排序
void InsertSort_Binary(int * array, int size)
{
if (array == NULL || size <= 0)
return;
for (int i = 1; i < size; ++i)
{
int temp = array[i];
int left = 0; // 有序序列的左邊界
int right = i - 1;// 有序序列的右邊界
while (left <= right)
{
int mid = (left + right) / 2;
// 注意這裏的 等號,爲了保證算法的穩定性(相同關鍵字排序前後位置不會變)
// 所以也需要向後移動
if (array[mid] <= temp)
left = mid + 1;
else if (array[mid] > temp)
right = mid - 1;
}
// 搬移數據, 上面循環結束後,left的位置就是插入位置
// 需要將從left 到 當前插入元素的前一個位置都搬移一個位置
for (int j = i - 1; j >= left; --j)
{
array[j + 1] = array[j];
}
array[left] = temp;
}
}
希爾排序
void ShellSort(int*array , int size)
{
int gap = 3;
while (gap > 0)
{
for (int idx = gap; idx < size; idx += gap)
{
int temp = array[idx];
int end = idx - gap;
while (end >= 0 && array[end] > temp)
{
array[end + gap] = array[end];
end -= gap;
}
array[end + gap] = temp;
}
gap--;
}
}