排序【1】插入排序
阿新 • • 發佈:2019-02-07
常見排序
在實際生活中,排序的運用很多,排序就是將一組雜亂無章的資料升序或者降序排成有序的序列。常見的排序演算法有。
不同的排序演算法適用於不同的場景下,衡量一個排序演算法的標準不僅有空間複雜度,空間複雜度,還有穩定性。一個穩定的排序演算法,相同的排序碼在排序前後相對位置是不會發生變化的。
當然,排序也會根據資料量的情況,分為:
1.內部排序:資料可以載入到記憶體中進行排序。
2.外部排序:資料元素太多不能一次性載入到記憶體中,根據排序的情況不能再記憶體和外村中移動資料的排序。
插入排序
演算法思想:每一步把一個元素key根據其排序碼插入到它前面的一組已經排好序的序列中,直到所有元素排好序。
具體執行步驟:
(1)先認為第一個元素是已序的,第二個元素。
(2)去第二個元素,從後向前在已序的序列中比較。
(3)如果該元素比(已排序)比新元素大,將該元素移動到下一個位置。
(3)重複步驟三,直到找到比已排序元素小或者等於的元素。
(4)插入新元素到該位置。
(5)重複步驟(2)
演算法效能
時間複雜度:
最優的情況下:就是資料元素已經是升序的,時間複雜度O(N);
最差的情況:資料序列是降序的,時間複雜度O(N^2);
空間複雜度:O(1)
穩定性:穩定。
適用的場景:當資料是已序的或者接近有序的,並且資料量比較小。
程式碼實現:
//最差的情況是降序拍,時間複雜度O(N^2)
//最好的情況是升序的,時間複雜度是O(N)
//平均時間複雜度O(N^2)
//穩定的排序演算法。
//空間複雜度O(1)
void InsertSort(int *array,int size)
{
for (int i=1;i<size;i++)
{
int end = array[i];
int j = i - 1;
while (j >= 0 && array[j] > end)//找到帶 c插入元素位置
{
array [j + 1] = array[j];
j--;
}
array[j + 1] = end;
}
}
我們可以用二分查詢來提高查詢插入位置的位置,來對插入排序進行優化,簡稱二分插入排序。
實現程式碼:
void BinaryInsertSort(int*array, int size)
{
for (int i = 1; i < size; ++i)
{
int left = 0;
int right = i - 1;
int end = array[i];
while (left<= right)
{
int mid = left + ((right - left) >> 1);
if (array[mid] < end)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
for (int j = i - 1; j >= left; --j)
{
array[j + 1] = array[j];
}
array[left] = end;
}
}
希爾排序 (減增量排序)
從本質上來說,希爾排序是對直接插入排序的一種優化,為了避免直接插入排序出現最差的情況,希爾排序將資料元素進行了分組,先進行預排序,使資料逐漸接近有序,再使用插入排序。
基本思想:先將待排序序列分割成若干個子序列(子序列由相隔某個“增量”的元素組成),分別對這些子序列進行直接插入排序,然後減小“增量”,分組排序子序列,使序列 基本有序,最後再對全體元素進行一次直接插入排序。
適用場景:希爾排序是對插入排序的一種優化,當資料元素比較多時,適合希爾排序。
時間複雜度:當N比較大的時候,時間複雜度在O(N^1.25)-1.6O(N……1.25)之間
空間複雜度:O(1)
穩定性:不穩定
程式碼實現:
void ShellSort(int*array, int size)
{
assert(array);
int gap = 1;
while (gap < size)
{
gap = gap * 2 + 1;
}
while (gap>=0)
{
for (int i = gap; i < size; ++i)
{
int key = array[i];
int j = i - gap;
while (j>0&&key<array[j])
{
array[j + 1] = array[j];
j = j - gap;
}
array[j + gap] = key;
}
gap = gap / 3 + 1;
}