选择排序、插入排序及优化、归并排序、三路快排、

各种排序的算法实现代码

 

  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&&gtidx<=right)
219             gtidx++;
220         while(arr[ltidx]>data&&ltidx>=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 }

 

转载于:https://www.cnblogs.com/kings0/p/6418727.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值