上次說到冒泡排序html
一共能夠產生4種方式來產生,由於兩個for循環皆可從小到大,也可從大到小
分類 排序算法
數據結構 vector、數組
最差時間複雜度 O(n^2)
最優時間複雜度 O(n)
平均時間複雜度 O(n^2)
最差空間複雜度 總共O(n),須要輔助空間O(1)//用於交換所需臨時變量
冒泡排序算法的運做以下:
一、 比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
二、 對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對。這步作完後,最後的元素會是最大的數。
三、 針對全部的元素重複以上的步驟,除了最後一個。
四、 持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。
因爲它的簡潔,冒泡排序一般被用來對於程序設計入門的學生介紹算法的概念。
4、插入算法node
一句話就是從未處理的數組(或vector)向前面處理好的數組插入,由於前面處理好的已經有必定規律
通常來講,插入排序都採用in-place在數組上實現。具體算法描述以下:
一、 從第一個元素開始,該元素能夠認爲已經被排序
二、 取出下一個元素,在已經排序的元素序列中從後向前掃描
三、 若是該元素(已排序)大於新元素,將該元素移到下一位置
四、 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置
五、 將新元素插入到該位置後
六、 重複步驟2~5
若是比較操做的代價比交換操做大的話,能夠採用二分查找法來減小比較操做的數目。該算法能夠認爲是插入排序的一個變種,稱爲二分查找排序。
若是目標是把n個元素的序列升序排列,那麼採用插入排序存在最好狀況和最壞狀況。最好狀況就是,序列已是升序排列了,在這種狀況下,須要進行的比較操做需(n-1)次便可。最壞狀況就是,序列是降序排列,那麼此時須要進行的比較共有n(n-1)/2次。插入排序的賦值操做是比較操做的次數減去(n-1)次。平均來講插入排序算法複雜度爲O(n2)。於是,插入排序不適合對於數據量比較大的排序應用。可是,若是須要排序的數據量很小,例如,量級小於千,那麼插入排序仍是一個不錯的選擇。 插入排序在工業級庫中也有着普遍的應用,在STL的sort算法和stdlib的qsort算法中,都將插入排序做爲快速排序的補充,用於少許元素的排序(一般爲8個或如下)。ios
1 #include <iostream> 2 #include <iterator> 3 #include <vector> 4 #include <ctime> 5 #include <random> 6 #include <functional> 7 #include <algorithm> 8 using namespace std; 9 int intSwap(int& a,int& b) 10 { 11 int intswaptemp=a; 12 a=b; 13 b=intswaptemp; 14 return 0; 15 } 16 /*---------------------------------------- 17 插入排序 18 從小到大 19 vector<int> 20 -----------------------------------------*/ 21 int insertionSort(vector<int> &ivec) 22 { 23 int i,j,temp; 24 for(i=1;i<=ivec.size();i++) 25 { 26 j=i-1; 27 temp=ivec[i]; 28 while((temp<ivec[j])&&(j>=0)) 29 { 30 ivec[j+1]=ivec[j]; 31 j--; 32 } 33 ivec[j+1]=temp; 34 35 } 36 return 0; 37 } 38 //照貓畫貓-------->>>>上面 39 template<typename T> 40 int insertionSort_(T begin,T end) 41 { 42 typedef typename iterator_traits<T>::value_type value_type; 43 value_type key; 44 T ins=begin; 45 T j; 46 advance(ins,1); 47 while(ins!=end) 48 { 49 key=*ins; 50 j=ins; 51 T pre=j; 52 advance(j,-1); 53 while(key<*j&&pre!=begin) 54 { 55 iter_swap(pre,j); 56 advance(pre,-1); 57 advance(j,-1); 58 } 59 *pre=key; 60 advance(ins,1); 61 } 62 } 63 inline void insertSort_1(vector<int>&ivec) 64 { 65 insertionSort_(ivec.begin(),ivec.end()); 66 } 67 int main() 68 { 69 clock_t start,end; 70 vector<int> ivec,copyivec; 71 srand(14); 72 for(int i=0;i<10000;i++)//10k 73 ivec.push_back((int)rand()); 74 copyivec=ivec; 75 start=clock(); 76 insertionSort(ivec); 77 end=clock(); 78 for(int i=0;i<10000;i+=500) 79 cout<<ivec[i]<<'\t'; 80 cout<<endl; 81 cout<<"the time of 1 is "<<end-start<<endl; 82 start=clock(); 83 insertSort_1(copyivec); 84 end=clock(); 85 for(int i=0;i<10000;i+=500) 86 cout<<ivec[i]<<'\t'; 87 cout<<endl; 88 cout<<"the time of 2 is "<<end-start<<endl; 89 return 0; 90 }
可見仍是比較費時。不過因爲暫時尚未優化,最後比較的時候才能判斷。算法
5、堆排序數組
堆排序的前提是要了解二叉樹這樣一種玩意。這個排序的講解有個大神,我也是第一次學這方法。數據結構
這個地方講解的很清楚了~(最喜歡這種無腦就能夠看懂的玩意,不須要本身拿筆一點點算)http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.htmldom
個人話說就是這玩意能夠就是一直要記得二叉樹(有規律的,而這種規律能夠用來實現排序)
優化
這幅圖一共二種信息,第一種就是剛開始會整理,注意,最大的在第一列,這就是二叉樹的頂(頭,)第二種就是開始排序算法,經過實現未排序最後一個和第一個交換,而後接着造成新的二叉樹(頭最大),對了,感受代碼解釋不多,我須要填寫一些信息,第一次寫,求不坑人!ui
1 #include <iostream> 2 #include <iterator> 3 #include <vector> 4 #include <ctime> 5 #include <random> 6 #include <functional> 7 #include <algorithm> 8 using namespace std; 9 int intSwap(int& a,int& b) 10 { 11 int intswaptemp=a; 12 a=b; 13 b=intswaptemp; 14 return 0; 15 } 16 /*---------------------------------------- 17 堆構造 18 從小到大 19 para:vector<int> 、int length、int node; 20 vector<int>數據集合 21 length經過該參數,能夠不須要把已找到的數據和Ivec種分離出來, 22 就像圖片第二幅信息中沒有紅線的一些數據(一列就是一數據) 23 node該參數肯定結點,根據二叉樹的原理。 24 -----------------------------------------*/ 25 int buildHeap(vector<int> &ivec,int node,int length) 26 { 27 int bondnode=node;//保存node,防止修改node 28 int lchild=bondnode*2+1;//左孩子數 二叉樹關係(+1爲了防止從node爲0致使左孩子一直爲0,先左後右(二叉樹)) 29 while(lchild<length) 30 { 31 //存在右孩子,且知足左小右大 32 //從兩者中選出較大的並記錄爲lchild中保存 33 if(lchild+1<length&&ivec[lchild]<ivec[lchild+1]) 34 lchild++; 35 36 //判斷node和右子數大小 37 if(ivec[bondnode]>ivec[lchild]) 38 break;//若是知足說明這個3個數或2個數已經按照邏輯關係已經排序好。 39 else// 40 { 41 intSwap(ivec[bondnode],ivec[lchild]); 42 //重置結點和左孩子 43 //這些都是二叉樹的一些性質 44 bondnode=lchild;//找下一個結點 45 lchild=2*bondnode+1;//新的左子數 46 } 47 } 48 return 0; 49 } 50 /*---------------------------------------- 51 堆排序 52 從小到大 53 vector<int> 54 -----------------------------------------*/ 55 int SortHeap(vector<int> &ivec) 56 { 57 for(int i=(ivec.size())/2-1;i>=0;i--)//產生node 58 buildHeap(ivec,i,ivec.size());//構造每一個小堆,從底層向高層。恰好能夠減小不少次無效的循環 59 for(int j=0;j<ivec.size();j++)//排序開始了 60 { 61 intSwap(ivec[0],ivec[ivec.size()-j-1]); 62 //爲0的結點發生變換 63 buildHeap(ivec,0,ivec.size()-j-1); 64 } 65 return 0; 66 } 67 int main() 68 { 69 clock_t start,end; 70 vector<int> ivec,copyivec; 71 srand(14); 72 for(int i=0;i<10000;i++)//10k 73 ivec.push_back((int)rand()); 74 copyivec=ivec; 75 start=clock(); 76 SortHeap(ivec); 77 end=clock(); 78 for(int i=0;i<10000;i+=500) 79 cout<<ivec[i]<<'\t'; 80 cout<<endl; 81 cout<<"the time of 1 is "<<end-start<<endl; 82 83 return 0; 84 }
堆排序其實也是一種選擇排序,是一種樹形選擇排序。只不過直接選擇排序中,爲了從R[1...n]中選擇最大記錄,需比較n-1次,而後從 R[1...n-2]中選擇最大記錄需比較n-2次。事實上這n-2次比較中有不少已經在前面的n-1次比較中已經作過,而樹形選擇排序剛好利用樹形的特 點保存了部分前面的比較結果,所以能夠減小比較次數。對於n個關鍵字序列,最壞狀況下每一個節點需比較log2(n)次,所以其最壞狀況下時間複雜度爲 nlogn。堆排序爲不穩定排序,不適合記錄較少的排序。(轉自上面連接做者)spa
一般堆是經過一維數組來實現的。在起始數組爲 0 的情形中: