排序算法
冒泡排序、选择排序、插入排序的算法复杂度都是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 }

浙公网安备 33010602011771号