青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

SmartPtr
本博客已搬至:http://www.cnblogs.com/baiyanhuang/
posts - 29,comments - 176,trackbacks - 0
By SmartPtr(http://m.shnenglu.com/SmartPtr/)

    這幾天在網上看到有人總結了4種比較常見簡單的排序的算法,并用C#實現了出來。看了之后不由的想起了大學時候學<<數據結構>>的情景, 忍不住用C++實現了一遍,除了冒泡排序, 選擇排序, 插入排序,希爾排序之外, 還包括了算法復雜度較好的快速排序與堆排序。 然后用C++強大的模板功能實現了一個基于policy的Sort函數, 很明顯,這個Sort函數是以排序算法為policy的。 這里利用了不同的模板技術實作出多個版本的Sort函數,并比較了它們的優劣。
好了,閑話不說, 下面給出6種排序算法, 每種算法用一個class包裝, 代碼的注釋應該能很好的解釋這些算法。

// sort type: bubble sort
// complexity: O(n^2)
// Algorithm: compare adjcent elements and swap if not meet the compare criterion.
template<typename T>
struct BubbleSorter
{
    
void Sort(T list[], int n)
    {
        
bool bIsDone = false;
        
for(int i = n-1; i > 0 && !bIsDone; --i)
        {
            bIsDone 
= true// if no sway happened, then this list is already sorted.
            for(int j = 0; j < i; ++j)
            {
                
if(list[j+1< list[j])
                {
                    bIsDone 
= false

                    
int tmp = list[j+1];
                    list[j
+1= list[j];
                    list[j] 
= tmp;
                }
            }
        }
    }
};

// sort type: selection sort
// complexity: O(n^2)
// Algorithm: select the minimum element and move it to the front.
template<typename T>
struct SelectionSorter
{
    
void Sort(T list[], int n)
    {
        
int nIndexOfMin;
        
for(int i = 0; i < n-1++i)
        {
            nIndexOfMin 
= i;
            
for(int j = i+1; j < n; ++j)
            {
                
if(list[j] < list[nIndexOfMin])
                    nIndexOfMin 
= j;
            }

            
// swap the minimum element with the front element
            if(nIndexOfMin != i)
            {
                
int tmp = list[i];
                list[i] 
= list[nIndexOfMin];
                list[nIndexOfMin] 
= tmp;
            }
            
        }
    }
};

// sort type: insert sort
// complexity: O(n^2)
// Algorithm:  insert the n+1 element to an already sorted n element array
template <typename T>
struct InsertionSorter
{
    
void Sort(T list[], int n)
    {
        
for(int i = 1; i <= n-1++i)
        {
            
int nInsert = list[i];
            
int j = i - 1;
            
while(j >= 0 && list[j] > nInsert)
            {
                list[j
+1= list[j];
                
--j;
            }
            list[j
+1= nInsert;
        }
    }
};


// sort type: shell sort
// complexity: O(n^1.5...)
// Algorithm:  separate the list into several sublist and sort them respectively
// then decrease the number of sublist and sort until only one sublist.
template <typename T>
struct ShellSorter
{
    
void Sort(T list[], int n)
    {
        
int gap = n / 2;
        
// decrease the gap: gap = gap / 2
        while(gap > 0)
        {
            
// insertion sort in each gap
            
// in first execution, gap is the second sublist's first element
            for(int i = gap; i <= n-1++i) // sub list execute insertion sort in turn.
            {
                
int tmp = list[i];  // store the element to insert
                int j = i;
                
while(j >= gap && list[j-gap] > tmp) // important: j >= gap, or else j<0 when out of the loop
                {
                    list[j] 
= list[j-gap];
                    j 
= j-gap;
                }
                list[j] 
= tmp;
            }

            gap 
/= 2// decrease gap
        }
    }
};

// sort type: quick sort
// complexity: O(n*logn)
// Algorithm: partite the list in 2 sub list based on its first element, pivot, one list greater than pivot
// and another less than pivot, this time pivot is in this right position. do this to each sublist recusively
// until the sublist length equals 0
template <typename T>
struct QuickSorter
{
    
void Sort(T list[], int n)
    {
        QuickSort(list, 
0, n-1);
    }

private:
    
// partite the list in 2 sublists, nPivot will be in the right position.
    int Partition(T list[], int low, int high)
    {
        
int nPivot = list[low];
        
int nPivotPos = low;
        
for(int i = low + 1; i <= high ; ++i)
        {
            
if(list[i] < nPivot && ++nPivotPos != i) //++pivotpos != i is very tricky
            {
                
int tmp = list[nPivotPos];
                list[nPivotPos] 
= list[i];
                list[i] 
= tmp;
            }
        }
        
// in the previous loop, we just calculate the final pivot position and move the large number
        
// to the 2nd sublist, small number to the 1st sublist by swap. and after doing that, we put the 
        
// pivot in the right position here.
        int t = list[nPivotPos];
        list[nPivotPos] 
= list[low];
        list[low] 
= t;

        
return nPivotPos;
    }

    
void QuickSort(T list[], int first, int last)
    {
        
if(first < last)// end condition-this sublist just has 1 element
        {
            
int nPivotPos = Partition(list, first, last);
            QuickSort(list, first, nPivotPos
-1);
            QuickSort(list, nPivotPos
+1, last);
        }
    }
};


// sort type: Heap sort
// complexity: O(n*logn)
// Algorithm: construct a max heap from the list, swap the first element (the heap root) with the last
// element. adjust the previous (n-1) elements to a heap again and swap to its end again, do it 
// until the heap has only one element
template <typename T>
struct HeapSorter
{
    
void Sort(T list[], int n)
    {
        
// make the heap. n/2 is the last non-leaf node.
        for(int i = n / 2; i >= 0--i) FilterDown(list, i, n-1);

        
// move the root element (the last) to the end one by one as the heap decrease its size...
        for(int i = n-1; i >= 1--i)
        {
            
int tmp = list[0];
            list[
0= list[i];
            list[i] 
= tmp;
            
            
// adjust the heap to be a max heap
            FilterDown(list, 0, i-1);
        }
    }

private:
    
void FilterDown(T list[], int nStart, int nEndOfHeap)
    {
        
int i = nStart, j = 2*i+1;
        
int temp = list[i];
        
while(j <= nEndOfHeap)
        {
            
if(j+1 <= nEndOfHeap && list[j] < list[j+1]) j++;  //get the larger subnode
            if(temp >= list[j]) break;  // do we need swap the larger subnode with the parent node
            else{list[i] = list[j]; i = j; j = 2*i+1;} // adjust its subnode because it is modified
        }
        list[i] 
= temp;
    }
};

OK, 下面我們希望能用一個模板函數來靈活的調用這些算法,細細一看,我們有兩個參數:排序算法與被排序元素類型, 于是, 我們第一個Sort函數的版本應聲而出:

// trick: normal template parameter
// usage: Sort1<BubbleSorter<int>, int>(list, sizof(list)/sizeof(list[0]));
template <class SortPolicy, typename T>
void Sort1(T list[], int n)
{
    SortPolicy().Sort(list, n);
};

但是正如注釋中所言, 我們要這么調用這個函數:Sort1<BubbleSorter<int>, int>(list, sizof(list)/sizeof(list[0]))這么些模板參數要制定,實在是太不方便了, 而且我們可以看到這里兩個int就是冗余了,如果把他們寫成不同的類型,就無法保證其正確性(或編譯或運行)。我們有必要消除這個冗余, 也許你注意到SortPolicy中的那個int應該可以由第二個模板T參數提供,一個模板參數由另一個模板參數決定,對, 我們需要的就是模板模板參數(template template paramter):

// trick: template template paramter
// usage: Sort2<int, BubbleSorter>(list, sizeof(list)/sizeof(list[0]));
template<typename T, template <typename U> class SortPolicy>
void Sort2(T list[], int n)
{
    SortPolicy
<T>().Sort(list, n);
}

這樣我們就可以這么使用: Sort2<int, BubbleSorter>(list, sizeof(list)/sizeof(list[0])); 嗯, 比Sort1要好些了,但是因為我們知道list的元素類型了,如果這個int能夠直接從list推出了, 我們就只需要寫一個模板參數了,解決方法出奇的簡單,調換模板參數的聲明順序:

// trick: template template paramter, make the second parameter deduced fromt the parameter
// usage: Sort3<BubbleSorter>(list, sizeof(list)/sizeof(list[0]));
template<template <typename U> class SortPolicy, typename T>
void Sort3(T list[], int n)
{
    SortPolicy
<T>().Sort(list, n);
}

試試Sort3<BubbleSorter>(list, sizeof(list)/sizeof(list[0]));是不是很更簡單了:)

當然,C++中模板太靈活了, 我們還可以有其他實現,并且有的還不比Sort3這個版本差.(如下Sort5). 首先, Sort4用了類似于trait的技巧,排序的元素類型從排序的類中得出:

//to use this sort function, define sort classes like this:
//template<typename T>
//struct BubbleSorter
//{
//    typedef T elementtype;
//    void Sort(T list[], int n){...}
//};
// trick: type trait
// usage: Sort4<BubbleSorter<int> >(list, sizeof(list)/sizeof(list[0]));
template<class SortPolicy>
void Sort4(typename SortPolicy::elementtype list[], int n)
{
    SortPolicy().Sort(list, n);
};

代碼應該能很好的解釋它自己了。當然,它還不能從list的元素類型來推出SortPolicy類的模板參數類型。下一個版本Sort5, 可以與Sort3相媲美, 它采用的是成員模板參數:

 

//to use this sort function, define sort classes like this:
//struct BubbleSorter
//{
//    template<typename T>
//    void Sort(T list[], int n){...}
//};
// trick: member template 
// usage: Sort5<BubbleSorter>(list, sizeof(list)/sizeof(list[0]));
template<class SortPolicy, typename T>
void Sort5(T list[], int n)
{
    SortPolicy().Sort(list, n);
}

這里, 我們的排序的類不再是模板類,但其Sort函數為成員模板函數。這樣,該模板函數就能根據其參數list元素類型推導其模板參數類型。

具體使用如下:

 

template<typename T>
void Output(const string& strSortType, T list[], int n)
{
    cout
<<strSortType<<":";
    
for(int i = 0; i < n; ++i) cout<<list[i]<<" ";
    cout
<<endl;
}
int main(int argc, char *argv[])
{
    
int list[] = {12570126700 ,3,6,9};
    
int n = sizeof(list)/sizeof(list[0]);
    
//Bubble Sort
    Sort1<BubbleSorter<int>int>(list, n);    Output("Bubble Sort", list, n);
    Sort2
<int, BubbleSorter>(list, n);    Output("Bubble Sort", list, n);
    Sort3
<BubbleSorter>(list, n);                Output("Bubble Sort", list, n);
    
//Sort4<BubbleSorter<int> >(list, n);        Output("Bubble Sort", list, n);
    
//Sort5<BubbleSorter>(list, n);            Output("Bubble Sort", list, n);
    

    
//Quick Sort
    Sort1<QuickSorter<int>int>(list, n);    Output("Quick Sort", list, n);
    Sort2
<int, QuickSorter>(list, n);        Output("Quick Sort", list, n);
    Sort3
<QuickSorter>(list, n);                Output("Quick Sort", list, n);
    
//Sort2<QuickSorter<int> >(list, n);    Output("Quick Sort", list, n);
    
//Sort3<QuickSorter>(list, n);            Output("Quick Sort", list, n);
    
    
return 0;
}

好了,至此, 6種排序算法,5種C++模板的應用,在此完成結合。 

改進建議:
1. 交換兩個元素最好用std::swap
這里,我交換兩個元素的代碼是:

  int tmp = list[j+1];
  list[j
+1= list[j];
  list[j] 
= tmp;

除了沒有用swap外,還有一個致命的錯誤就是直接寫了int, 而不是模板類型T,這是因為考慮不仔細,且測試不完全(只測試了int一種類型)所導致的。

2. 因為各個排序類并不存儲任何數據,其存在的意義就在于區別算法類型,因此可以把所有函數聲明為static,這樣在排序模板函數中調用時只要直接調用static函數,而不用生成一個排序類的對象了。以Sort1為例:

// trick: normal template parameter
// usage: Sort1<BubbleSorter<int>, int>(list, sizof(list)/sizeof(list[0]));
template <class SortPolicy, typename T>
void Sort1(T list[], int n)
{
    SortPolicy::Sort(list, n);
};
posted on 2007-07-05 17:44 SmartPtr 閱讀(1798) 評論(9)  編輯 收藏 引用

FeedBack:
# re: 經典排序算法的C++ template封裝
2007-07-05 20:59 | czxskell
效率如何??
我以前寫過,數據太多的話,效率還是大打折扣
還是c語言實現的最快  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-05 21:56 | SmartPtr
為什么C實現會比這個快呢, 他們的區別在哪里, 是什么影響了其效率?  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-05 23:27 | czxskell
不好意思,看錯了,我以為你用了STL那一套東西,
這個不錯哦,這個能否借用表達式模板呢?估計不知  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-06 08:32 | SmartPtr
不好意思, 對表達式模板不太清楚, 可否介紹一下先?  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-06 13:39 | SuperPlayeR
貌似第一個排序類 BubbleSorter中的
if(list[j+1] < list[j])
{
bIsDone = false;

int tmp = list[j+1];
list[j+1] = list[j];
list[j] = tmp;
}
其中int tmp應該是T tmp吧?
后面的用到交換的好像都有這個問題。
哦,原來作者在文章結尾的時候說明了,呵呵~~~怪我太著急還沒看完就評論了。哎~下次要改掉這個壞習慣。  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-06 22:50 | pass86
贊一個。  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-08 01:54 | 天津大學計算機學院 常興龍
很不錯,贊一個!  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-10 09:22 | anders06
Lz 可否考慮用template 模式實現呢  回復  更多評論
  
# re: 經典排序算法的C++ template封裝
2007-07-10 10:11 | SmartPtr
To aders06:

你是說template method嗎, 這么做有什么好處?  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一区二区三区免费视频| 在线欧美亚洲| 亚洲午夜电影网| 亚洲激情网站| 美女网站在线免费欧美精品| 麻豆av一区二区三区久久| 午夜电影亚洲| 久久成人免费| 欧美国产精品| 国产在线国偷精品产拍免费yy| 黄色精品一区二区| 一区二区三区国产在线观看| 午夜精品久久一牛影视| 欧美专区在线| 亚洲靠逼com| 久久精品综合一区| 欧美视频在线不卡| 永久域名在线精品| 亚洲午夜精品一区二区| 免费在线看一区| 亚洲影音先锋| 欧美日韩一级黄| 亚洲精品久久7777| 久久全球大尺度高清视频| 91久久精品国产91久久性色tv | 欧美日韩视频在线一区二区观看视频| 国产精品久久久久影院亚瑟| 亚洲精品一区二区三区四区高清| 久久久精品国产一区二区三区 | 欧美成人精品不卡视频在线观看| 你懂的亚洲视频| 亚洲欧美电影院| 欧美日韩精品系列| 亚洲福利国产精品| 欧美电影免费观看高清| 国产精品三级视频| 日韩亚洲在线观看| 欧美激情女人20p| 久久精品人人做人人爽| 国产精品亚发布| 欧美一区二区三区视频在线| 亚洲性视频网址| 国内不卡一区二区三区| 久久精品成人| 欧美成人伊人久久综合网| 亚洲精品欧洲精品| 一区二区三区国产在线| 国产精品热久久久久夜色精品三区| 亚洲一卡二卡三卡四卡五卡| 亚洲一级在线观看| 亚洲精品偷拍| 亚洲一区二区在| 亚洲第一精品夜夜躁人人爽| 亚洲精品极品| 国产三级精品在线不卡| 亚洲第一精品久久忘忧草社区| 欧美日韩国产成人在线91| 欧美综合激情网| 欧美精品三级| 久久综合色8888| 欧美日韩综合精品| 免费久久99精品国产自在现线| 欧美日韩成人一区| 久久久久久网站| 国产精品久久国产愉拍| 老司机一区二区三区| 国产精品自拍视频| 亚洲精品乱码久久久久| 亚洲综合国产| 久久精品亚洲一区| 性18欧美另类| 国产精品久久久久aaaa九色| 欧美国产视频一区二区| 在线不卡欧美| 麻豆成人91精品二区三区| 免费在线看成人av| 国产日韩一区二区| 中日韩美女免费视频网站在线观看| 亚洲精品网站在线播放gif| 久久久久看片| 亚洲第一色中文字幕| 在线日韩中文| 欧美日韩一区二区三区高清| 99精品久久| 欧美一区二区三区电影在线观看| 国产农村妇女毛片精品久久麻豆| 亚洲欧美综合v| 久久最新视频| 9久re热视频在线精品| 国产精品劲爆视频| 久久国产精品毛片| 亚洲国内精品在线| 亚洲香蕉伊综合在人在线视看| 国产精品成人在线观看| 欧美夜福利tv在线| 亚洲品质自拍| 裸体一区二区三区| 亚洲一级黄色片| 一区二区三区在线看| 国产精品三级视频| 欧美破处大片在线视频| 午夜一区不卡| 在线亚洲欧美专区二区| 亚洲国产精品一区二区久| 亚洲欧美色一区| 国产精品99久久久久久www| 国产一区二区| 亚洲伊人久久综合| 亚洲第一综合天堂另类专| 欧美一级视频| 亚洲欧美日本日韩| 亚洲四色影视在线观看| 亚洲人成在线观看网站高清| 国产日本欧美在线观看 | 亚洲一区二区三区777| 国产色综合天天综合网| 欧美午夜不卡在线观看免费 | 亚洲私人影院在线观看| 亚洲精品国产无天堂网2021| 欧美国产亚洲另类动漫| 欧美高清成人| 亚洲欧洲综合另类在线| 亚洲电影免费在线观看| 老牛国产精品一区的观看方式| 久久成人18免费网站| 久久久91精品国产| 欧美xx69| 亚洲高清在线观看| 9人人澡人人爽人人精品| 亚洲一区二三| 欧美成人中文字幕| 国产精品久久午夜| 亚洲国产精品尤物yw在线观看| 亚洲精品中文字幕有码专区| 亚洲午夜精品一区二区| 久久久亚洲人| 亚洲宅男天堂在线观看无病毒| 欧美一区日韩一区| 欧美日韩中文字幕日韩欧美| 国产色视频一区| 在线亚洲伦理| 欧美国产日本在线| 久久国产精品久久久久久久久久| 欧美日一区二区在线观看| 黄色成人91| 国产日韩1区| 中文在线资源观看网站视频免费不卡| 久久se精品一区精品二区| 99www免费人成精品| 久久综合九色欧美综合狠狠| 国产日韩一级二级三级| 亚洲午夜久久久久久久久电影院| 欧美激情第9页| 久久综合久久综合久久| 狠狠色伊人亚洲综合网站色| 久久国产高清| 久久久久久电影| 亚洲国产cao| 亚洲高清色综合| 欧美极品aⅴ影院| 一区二区三区偷拍| 亚洲欧美国产视频| 一区二区在线不卡| 亚洲精品国产精品国产自| 欧美另类变人与禽xxxxx| 亚洲图片在区色| 亚洲欧美日韩一区二区三区在线观看 | 国产亚洲成人一区| 亚洲国产日日夜夜| 国产精品看片你懂得| 久久精品一本| 欧美日韩日韩| 免费看精品久久片| 国产精品国产自产拍高清av| 久久国产毛片| 欧美调教vk| 亚洲国产经典视频| 国产亚洲制服色| 一区二区三区**美女毛片 | 欧美va天堂| 欧美伊人久久大香线蕉综合69| 久久久久久久久久久久久久一区| 日韩视频一区二区| 欧美一区二区视频观看视频| 日韩一区二区精品在线观看| 欧美一区二区大片| 欧美精品1区| 亚洲电影av在线| 亚洲电影下载| 男人天堂欧美日韩| 欧美成人免费播放| 在线日韩欧美视频| 久久夜色精品一区| 蜜桃av噜噜一区| 激情成人综合| 久久综合九色综合欧美就去吻| 久久在线91| 亚洲国产成人tv| 欧美二区乱c少妇| 99视频热这里只有精品免费|