1 /************ 2 十大排序算法 3 ***********/ 4 5 #include<iostream> 6 #include<ctime> 7 using namespace std; 8 9 typedef int T; 10 11 void swap(T &x,T &y) 12 { 13 T temp; 14 temp=x; 15 x=y; 16 y=temp; 17 } 18 //1,冒泡 原地稳定 o(n^2) 19 void bubble(T *a, int n) 20 { 21 for(int i=0;i<n-1;i++) 22 for(int j=0;j<n-1-i;j++) 23 { 24 if(a[j]>a[j+1]) 25 swap(a[j],a[j+1]); 26 } 27 } 28 29 void improvebubble(T *a, int n) 30 { 31 bool over=true;//作指示,若有一次没交换就结束 32 for(int i=0;i<n-1&&over;i++) 33 { 34 over =false; 35 for(int j=0;j<n-1-i;j++) 36 if(a[j]>a[j+1]) 37 { 38 swap(a[j],a[j+1]); 39 over=true; 40 } 41 } 42 } 43 //2,插排 原地稳定 o(T)=1+2+3+..+n-1=o(n^2) 44 void insert1(T *a,int n) 45 { 46 for(int i=1;i<n;i++) 47 { 48 T temp=a[i]; 49 int j; 50 for(j=i-1;j>=0;j--)//和前面抽出来有序的比较 51 { 52 if(a[j]<=temp) 53 break; 54 a[j+1]=a[j]; 55 } 56 a[j]=temp; 57 } 58 } 59 60 int findpos(T *a,int n, T key) 61 { 62 int high=n-1,low=0; 63 while(low<=high)//***这里要有等号,不然high=low(即排查到只剩一个数时)就不判断直接排在前面了 64 { 65 int mid=(high+low)/2; 66 if(key>=a[mid]) //如果相等,定位到其后面,保证稳定排序 67 low=mid+1; 68 else if (key<a[mid]) 69 high=mid-1; 70 } 71 72 return low; 73 } 74 void insert2(T *a,int n) 75 { 76 for(int i=1;i<n;i++) 77 { 78 T temp=a[i]; 79 int pos=findpos(a,i,temp); 80 for(int j=i-1;j>=pos;j--) 81 { 82 a[j+1]=a[j]; 83 } 84 a[pos]=temp; 85 cout<<pos<<endl; 86 for(int i=0;i<n;i++) 87 cout<<a[i]; 88 cout<<endl; 89 } 90 } 91 92 93 //3,选择排序 原地不稳定,一次选一个最小的, o(n^2) 94 void select(T *a,int n) 95 { 96 for(int i=0;i<n-1;i++) 97 { 98 T min=a[i]; 99 int k=i;//重要一定要让k=i 100 for(int j=i+1;j<n;j++) 101 { 102 if(min>a[j])//找最小的 103 { 104 min=a[j]; 105 k=j; 106 } 107 } 108 if(i!=k)//重要 109 swap(a[i],a[k]);//不稳定,比如a[i]不是最小的,它与最小发生交换,打乱了它自己的位置 110 111 } 112 } 113 //4.归并排序 非原地稳定 o(nlogn), 需要开辟o(n)的空间 114 //分治法,每次一分为二,最后将俩部分合并排序 115 void MergeSort(T *a,int f,int r,int mid) 116 { 117 int i=f,j=mid+1; 118 int m=mid,n=r; 119 int k=0; 120 T *temp=new T[r-f+1];//非原地排序,用来合并数组 121 122 while(i<=m && j<=n) 123 { 124 if(a[i]<=a[j])//这里等号可保证稳定 125 temp[k++]=a[i++]; 126 else 127 temp[k++]=a[j++]; 128 } 129 while(i<=m) 130 temp[k++]=a[i++]; 131 while(j<=n) 132 temp[k++]=a[j++]; 133 for(i=0;i<k;i++)//数组a局部有序 134 a[f+i]=temp[i]; 135 136 delete [] temp; 137 } 138 139 void Merge(T *a,int f,int r) 140 { 141 if(f<r) 142 { 143 int mid=(f+r)/2; 144 Merge(a,f,mid); 145 Merge(a,mid+1,r); 146 MergeSort(a,f,r,mid); 147 } 148 } 149 void merge(T *a, int n) 150 { 151 Merge(a,0,n-1); 152 } 153 154 //5.快排,原地不稳定 o(nlogn) 155 void Quick(T *a,int f,int r) 156 { 157 if(f>=r) 158 return; 159 int i=f,j=r; 160 T temp=a[f];//第一个坑 161 while(i<j) 162 { 163 while(temp<=a[j] && i<j)//有可能越界 164 j--; 165 if(i<j)//如果俩者相遇,即跑到挖的坑那了 166 a[i++]=a[j];//后面的小的数填前面的坑 167 while(temp>a[i] && i<j) 168 i++; 169 if(i<j) 170 a[j--]=a[i];//用前面的大的数填后面的坑 171 } 172 a[i]=temp;//最后一坑 173 Quick(a,f,i); 174 Quick(a,i+1,r); 175 } 176 void quick(T*a,int n) 177 { 178 Quick(a,0,n-1); 179 } 180 181 //6.计数排序 182 //只能是整数(或字符)排序,而且要求分布比较均匀,非原地稳定 183 //好处是o(n)线性复杂度,方便序列去重操作 184 void count(T *a,int n) 185 { 186 T max=a[0],min=a[0]; 187 int i; 188 for(i=0;i<n;i++)//找到序列最小值,以确定桶大小 189 { 190 if(max<a[i]) 191 max=a[i]; 192 if(min>a[i]) 193 min=a[i]; 194 } 195 int len=max-min+1; 196 T* C=new T[len];//记录每个数出现的次数 197 for(i=0;i<len;i++) 198 C[i]=0; 199 for(i=0;i<n;i++) 200 C[a[i]-min]+=1; 201 for(i=1;i<len;i++) 202 C[i]+=C[i-1]; 203 204 T *R=new T[n];// 205 for(i=n-1;i>=0;i--)//倒着来取可保证稳定排序,后面的还排在后面 206 { 207 T temp=a[i]; 208 int pos=C[temp-min]; 209 R[pos-1]=temp;//注意这的减一.C统计的的是个数,R是从0开始存储的 210 C[temp-min]--; 211 } 212 213 for(i=0;i<n;i++) 214 a[i]=R[i]; 215 216 delete [] C; 217 delete [] R; 218 } 219 //7,希尔排序 分组排序 原地不稳定 220 //数组基本有序的情况下更好 221 void shell1(T *a, int n) 222 { 223 for(int gap=n/2;gap>0;gap/=2) //log n 224 for(int i=gap;i<n;i++)//gap=1就是insertSort o(n/gap) 225 for(int j=i-gap;j>=0 && a[j]>a[j+gap];j-=gap) 226 swap(a[j+gap],a[j]);//或者可以先后推找到位置,最后填进去 227 } 228 229 void shell2(T *a,int n)//??不理解 o(nlogn) 230 { 231 int d=n; 232 while(d>1) 233 { 234 d=(d+1)/2; 235 for(int i=0;i<n-d;i++) 236 if(a[i+d]<a[i]) 237 swap(a[i+d],a[i]); 238 } 239 } 240 241 242 //8,堆排序 大根堆,向下调整 o(nlogn) 原地不稳定 适合处理大文件 243 void shiftdown(T *a,int n,int i)// 244 { 245 int t,flag=0; 246 while(2*i+1<n && flag==0)//以0为根节点,左右孩子是2i+1,2i+2 247 { 248 if(a[i]<a[2*i+1]) 249 t=2*i+1; 250 else t=i; 251 if(2*i+2<n)//n是节点数,从1开始计的,而i是从0开始计的 252 if(a[t]<a[2*i+2]) 253 t=2*i+2; 254 if(t!=i) 255 { 256 swap(a[i],a[t]); 257 i=t;//继续往下调整 258 } 259 else flag=1; 260 } 261 } 262 263 void createMaxHeap(T *a,int n)//建立大根堆,o(n/2) 264 { 265 for(int i=n/2;i>=0;i--)//父节点向下调整 266 shiftdown(a,n,i); 267 } 268 269 void heapsort(T *a, int n) 270 { 271 createMaxHeap(a,n); 272 int k=n-1; 273 while(k>0) 274 { 275 swap(a[k],a[0]); 276 k--; 277 shiftdown(a,k,0);//o(logk) 278 } 279 } 280 281 int main() 282 { 283 const int n=15; 284 int a[n]={4,6,5,3,2,1,4,5,6,7,2,8,9,3,1}; 285 shell2(a,n); 286 for(int i=0;i<n;i++) 287 cout<<a[i]; 288 cout<<endl; 289 return 0; 290 }
时间: 2024-10-29 19:05:45