【啊哈!算法】之二、插入排序
作者:jofranks?原創(chuàng)作品,轉(zhuǎn)載請標(biāo)明出處!版權(quán)所有,侵權(quán)必究!
來源:http://blog.csdn.net/jofranks
插入排序包括:直接插入排序,折半插入排序,希爾排序~!
OK,下面我們就來逐個講解!
一、直接插入排序
直接插入排序?qū)儆诜€(wěn)定的排序,時間復(fù)雜性為O(n^2),空間復(fù)雜度為O(1)。
它的基本思想是: ? ?
假設(shè)待排序數(shù)據(jù)存放在數(shù)組A[1..n]中,則A[1]可看作是一個有序序列,讓i從2開始,依次將A[i]插入到有序序列A[1..i-1]中,A[n]插入完畢則整個過程結(jié)束,A[1..n]成為有序序列。
OK,現(xiàn)在我們來看一下排序的過程:
待排序數(shù)據(jù):? 【25】? 54?8? 54? 21?1? 97? 2?73? 15??????????? (n=10)
i=2:?????????????? 【25?54】? 8?54? 21? 1?97? 2? 73? 15
i=3:?????????????? 【8? 25? 54】? 54?21? 1? 97?2? 73? 15
i=4:?????????????? 【8? 25?54?54】? 21?1? 97? 2?73? 15
i=5:?????????????? 【8? 21? 25?54? 54】? 1?97? 2? 73? 15
i=6:?????????????? 【1? 8? 21?25? 54? 54】? 97?2? 73? 15
i=7:?????????????? 【1? 8?21? 25? 54?54?97】? 2?73? 15
i=8:?????????????? 【1? 2? 8?21? 25? 54?54? 97】? 73? 15
i=9:?????????????? 【1? 2?8? 21? 25?54? 54?73? 97】? 15
i=10:???????????? 【1? 2?8?15? 21?25? 54? 54?73? 97】???????????排序結(jié)束
可在數(shù)組中增加元素A[0]作為關(guān)鍵值存儲器和循環(huán)控制開關(guān)。第i趟排序,即A[i]的插入過程為:
① 保存A[i]→A[0]
②
③ 如果A[j]<=A[0](即待排序的A[i]),則A[0]→A[j+1],完成插入;
?? 否則,將A[j]后移一個位置:A[j]→A[j+1];;繼續(xù)執(zhí)行③
對于上面的數(shù)據(jù)實例,i從2依次變化到10的過程中,j值分別為{1,0,3,1,0,6,1,7,3}
來看一下動畫演示:直接插入排序動畫演示
OK,下面來看一下代碼,本代碼是C語言!
void insert_sort(int a[], int N) {int temp;int j;//從第二個元素開始逐個往下for(int i = 1; i < N; i++){if(a[i] >= a[i - 1])continue;temp = a[i];//與前面的元素比較,看是否需要插入j = i - 1;for(; a[j] > temp; j--){if(j < 0)break;a[j + 1] = a[j]; //后移 }a[j + 1] = temp;} }ok,現(xiàn)在我們來看一下C++版本的代碼:(本代碼取自維基百科)
#include <iterator>template<typename biIter> void insertion_sort(biIter begin, biIter end){typedef typename std::iterator_traits<biIter>::value_type value_type;biIter bond = begin;std::advance(bond, 1);for(; bond!=end; std::advance(bond, 1)) {value_type key = *bond;biIter ins = bond;biIter pre = ins;std::advance(pre, -1);while(ins!=begin && *pre>key) {*ins = *pre;std::advance(ins, -1);std::advance(pre, -1);}*ins = key;}}二、折半插入排序
折半插入排序算法是一種穩(wěn)定的排序算法,時間復(fù)雜度仍然為o(n^2)!!!
本排序是在直接插入排序的基礎(chǔ)上,減少了比較和移動的次數(shù)形成的!是對插入排序算法的一種改進!
具體操作:在將一個新元素插入已排好序的數(shù)組的過程中,尋找插入點時,將待插入?yún)^(qū)域的首元素設(shè)置為a[low],末元素設(shè)置為a[high],則輪比較時將待插入元素與a[m],其中m=(low+high)/2相比較,如果比參考元素小,則選擇a[low]到a[m-1]為新的插入?yún)^(qū)域(即high=m-1),否則選擇a[m+1]到a[high]為新的插入?yún)^(qū)域(即low=m+1),如此直至low<=high不成立,即將此位置之后所有元素后移一位,并將新元素插入a[high+1]。
OK,我們來看一下代碼! 這類似于二分法查找,相信大家都不陌生!
void binary_insert_sort(int a[], int N) {int temp;int low, high,mid;for(int i = 1; i < N; i++){if(a[i] >= a[i - 1])continue;//開始二分low = 0;high = i - 1;temp = a[i];for(;low <= high;){mid = (low + high) / 2;if(temp > a[mid])low = mid + 1;else if(temp < a[mid])high = mid - 1;elsebreak;}//開始移動元素for(int j = i; j > low; j--){a[j] = a[j - 1];}a[low] = temp;} }
三、希爾排序
該算法也是對直接插入排序的一種改進!也叫做遞減增量排序算法!
該算法的性能提升至O(n?log2?n)!他的最優(yōu)時間是線性時間!
算法基本思想:
取一個小于n的整數(shù)S1作為增量,把所有元素分成S1個組。所有間距為S1的元素放在同一個組中。
第一組:{A[1],A[S1+1],A[2*S1+1],……}
第二組:{A[2],A[S1+2],A[2*S1+2],……}
第三組:{A[3],A[S1+3],A[2*S1+3],……}
……
第s1組:{A[S1],A[2*S1],A[3*S1],……}
先在各組內(nèi)進行直接插人排序;然后,取第二個增量S2(<S1)重復(fù)上述的分組和排序,直至所取的增量St=1(St<St-1<St-2<…<S2<S1),即所有記錄放在同一組中進行直接插入排序為止。
| 序號 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
| 原始數(shù)據(jù) | 12 | 89 | 57 | 32 | 96 | 37 | 54 | 5 | 79 | 57 | |
| S1=5 | 組別 | ① | ② | ③ | ④ | ⑤ | ① | ② | ③ | ④ | ⑤ |
| 排序結(jié)果 | 12 | 54 | 5 | 32 | 57 | 37 | 89 | 57 | 79 | 96 | |
| S2=3 | 組別 | ① | ② | ③ | ① | ② | ③ | ① | ② | ③ | ① |
| 排序結(jié)果 | 12 | 54 | 5 | 32 | 57 | 37 | 89 | 57 | 79 | 96 | |
| S3=2 | 組別 | ① | ② | ① | ② | ① | ② | ① | ② | ① | ② |
| 排序結(jié)果 | 5 | 32 | 12 | 37 | 57 | 54 | 79 | 57 | 89 | 96 | |
| S4=1 | 組別 | ① | ① | ① | ① | ① | ① | ① | ① | ① | ① |
| 排序結(jié)果 | 5 | 12 | 32 | 37 | 54 | 57 | 57 | 79 | 89 | 96 | |
OK,通過上表可以看的清楚是如何排序的,有可能有的童鞋還是不清楚,那沒事,我現(xiàn)在上傳一個短動畫,通過動畫我相信你能夠很好的理解shell排序!
希爾排序動畫演示
ok,我們現(xiàn)在來看代碼吧!
void shell_sort(int a[], int N) {int temp, m;int i = 0;for(; i < N; ){i = i * 4 + 1;}//還是直接插入for(;i > 0;){for(int j = i; j < N; j++){m = j - i;temp = a[j];while(a[m] > temp){a[m + i] = a[m];m -= i;}a[m + i] = temp;}i = (i - 1) / 4;} }
OK,再來看一段C++代碼,來自維基百科!
template<typename T> void sort(std::vector<T>& v) {const size_t s=v.size();for(int gap=s/2;gap>0;gap/=2)for(int i=gap;i<s;++i)for(int j=i-gap;j>=0;j-=gap)if(v[j+gap]<v[j]){T temp=v[j];v[j]=v[j+gap];v[j+gap]=temp;} }
本節(jié)到此結(jié)束!
--------2012/7/31
--------jofranks 于南昌
轉(zhuǎn)載于:https://www.cnblogs.com/java20130723/archive/2012/07/31/3211427.html
總結(jié)
以上是生活随笔為你收集整理的【啊哈!算法】之二、插入排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ProSolid下的遍历访问封装代码
- 下一篇: Asp.Net+Jquery.Ajax详