数据结构基础(3) --Permutation 插入排序
Permutation(排列組合)
排列問題:
設R?=?{r1,?r2,?...?,?rn}是要進行排列的n個元素,?Ri?=?R-{ri};?集合X中元素的全排列記為Permutation(X),?(ri)Permutation(X)表示在全排列Permutation(X)的每一個排列前加上前綴ri得到的排列.
R的全排列可歸納定義如下:
當n=1時,Permutation(R)={r},r是集合R中唯一的元素;
當n>1時,Permutation(R)由(r1)Permutation(R1),(r2)Permutation(R2),?...,?(rn)Permutation(Rn)構成。
依次遞歸定義,則可設計產生Permutation(X)的遞歸算法如下:
template <typename Type> void permutation(Type *array, int front, int last) {//已經遞歸到了最后一個元素if (front == last){//打印輸出for (int i = 0; i < front; ++i){cout << array[i] << ' ';}cout << array[front] << endl;return ;}else{for (int i = front; i <= last; ++i){// 不斷的從下標為[front ~ last]的元素中選擇一個元素//作為當前序列的開頭元素std::swap(array[front], array[i]);permutation(array, front+1, last);std::swap(array[front], array[i]);}} }
算法說明:
算法Permutation(array,?k,?m)遞歸地產生所有前綴是array[0:k-1],且后綴是array[k:m]的全排列的所有排列.函數調用(list,?0,?n-1)則產生list[0:n-1]的全排列.
?
算法演示:
char?str[]?=?“abc”;的遞歸調用過程如圖:
小結:
雖然我們自己實現了Permutation,?但C++?STL中也實現了std::next_permutation算法,?在一般應用中,?我比較推薦使用STL中已經實現好的next_permutation,?畢竟STL的代碼質量還是非常高的,?而且速度一點也不遜色于我們的實現;
?
插入排序
插入排序是低級排序中速度最快的一種(冒泡/選擇/插入排序效率均為O(N^2)),但是跟快速排序(NlogN),歸并排序(NlogN)還是有一定的差距的⊙﹏⊙b汗!
算法思想:
不斷的從尚未排序的序列中選擇一個元素插入到已經排好序的序列中(當然,會有一個選擇插入位置的過程:選擇一個位置,?該位置前的元素都比該元素小,?該位置后的元素都比該元素大),類似于現實生活中的斗地主的摸排過程.
//實現與解析 /**說明:outer:第一個未排序的元素inner:搜索第一個小于tmp的元素的位置tmp: 用于暫存第一個尚未排序的元素 */ template <typename Type> void insertionSort(Type *begin, Type *end) throw (std::range_error) {if ((begin == end) || (begin == NULL) || (end == NULL))throw std::range_error("pointer unavailable");//假設第一個元素已經排好序了for (Type *outer = begin+1; outer < end; ++outer){Type tmp = *outer; //暫存第一個未排序的元素Type *inner = outer;//inner 不斷尋找一個位置(*(inner-1) <= tmp),//使得tmp->*inner(tmp所保存的值插入到inner位置)while (inner > begin && *(inner-1) > tmp){*inner = *(inner-1); //元素后移-- inner; //指針前移}*inner = tmp; //將元素插入已排序序列} }template <typename Iter> void insertionSort(Iter begin, Iter end) {return insertionSort(&(*begin), &(*end)); } /**insertionSort_2算法的由來:可以使用*begin(序列的第一個元素)作為哨兵,這樣就可以省去insertionSort 中第15行的inner > begin判斷,但付出的代價是begin所指向的位置不能再存儲有用的數據,只能被用作排序的哨兵 -> 以空間換時間(個人感覺沒什么必要...) */ template <typename Type> void insertionSort_2(Type *begin, Type *end) throw (std::range_error) {if ((begin == end) || (begin == NULL) || (end == NULL))throw std::range_error("pointer unavailable");for (Type *outer = begin+2; outer < end; ++outer){*begin = *outer;Type *inner = outer;//因為*begin不可能 > *begin, 所以該循環一定會退出while (*(inner-1) > *begin){*(inner) = *(inner-1);--inner;}*inner = *begin;} }
附-permutation與std::next_permutation測試代碼
int main() {vector<char> str;for (char ch = 'a'; ch <= 'c'; ++ch)str.push_back(ch);permutation(&(*str.begin()), 0, 2);cout << "----------" << endl;typedef vector<char>::iterator Iter_type;do{for (Iter_type iter = str.begin(); iter != str.end(); ++iter)cout << *iter << ' ';cout << endl;}while (std::next_permutation(str.begin(), str.end()));return 0; }總結
以上是生活随笔為你收集整理的数据结构基础(3) --Permutation 插入排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用DLL封装窗体和业务类
- 下一篇: Struts2拦截器简单示例