[学习记录]排序算法总结
1.桶排序
准备一个已经确定顺序的序列,要求被排序的元素为有序序列的子集,挨个对应之后按照顺序取出就是桶排序了
1 #include<stdio.h> 2 int max(int* a,int len); 3 int main() 4 { 5 int a[10]={5,4,6,8,1,2,3,3,12,7}; 6 int len=10; 7 //获取数组中最大值,即桶的上限 8 int maxnum=max(a,len); 9 int b[50]={0}; 10 //向桶中放入元素 11 for(int i=0;i<len;i++) 12 { 13 b[a[i]]++; 14 } 15 //按照桶的顺序依次取出 16 for(int i=0;i<=len;i++) 17 { 18 for(int j=0;j<b[i];j++) 19 printf("%d ",i); 20 } 21 return 0; 22 } 23 int max(int* a,int len) 24 { 25 int max=-10; 26 for(int i=0;i<len;i++) 27 { 28 if (max<a[i]) 29 { 30 max=a[i]; 31 } 32 } 33 return max; 34 }
缺点:对于空间跨度较大的序列,空间利用率极低
2.冒泡排序
对于从小到大的顺序,我们从最后一位向前遍历,凡是发现逆序的相邻元素便交换位置,一路交换到头则一定会把最小的元素放到首位,这样最多重复n(元素总数量)次即可完成排序
1 #include<stdio.h> 2 void swap(int* a,int* b); 3 int main() 4 { 5 int a[10]={5,4,6,8,1,2,3,3,12,7}; 6 int len=10; 7 for(int i=0;i<len;i++) 8 { 9 for(int j=len-1;j>0;j--) 10 if(a[j]<a[j-1]) 11 swap(&a[j],&a[j-1]); 12 } 13 for(int i=0;i<len;i++) 14 { 15 printf("%d ",a[i]); 16 } 17 return 0; 18 } 19 //注意指针 20 void swap(int* a,int* b) 21 { 22 int t=*a; 23 *a=*b; 24 *b=t; 25 }
3.快速排序
基本思想为,一次排序似的数据分成两个部分,并且保证其中一部分的所有元素都大于另一部分的所有元素。
在一次排序中首先选择一个基准元素作为判断值,比它大的放一边,小的放另一边。
这里我们永远把第一个元素作为基准,指针i从第二个元素向后寻找,遇到第一个不小于基准的元素就停下,指针j从最后一个元素向前找,遇到第一个小于基准的元素则停下,当IJ都停下后交换元素。
然后继续搜索,直到IJ交叉,最后基准与当前J位置元素交换,并且把0-J分成新部分,I-N分为另一部分,重复排序过程。
1 #include<stdio.h> 2 void qs(int* a,int l,int r); 3 int main() 4 { 5 int a[10]={5,4,6,8,1,2,3,3,12,7}; 6 int len=10; 7 qs(a,0,9); 8 for(int i=0;i<len;i++) 9 { 10 printf("%d ",a[i]); 11 } 12 return 0; 13 } 14 //注意!当基准值为min或max时的情况处理 15 16 void qs(int* a,int l,int r) 17 { 18 //printf("%d %d\n",l,r); 19 int mid=a[l]; 20 int i=l+1; 21 int j=r; 22 while(i<j) 23 { 24 //重点:前向后 25 while((i<=r)&&(a[i]<mid)) 26 i++; 27 //重点:后向前 28 while((j>=l+1)&&(a[j]>=mid)) 29 j--; 30 if(j>i) 31 { 32 int t=a[j]; 33 a[j] = a[i]; 34 a[i] = t; 35 j--; 36 i++; 37 } 38 } 39 //为了避免i=j时候出现bug,卡在0,1无限递归 40 if(i==j) 41 j--; 42 int t=a[l]; 43 a[l] = a[j]; 44 a[j] = t; 45 46 if(j>l) 47 qs(a,l,j); 48 if(i<r) 49 qs(a,i,r); 50 }
同时由于分治的策略,快排可以使用并行计算的方法提高速度。
4.插入排序
认为左部分开始都是排好序的,每次循环从右部分第一个开始向前比较,如果小就前移直到移动到合适的位置
1 #include<stdio.h> 2 void qs(int* a,int l,int r); 3 int main() 4 { 5 int a[10]={5,4,6,8,1,2,3,3,12,7}; 6 int len=10; 7 for(int i=1;i<len;i++) 8 { 9 int j=i; 10 while((j>0)&&(a[j]<a[j-1])) 11 { 12 int t=a[j]; 13 a[j]=a[j-1]; 14 a[j-1]=t; 15 j--; 16 } 17 } 18 for(int i=0;i<len;i++) 19 { 20 printf("%d ",a[i]); 21 } 22 return 0; 23 }
5.希尔排序
希尔排序为插入排序的一种改良,通过一定的步长将原序列分组进行排序,旨在减少部分不必要的交换次数
1 #include<stdio.h> 2 void qs(int* a,int l,int r); 3 int main() 4 { 5 int a[10]={5,4,6,8,1,2,3,3,12,7}; 6 int len=10; 7 //按照长度的一半进行分组,下一次再减半 8 for(int i=len/2;i>=1;i=i/2) 9 { 10 //每次排序共有i-1个组 11 for(int j=0;j<i;j++) 12 { 13 //遍历本组的所有元素,插入排序 14 for(int k=i;k<len;k=k+i) 15 { 16 while((k>0)&&(a[k]<a[k-i])) 17 { 18 int t=a[k]; 19 a[k]=a[k-i]; 20 a[k-i]=t; 21 k=k-i; 22 } 23 } 24 } 25 } 26 for(int i=0;i<len;i++) 27 { 28 printf("%d ",a[i]); 29 } 30 return 0; 31 }
6.选择排序
最接近人的思维,从全局挑一最小的放第一,再挑个第二的放第二,这里不放代码了。