各种排序的算法实现代码
1 //选择排序法 2 template<typename T> 3 void selectSort(T * arr,int n) 4 { 5 for(int i=0;i<n;i++) 6 { 7 int min=i; 8 for(int j=i;j<n;j++) 9 { 10 //内循环找最小的那个值 11 if(arr[j]<arr[min]) 12 { 13 min=j; 14 } 15 } 16 if(i!=min) 17 { 18 swap(arr[i],arr[min]); 19 } 20 } 21 } 22 23 //插入排序版本1,性能略差 24 void insertSort1(int * arr,int n) 25 { 26 for(int i=1;i<n;i++) 27 { 28 for(int j=i;j>0&&arr[j]<arr[j-1];j--) 29 { 30 swap(arr[j],arr[j-1]); 31 } 32 } 33 } 34 35 void __insertSort(int * arr,int left,int right) 36 { 37 for(int i=left;i<=right;i++) 38 { 39 int data=arr[i]; 40 int j=i; 41 for(;j>0&&arr[j-1]>data;--j) 42 arr[j]=arr[j-1]; 43 arr[j]=data; 44 } 45 } 46 47 //插入排序版本2,性能强多了 48 void insertSort2(int * arr,int n) 49 { 50 __insertSort(arr,0,n); 51 } 52 53 54 55 //归并排序核心逻辑部分,这里需要将arr[left]-arr[mid]的区域和arr[mid+1]-arr[right]进行合并 56 template<typename T> 57 void __merge(T* arr,int left,int mid,int right) 58 { 59 T arrns[right-left+1];//相当于是arr[数组长度]的情况,创建一个新的数组用来存放合并后的结果 60 for(int i=left;i<=right;i++) 61 { 62 //先将数据都拷贝到新的数组中 63 arrns[i-left]=arr[i]; 64 } 65 //左边数组的开始位置 66 int l=left; 67 //右边数组的开始位置 68 int r=mid+1; 69 for(int i=left;i<=right;i++) 70 { 71 72 //如果左边的数组已经全部合并完了,则将右边的下一个节点直接添加上去 73 if(l>mid) 74 { 75 arr[i]=arrns[r-left]; 76 r++; 77 continue; 78 } 79 //如果右边的数组已经全部合并完了,则将左边的下一个节点添加上去 80 else if(r>right) 81 { 82 arr[i]=arrns[l-left]; 83 l++; 84 continue; 85 } 86 //如果左边列表当前节点小于右边列表当前节点。则将左边的节点添加上去 87 if(arrns[l-left]<arrns[r-left]) 88 { 89 arr[i]=arrns[l-left]; 90 l++; 91 } 92 else 93 { 94 //否则将右边的节点添加上去 95 arr[i]=arrns[r-left]; 96 r++; 97 } 98 } 99 100 } 101 102 //归并排序私有函数 103 template<typename T> 104 void __mergeSort(T *arr,int left,int right) 105 { 106 if(left>=right) 107 return; 108 int m=(left+right)/2; 109 __mergeSort(arr,left,m); 110 __mergeSort(arr,m+1,right); 111 __merge(arr,left,m,right); 112 } 113 114 //归并排序优化版本2 115 template<typename T> 116 void __mergeSort2(T *arr,int left,int right) 117 { 118 //将数量小于15的分治排序使用插入排序算法进行处理 119 if(right-left<=15) 120 { 121 __insertSort(arr,left,right); 122 return; 123 } 124 125 int m=(left+right)/2; 126 __mergeSort(arr,left,m); 127 __mergeSort(arr,m+1,right); 128 //如果不符合说明右边的第一个值比左边的最后一个值都大,则可以无需归并 129 if(arr[m]>arr[m+1]) 130 { 131 __merge(arr,left,m,right); 132 } 133 } 134 135 136 //归并排序 137 void mergeSort(int* arr,int n) 138 { 139 __mergeSort(arr,0,n-1); 140 } 141 142 //归并排序自底向上 143 void mergeSortByU(int* arr,int n) 144 { 145 for(int sz=1;sz<=n;sz+=sz) 146 { 147 for(int sk=0;sk+sz<n;sk+=sz+sz) 148 { 149 __merge(arr,sk,sk+sz-1,min(sk+sz+sz-1,n-1)); 150 } 151 } 152 } 153 154 155 156 //单路快排关键部分 157 template<typename T> 158 int __partition(T *arr,int left,int right) 159 { 160 //随机一个有效范围的值 161 int idx=rand()%(right-left+1)+left; 162 //将第一个值和随机的交换,这样避免了在近乎有序的情况下使用快排太慢的情况 163 swap(arr[idx],arr[left]); 164 165 T data=arr[left]; 166 int gidx=left; 167 for(int i=left+1;i<=right;i++) 168 { 169 if(arr[i]>=data) 170 swap(arr[++gidx],arr[i]); 171 } 172 swap(arr[left],arr[gidx]); 173 174 return gidx; 175 } 176 177 //单路快排,快排的最初版本,效率还达不到我们的期望 178 template<typename T> 179 void __quickSortSig(T* arr,int left,int right) 180 { 181 //同样可以优化为当需要排序的长度小于15个时使用插入算法排序 182 if(right-left<=15) 183 { 184 __insertSort(arr,left,right); 185 return; 186 } 187 188 int idx=__partition(arr,left,right); 189 __quickSortSig(arr,left,idx-1); 190 __quickSortSig(arr,idx+1,right); 191 } 192 193 194 195 196 //快速排序,现今最快的排序,最开始的单路排序 197 void quickSortSig(int* arr,int n) 198 { 199 srand(time(NULL)); 200 __quickSortSig(arr,0,n-1); 201 } 202 203 204 template<typename T> 205 int __partition_double(T *arr,int left,int right) 206 { 207 //随机一个有效范围的值 208 int idx=rand()%(right-left+1)+left; 209 //将第一个值和随机的交换,这样避免了在近乎有序的情况下使用快排太慢的情况 210 swap(arr[idx],arr[left]); 211 212 T data=arr[left]; 213 int gtidx=left+1; 214 int ltidx=right; 215 216 while(true) 217 { 218 while(arr[gtidx]<data&>idx<=right) 219 gtidx++; 220 while(arr[ltidx]>data&<idx>=left+1) 221 ltidx--; 222 if(gtidx>ltidx) 223 break; 224 swap(arr[gtidx],arr[ltidx]); 225 gtidx++; 226 ltidx--; 227 } 228 229 swap(arr[left],arr[gtidx]); 230 231 return gtidx; 232 } 233 234 235 //双路快排版本 236 void __quickSortDouble(int* arr,int left,int right) 237 { 238 if(right-left<=10) 239 { 240 __insertSort(arr,left,right); 241 return; 242 } 243 int idx=__partition_double(arr,left,right); 244 __quickSortDouble(arr,left,idx-1); 245 __quickSortDouble(arr,idx+1,right); 246 } 247 248 //快速排序,现今最快的排序,双路快排版本 249 void quickSortDouble(int* arr,int n) 250 { 251 srand(time(NULL)); 252 __quickSortDouble(arr,0,n-1); 253 } 254 255 256 257 //三路快排版本 258 template<typename T> 259 void __quickSortThree(T* arr,int left,int right) 260 { 261 if(right-left<=15) 262 { 263 __insertSort(arr,left,right); 264 return; 265 } 266 267 //随机一个有效范围的值 268 int ridx=rand()%(right-left+1)+left; 269 //将第一个值和随机的交换,这样避免了在近乎有序的情况下使用快排太慢的情况 270 swap(arr[ridx],arr[left]); 271 T data=arr[left]; 272 int gtidx=left; //left+1~gtidx 的值小于data 273 int ltidx=right+1; //ltidx~right的值大于data 274 int idx=left+1; //gtidx+1~idx的值等于data 275 276 while(idx<ltidx) 277 { 278 if(arr[idx]<data) 279 { 280 swap(arr[idx],arr[gtidx+1]); 281 gtidx++; 282 idx++; 283 } 284 else if(arr[idx]>data) 285 { 286 swap(arr[idx],arr[ltidx-1]); 287 ltidx--; 288 } 289 else 290 { 291 idx++; 292 } 293 } 294 swap(arr[left],arr[gtidx]); 295 __quickSortDouble(arr,left,gtidx-1); 296 __quickSortDouble(arr,ltidx,right); 297 298 } 299 300 //三路快排法 301 void quickSortThree(int* arr,int n) 302 { 303 srand(time(NULL)); 304 __quickSortThree(arr,0,n-1); 305 }