算法就是這麼一回事(排序)(第二部分)

上次說到冒泡排序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 的情形中:

  • 父節點i的左子節點在位置 (2*i+1);
  • 父節點i的右子節點在位置 (2*i+2);
  • 子節點i的父節點在位置 floor((i-1)/2);
相關文章
相關標籤/搜索