[学习记录]排序算法总结

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.选择排序

最接近人的思维,从全局挑一最小的放第一,再挑个第二的放第二,这里不放代码了。

猜你喜欢

转载自www.cnblogs.com/trickofjoker/p/10495915.html
今日推荐