第一种:选择排序
第二种:冒泡排序、改进冒泡排序
第三种:插入排序
第四种:快速排序--->升级版 随即快速排序
第五种:归并排序
第六种:希尔排序
第七种:桶排序(直接下标排序,适合数据范围较小的)
第八种:堆排序(学会手写堆的操作函数,堆调整、删除添加元素等等)
快速排序和归并排序都用到了二分,但是快速排序是先排后递归,归并排序是先二分递归再排(需要两个数组)
#include<iostream> #include<cstring> using namespace std; const int MAXN=1000; int a[MAXN]; int n; //选择排序 void xuanze(){ int k; for(int i=0;i<n;i++){ k=i; for(int j=i+1;j<n;j++) if(a[j]<a[k]) k=j; //注意是a[j]<a[[k] if(k!=i) { swap(a[i],a[k]); } } cout<<"选择排序如下: "; for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; } //冒泡排序 void maopao(){ for(int i=n-1;i>=1;i--){ for(int j=0;j<i;j++){ if(a[j]>a[j+1]) swap(a[j],a[j+1]); } } cout<<"冒泡排序如下: "; for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; } //改进冒泡排序 void impmaopao(){ bool ok; for(int i=n-1;i>=1;i--){ ok=true; for(int j=0;j<i;j++){ if(a[j]>a[j+1]) { swap(a[j],a[j+1]); ok=false; } } if(ok==true) break; } cout<<"改进冒泡排序如下: "; for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; } //插入排序 void charu(){ int temp=0,k,i,j; for( i=1;i<n;i++){ for(j=i-1;j>=0;j--){ if(a[j]<a[i]) break; } if(j!=i-1){ temp=a[i]; for(k=i-1;k>j;k--) a[k+1]=a[k]; a[k+1]=temp; } } cout<<"插入排序如下: "; for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; } //快速排序 void qsort(int l,int r){ int i,j,mid; i=l;j=r; mid=a[(l+r)/2]; do{ while(a[i]<mid) i++; while(a[j]>mid) j--; if(i<=j){ swap(a[i],a[j]); i++;j--; } }while(i<=j); if(l<j) qsort(l,j); if(i<r) qsort(i,r); } //归并排序 int r[MAXN];//辅助数组 int ans=0; //逆序数 void msort(int s,int t){ if(s==t) return; //只有一个元素时不需要比较 int mid=(s+t)/2; msort(s,mid); //分解左序列 msort(mid+1,t); //分解右序列 int i=s,j=mid+1,k=s; //合并,注意k的初始值不是为0 while(i<=mid&&j<=t){ if(a[i]<=a[j]) r[k++]=a[i++]; else { r[k++]=a[j++]; ans+=mid-i+1; } } while(i<=mid) r[k++]=a[i++]; while(j<=t) r[k++]=a[j++]; for(int i=s;i<=t;i++) a[i]=r[i]; //注意i的起始和终止值 } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; //快速排序和归并排序从i=1开始 //xuanze(); //maopao(); //impmaopao(); //charu(); /*qsort(1,n); cout<<"快速排序如下: "; for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl; */ msort(1,n); cout<<"归并排序如下: "; for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl; return 0; }
希尔排序的概念:
希尔排序(Shellsort)也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。希尔(Donald Shell)于1959年提出这种排序算法。
希尔排序是非稳定排序算法。
二、图解希尔排序的基本思想:
希尔排序是把数据序列按下标的一定增量分组,对每组使用直接插入排序算法排序;
随着增量逐渐减少,每组包含的数据个数越来越多,当增量减至1时,整个文件恰被分成一组,整个数据序列就已经排序好了,算法便终止。
原文链接:https://blog.csdn.net/qq_33479129/article/details/110599751
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1010; const int INF=0x3fffffff; typedef long long LL; typedef unsigned long long ull; int a[maxn]; void shellsort(int length){ int gap=0,temp; int i,j; for(gap=length/2;gap>=1;gap/=2){ for(i=gap;i<length;i++){ temp=a[i]; for(j=i-gap;j>=0&&temp<a[j];j=j-gap){ a[j+gap]=a[j]; } a[j+gap]=temp; } } } int main(){ int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; shellsort(n); for(int i=0;i<n;i++) cout<<a[i]<<" "; return 0; }
第七种:桶排序
适用于数字范围较小的
1184:明明的随机数
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n; int a[101]; int b[1001]; int main(){ cin>>n; int m=0; memset(b,0,sizeof(b)); for(int i=0;i<n;i++){ cin>>a[i]; if(b[a[i]]==0) m++; b[a[i]]++; } cout<<m<<endl; for(int i=0;i<=1000;i++){ if(b[i]!=0) cout<<i<<" "; } cout<<endl; return 0; }
第八种:堆排序(基本的堆的操作)
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> using namespace std; //堆排序 //小根堆 int n,heap[100001]; //堆调整 void heapadjust(int x,int high){ //后面的high必须要有 int i=x,j=2*i; while(j<=high){ if((j+1<=high)&&heap[j]>heap[j+1]) j++; if(heap[j]<heap[i]){ swap(heap[i],heap[j]); i=j; j=2*i; } else break; } } //删除堆顶元素 int delete(){ int ans=heap[1]; heap[1]=heap[n--]; heapadjust(1,n); return ans; } //添加堆顶元素 void insert(int x){ heap[++n]=x; heapadjust(1,n);//向上调整新加入的节点 } //建堆 void heapsort(){ for(int i=n/2;i>=1;i--) heapadjust(i,n); //建立一个初始小根堆 for(int i=n;i>1;i--){ swap(heap[1],heap[i]); //将最后一个与第一个交换,最小值到了最后 heapadjust(1,i-1); } } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>heap[i]; heapsort(); for(int i=n;i>1;i--) cout<<heap[i]<<" "; cout<<heap[1]<<endl; return 0; }
随机选择算法
求出无序序列中第k大的数
利用随机选择排序的函数,因为快速排序是查找一个数左边有多少小于他即temp,如果小于他就往后走,直到>temp,右边也是查找有多少大于temp,如果大于就往前走,直到<temp,这个时候才交换这两个指针指向的对象,这里就可以用来判断有多少值是小于temp的,即temp是第几大的。
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> using namespace std; typedef long long LL; int a[1010]; int randpar(int left,int right){ int p=round(1.0*rand()/RAND_MAX*(right-left)+left); swap(a[p],a[left]); int temp=a[left]; while(left<right){ while(left<right&&a[right]>temp) right--; a[left]=a[right]; while(left<right&&a[left]<=temp) left++; a[right]=a[left]; } a[left]=temp; return left; } //int randsel(int left,int right,int k){ // if(left==right) return a[left]; // int p=randpar(left,right); // int m=p-left+1; // if(m==k) return a[p]; // if(k<m){ //在左侧 // return randsel(left,p-1,k); // } // else return randsel(p+1,right,k-m); //} /* 8 3 7 6 9 3 1 5 2 4 */ void randsel(int l,int r){ if(l>r) return; int p=randpar(l,r); randsel(l,p-1); randsel(p+1,r); } int main(){ int n,k; cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i]; } // cout<<randsel(1,n,k); randsel(1,n); for(int i=1;i<=n;i++) cout<<a[i]<<" "; return 0; }