思路:
從最左邊的元素開始,逐個遍歷,找到這一趟中的最小值,存到minindex裡面,最後這一趟結束,將它和這一趟開始遍歷的位置i上的元素swap,直到最後乙個位置上也就位。相當於選擇出每一趟最小的元素,然後把它放到這一趟開始的地方。
基礎版:
void selectionsort(int arr, int n)
}
思路:
由於第乙個元素可以預設為已排好序,因此可以從第二個元素開始遍歷,每一趟使乙個元素正確的插入到前面已排好序的陣列中。如果這個元素比它前面的元素小,則swap一下,如果大於等於它前面的元素,說明它以及它前面的元素已經排好序了,這一趟結束。
插入排序和選擇排序乙個很大的區別就是插入排序每一趟有可能提前結束,即它只要到達乙個位置大於等於它前面的元素,那麼這一趟就已經排好了;而選擇排序每一趟必須遍歷完這一趟所有的元素,找到最小的那個,然後再把最小的那個和這一趟開始的元素進行swap,是不能提前結束的。
對於近乎有序的陣列,適合用插入排序。
對於完全有序的陣列,插入排序複雜度為o(
n)o (n
)。基礎版:
void insertionsort(t arr, int n)
return;
}
改進版:
將原本一次次的swap操作,變成一次次比較,而在一趟的最後進行賦值。
插入排序演算法針對完全排好序的陣列是o(n)級別的演算法,每次判斷一下當前數就是正確位置,這一趟就退出了
改進後的插入排序避免了很多次unnecessary copy,由此非常適合基本排好序而不需要很多次變動的陣列。
void insertionsort(t arr, int n)
return;
}
思路:
i從最左邊的元素開始遍歷,一共要遍歷n-1趟,因為第n-1趟遍歷完成後,最後乙個元素也就位了。在每一趟裡面,j用來從第二個元素開始遍歷到這一趟的最後乙個元素,然後將它與它前面的元素比較,如果比前面的元素小就交換,然後j++;如果大於等於前面的元素就不交換,然後j++。直到遍歷到這一趟的最後乙個元素為止。
如, 第一趟:i = 0, j下標從1遍歷到n-1,最後乙個元素就位;
第二趟:i = 1, j從1遍歷到n-2,最後乙個元素就位
… 第m趟:i = m-1, j從1遍歷到n-1-i
… 第n-1趟:i = n-2, j從1遍歷到n-1-n+2=1
基礎版:
void bubblesort(t arr, int n)}}
思路:
希爾排序的思路實際上是插入排序的延伸。插入排序中每一次都和之前的乙個元素比較,而希爾排序每一次對之前的第h個元素進行比較,這樣通過將h乙個很大的值,逐漸變成乙個很小的值,直到等於1,此時整個陣列也排好了。
基礎版:
void shellsort(t arr, int n)
h /= 3;
}}// 比較selectionsort, insertionsort和bubblesort和shellsort四種排序演算法的效能效率
// shellsort是這四種排序演算法中效能最優的排序演算法
上面的排序演算法都是o(
n2) o(n
2)級別的演算法,下面介紹的歸併排序和快速排序是o(
nlog
n)o (n
logn
)級別的,那麼o(
n2) o(n
2)和o(nlog
n)o (n
logn
)有什麼不同呢?
思路:歸併排序利用遞迴的思想,把陣列分成兩組,而後再在組內再分成兩組,以此類推直到每組只有乙個元素,此時每組都是排好序的。之後再兩組兩組進行merge操作。
需要申請額外空間,使得歸併的時候時間複雜度是o(n)。
注意陣列越界和範圍定義的問題。
基礎版:
template
void mergesort(t arr, int l, int r)
void merge(t arr, int l, int mid, int r)
else
if ( j > r)
//都沒有越界的情況
if(aux[i-l] < aux[j-l])
else}}
改進版:
對於近乎有序的陣列,適合用插入排序,此時用歸併排序反而效率很低,因此我們要對它進行優化。在mergesort函式裡,當兩個子陣列都sort了之後,且arr[mid]<=arr[mid+1],則無需進行merge操作,因為arr[l…mid]和arr[mid+1…r]都已經排好序了,而arr[mid]又小於等於arr[mid+1],此時整個陣列就已經排好序了。在**中只需加一行判斷即可。
void mergesort(t arr, int l, int r)
當subarray比較小的時候,我們可以轉而使用插入排序而非歸併排序來提高效能,這是因為此時很大概率這個subarray是近乎有序的陣列。
void mergesort(t arr, int l, int r)
int mid = l + (r-l)/2;
mergesort(arr, l, mid);
mergesort(arr, mid+1, r);
if(arr[mid] > arr[mid+1])//merge之前判斷
merge(arr,l,mid,r);
}
之前的插入排序是從0…n-1進行排序的,這裡的插入排序是從l到r進行排序的,細節上略有不同:
需要注意的是,快速排序的空間複雜度是o(
logn
) o(l
ogn)
,這是因為它使用遞迴需要開闢額外的棧空間來儲存上一狀態,遞迴的次數是lo
gnl og
n級別的。
排序查詢演算法大總結
溫故而知新,可以為師矣 深入理解 選擇排序演算法 深入理解 交換排序演算法 深入理解 插入排序演算法 深入理解 歸併排序演算法 二分查詢演算法 不對之處請各位指出,感謝。import org.junit.test 總結排序演算法 氣泡排序 快速排序 直接插入排序 折半插入排序 希爾排序 選擇排序 堆...
排序演算法 九大排序演算法總結
參考部落格 排序演算法 直接插入排序 時間複雜度 空間複雜度 o 1 穩定性 穩定 參考部落格 排序演算法 希爾排序 時間複雜度 空間複雜度 o 1 穩定性 不穩定 參考部落格 排序演算法 選擇排序 時間複雜度 空間複雜度 o 1 穩定性 不穩定 參考部落格 排序演算法 堆排序 時間複雜度 空間複雜...
經典演算法大總結之排序演算法
從本章開始,我們將總結常用的排序演算法這裡有乙個很好的博文 一,插入排序,o n2 includeusing namespace std void insertionsort int a,int len a i 1 key void main insertionsort a,6 for int i ...