排序算法

 冒泡排序、选择排序、插入排序的算法复杂度都是O(N*N),在ubuntu16.04下,CPU为i7-2640m,g++版本为5.4.0,实际排序十万个不重复随机数的结果显示,冒泡排序运行时间71.2s,选择排序运行时间为41.2s,插入排序运行时间为39.8s,可见插入排序的效率更好一些。

实际上插入排序可以不用swap函数,利用类似堆排序的技巧,可以得到更进一步的优化,经过验证,优化后的插入排序的运行时间缩短到23.3秒。另外,如果序列已经预先排序,那三种O(N*N)算法只有插入排序会将复杂度降到O(N),因为第一次比较之后break语句就将内部循环中断,相当于只进行了一次外部循环。

Shell排序的时间复杂度为次O(N*N),实际测得比堆排序时间略长。

另外堆排序的运行时间为0.036秒,可见O(N*logN)复杂度对运行时间的巨大提升。

注意算法的边界条件的选取。

 

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <vector>
  4 #include <iterator>  
  5 #include <ctime>     
  6 using namespace std;
  7 //冒泡排序
  8 template<typename T>
  9 void sort_mp(vector<T>& items)
 10 {
 11     for(int i = 0; i < items.size() - 1 && items[i] < items[i + 1]; ++i){
 12         if(i == items.size() - 2)
 13             return;
 14     }
 15     for(int i = items.size() - 1; i > 0; --i){
 16         for(int j = 0; j < i; ++j){
 17             if(items[j] > items[j + 1])
 18                 swap(items[j], items[j + 1]);
 19         }
 20     }
 21 }
 22 //插入排序
 23 template<typename T>
 24 void sort_cr(vector<T>& items)
 25 {
 26     for(int i = 1; i < items.size(); ++i){
 27         T tmp = items[i];
 28         for(int j = i; j > 0; --j){
 29             if(items[j - 1] > tmp)
 30                 swap(items[j], items[j - 1]);
 31             else
 32                 break;
 33         }
 34     }
 35 }
 36 //插入排序改进版,用于快排
 37 template<typename T>
 38 void sort_cr_pro(vector<T>& items, int begin, int end)
 39 {
 40     for(int i = begin + 1; i <= end; ++i){
 41         T tmp = items[i];
 42         int j = i;
 43         for(; j > begin; --j){
 44             if(items[j - 1] > tmp)
 45                 items[j] = items[j - 1];
 46             else
 47                 break;
 48         }
 49         items[j] = tmp;
 50     }
 51 }
 52 //选择排序
 53 template<typename T>
 54 void sort_xz(vector<T>& items)
 55 {
 56     for(int i = 0; i < items.size() - 1 && items[i] < items[i + 1]; ++i){
 57         if(i == items.size() - 2)
 58             return;
 59     }
 60     for(int i = 0; i < items.size() - 1; ++i){
 61         int min_index = i + 1;
 62         for(int j = i + 1; j < items.size(); ++j){
 63             if(items[min_index] > items[j])
 64                 min_index = j;
 65         }
 66         if(items[min_index] < items[i])
 67             swap(items[min_index], items[i]);
 68     }
 69 }
 70 //希尔排序
 71 template<typename T>
 72 void sort_shell(vector<T>& items)
 73 {
 74     int increment = items.size() / 2;
 75     while(increment > 0){
 76         for(int i = increment; i < items.size(); ++i){
 77             T tmp = items[i];
 78             int j = i;
 79             for(; j >= increment; j -= increment){
 80                 if(items[j - increment] > tmp)
 81                     items[j] = items[j - increment];
 82                 else
 83                     break;
 84             }
 85             items[j] = tmp;
 86         }
 87         increment /= 2;
 88     }
 89 }
 90 
 91 //堆排序1
 92 template <typename T>
 93 void itemDown1(vector<T>& array, int hole, int currentSize)
 94 {
 95     T tmp = array[hole];
 96     int child = 0;
 97     for(; hole * 2 <= currentSize; hole = child){
 98         child = hole * 2;
 99         if(child != currentSize && array[child] < array[child + 1])
100             child++;
101         if(array[child] > tmp)
102             array[hole] = array[child];
103         else
104             break;
105     }
106     array[hole] = tmp;
107 }
108 template <typename T>
109 void sort_heap1(vector<T>& items)
110 {
111     int currentSize = items.size() - 1;
112     for(int i = currentSize / 2; i >= 1; --i)
113         itemDown1(items, i, currentSize);
114     while(currentSize > 1){
115         swap(items[currentSize--], items[1]);
116         itemDown1(items, 1, currentSize);
117     }
118     T tmp = items[0];
119     int j = 0;
120     for(j = 0; j < items.size(); ++j){
121         if(items[j + 1] < tmp)
122             items[j] = items[j + 1];
123         else
124             break;
125     }
126     items[j] = tmp;
127 }
128 
129 //堆排序2
130 template <typename T>
131 void itemDown2(vector<T>& array, int hole, int currentSize)
132 {
133     T tmp = array[hole];
134     int child;
135     for(; hole * 2 + 1 < currentSize; hole = child){
136         child = hole * 2 + 1;
137         if(child != currentSize - 1 && array[child] < array[child + 1])
138             ++child;
139         if(array[child] > tmp)
140             array[hole] = array[child];
141         else
142             break;
143     }
144     array[hole] = tmp;
145 }
146 template <typename T>
147 void sort_heap2(vector<T>& items)
148 {
149     int currentSize = items.size();
150     for(int i = items.size() / 2 - 1; i >= 0; --i)
151         itemDown2(items, i, items.size());
152     while(--currentSize > 0){
153         swap(items[0], items[currentSize]);
154         itemDown2(items, 0, currentSize);
155     }
156 }
157 //归并排序
158 template <typename T>
159 void merge_(vector<T>& items, vector<T>& tmp, int lbegin, int rbegin,  int rend)
160 {
161     int lend = rbegin - 1;
162     int tmp_index = lbegin;
163     int temp_begin = lbegin;
164     while(lbegin <= lend && rbegin <= rend){
165         if(items[lbegin] < items[rbegin])
166             tmp[tmp_index++] = items[lbegin++];
167         else
168             tmp[tmp_index++] = items[rbegin++];
169     }
170     while(lbegin <= lend)
171         tmp[tmp_index++] = items[lbegin++];
172     while(rbegin <= rend)
173         tmp[tmp_index++] = items[rbegin++];
174     while(rend >= temp_begin){
175         items[rend] = tmp[rend];
176         --rend;
177     }
178 }
179 template <typename T>
180 void sort_merge_Rec_(vector<T>& items, vector<T>& tmp, int begin, int end)
181 {
182     if(begin < end){
183         int middle = (begin + end) / 2;
184         sort_merge_Rec_(items, tmp, begin, middle);
185         sort_merge_Rec_(items, tmp, middle + 1, end);
186         merge_(items, tmp, begin, middle + 1, end);
187     }
188 }
189 template <typename T>
190 void sort_merge_Rec(vector<T>& items)
191 {
192     vector<T> tmp(items.size());
193     sort_merge_Rec_(items, tmp, 0, items.size() - 1);
194 }
195 //非递归归并排序   
196 template <typename T>
197 void sort_merge_NonRec_(vector<T>& items, vector<T>& tmp)
198 {
199     int step = 2;
200     while(step / 2 < items.size()){
201         int i = 0;
202         for(; i + step - 1 < items.size(); i += step){
203             merge_(items, tmp, i, i + step / 2, i + step - 1);
204         }
205         if(i + step / 2 < items.size()){
206             merge_(items, tmp, i, i + step / 2, items.size() - 1);
207         }
208         step *= 2;
209     }
210 }
211 template <typename T>
212 void sort_merge_NonRec(vector<T>& items)
213 {
214     vector<T> tmp(items.size());
215     sort_merge_NonRec_(items, tmp);
216 }
217 //快排
218 template <typename T>
219 const T& get_pivot(vector<T>& items, int begin, int end)
220 {
221     int middle = (begin + end) / 2;
222     if(items[begin] > items[middle])
223         swap(items[begin], items[middle]);
224     if(items[begin] > items[end])
225         swap(items[begin], items[end]);  
226     if(items[middle] > items[end])
227         swap(items[middle], items[end]);
228     swap(items[middle], items[end - 1]);
229     return items[end - 1];
230 }
231 template <typename T>
232 void sort_quick(vector<T>& items, int begin, int end)
233 {
234     //可以在数组长度小于一定值时候采用插入排序改进,减少递归次数
235     if(end - begin >= 3){
236         T pivot = get_pivot(items, begin, end);
237         int i = begin, j = end - 1;
238         while(true){
239             while(items[++i] < pivot){}
240             while(items[--j] > pivot){}
241             if(i < j)
242                 swap(items[i], items[j]);
243             else
244                 break;
245         }
246         swap(items[i], items[end - 1]);
247         sort_quick(items, begin, i - 1);
248         sort_quick(items, i + 1, end);
249     }
250     else
251         sort_cr_pro(items, begin, end);
252 }
253 template <typename T>
254 void sort_quick(vector<T>& items)
255 {
256     sort_quick(items, 0, items.size() - 1);
257 }
258 
259 template <typename T>
260 void sort_quick_(vector<T>& items, int begin, int end)
261 {
262     /*递归过深可能导致栈溢出,可在数组小于一定长度时候
263     由插入排序完成,数组长度长于一定长度改为快排
264     */
265     if(end - begin >= 1){
266         T pivot = items[begin];
267         int i = begin, j = end + 1;
268         //如果此处为i<j,那么需要在while循环外判断items[j], items[begin]大小
269         while(true){
270             //此if用来处理有多个相同元素的排序,防止无限循环
271             //if(i < j && items[i] == pivot && items[j] == pivot)
272              //   --j;
273             //此处对i的上限进行限制,否则i可能超出数组长度
274             while(i < end && items[++i] < pivot ){}
275             while(items[--j] > pivot){}
276             if(i < j)
277                 swap(items[i], items[j]);
278             else
279                 break;
280         }
281         /*if(items[j] < items[begin]), 前面循环为true,
282         这里不再需要,因为j可达到begin处
283         */
284             swap(items[j], items[begin]);
285         sort_quick_(items, begin, j - 1);
286         sort_quick_(items, j + 1, end);
287     }
288 }
289 template <typename T>
290 void sort_quick_(vector<T>& items)
291 {
292     sort_quick_(items, 0, items.size() - 1);
293 }
294 int main()
295 {
296     typedef ostream_iterator<int> OstreamItr;
297     clock_t start,finish;
298     vector<int> temp;
299     for(int i = 0; i < 100; ++i)
300         temp.push_back(i + 1);
301     for(int i = 0; i < 1000; ++i)
302         temp.push_back(i + 1);
303     random_shuffle(temp.begin(), temp.end());
304     vector<int> yj(temp.begin(), temp.begin() + 100);
305     //sort(yj.begin(), yj.end());
306 
307     
308     //copy(yj.begin(), yj.end(), OstreamItr(cout, " "));
309     //cout << endl;
310     
311     start = clock();
312     //sort(yj.begin(), yj.end());
313     sort_quick(yj);
314     finish = clock();
315     cout << (double)(finish - start) / CLOCKS_PER_SEC << " s" << endl;
316     copy(yj.begin(), yj.begin() + 20, OstreamItr(cout, " "));
317     cout << endl;
318     return 0;
319 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-08-20 17:39  技术人员kelvin  阅读(158)  评论(0)    收藏  举报