Chinaunix首页 | 论坛 | 博客
  • 博客访问: 505369
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1172
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-21 13:40
个人简介

技术改变命运

文章分类

全部博文(184)

文章存档

2020年(16)

2017年(12)

2016年(156)

我的朋友

分类: C/C++

2016-07-04 00:19:51

 考虑一个数组,或者更一般的一个字数组A[l...r](0≤l≤r≤n-1),该数组由连续的3段组成。这3段按顺序排在中轴p的后面:一段为已知小于p的元素,一段为已知大于或等于p的元素,还有一段未同p比较过的元素。这些段可以为空,在算法开始时,前两段通常是空的。
在i= l+1开始,算法从左到右扫面字数组A[l...r],并保持这个结构直到划分完成。在每一次迭代中,它把未知段中的第一个元素与中轴p进行对比。如果A[i] >= p,则只要i+1就扩大了大于等于p元素的段,而同时缩小了未处理的段。  求数组中最小的k个数(c代码如下)

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define swap(t,x,y) (t = (x),x = (y),y = (t))
  4. int position = 0;
  5. int lomutopartition(int *a,int lo,int hi)
  6. {
  7.     int p =a[lo];
  8.     int i = lo+1,s = lo,temp = 0;
  9.     for (i = lo+1;i < hi;i++)
  10.     {
  11.         if (a[i] < p)
  12.         {
  13.             s = s+1;
  14.             swap(temp,a[i],a[s]);
  15.         }
  16.     }
  17.     swap(temp,a[lo],a[s]);
  18.     return s;
  19. }
  20. int quickselect(int *a,int lo,int hi,int k)
  21. {
  22.     int s = lomutopartition(a,lo,hi);
  23.     if (s == lo+k-1){ position=s; return a[s];}
  24.     else if (s > lo+k-1) quickselect(a,lo,s-1,k);
  25.     else quickselect(a,s+1,hi,lo+k-1-s);
  26.     
  27. }//这里lo很重要,不写会出现段错误
  28. int main()
  29. {
  30.     int len = 0;
  31.     scanf("%d",&len);

  32.     
  33.     int a[len];
  34.     int i = 0;
  35.     for (i = 0;i < len;i++)
  36.     {
  37.         printf("请输入第%d个元素",i+1);
  38.         scanf("%d",&a[i]);
  39.     }
  40.     int k = 0;
  41.     printf("请输入k的值");
  42.     scanf("%d",&k);
  43. //    int a[5] = {1,2,3,4,5};
  44.     int result = quickselect(a,0,len-1,k);
  45.     for (i = 0;i < position+1;i++)
  46.     {
  47.         printf("%d\n",a[i]);
  48.     }
  49. //int i = 0;
  50. /*    do{
  51.         printf("a[%d] = %d\n",i,a[i]);
  52.         i++;
  53.     }while(i < position);*/
  54. //    printf("position = %d\n",position);
  55. //    printf("result = %d\n",result);
  56.     return 0;
  57. }
如果A[i] < p,则小于p元素的段需要扩大,这将通过s +1来实现。s是指向第一段中最后一个元素,再交换A[i]与A[s],然后i+1,使i指向缩小后的未处理段的第一个元素,在未处理元素为空时,算法把中轴与A[s]交换,就得到了一个我们所要求的划分。(快排的另一种划分)
运行如下(centos5.5)
[root@localhost ~]# ./a.out
5
请输入第1个元素3
请输入第2个元素2
请输入第3个元素1
请输入第4个元素4
请输入第5个元素5
请输入k的值3
1
2
3
2)奇数偶数排序:
    给定一个整数数组,请调整数组中暑的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分,要求时间复杂度唯一
划分三部分
奇数部分 偶数部分 未处理部分,与上一题如出一辙
c代码如下:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define swap(t,x,y) (t = (x),x = (y),y = (t))
  4. /*int evenOrOdd(int i)//判断奇数 偶数
  5. {
  6.     if (i % 2 != 0)
  7.         return 1;
  8.     else
  9.         return 0;
  10. }*/
  11. int evenOrOdd(int i)//这种方式比上一种快许多
  12. {
  13.     if ( (data  & 1) == 1)
  14.         return 1;
  15.     else
  16.         return 0;
  17. }
  18. void sort(int *a,int lo,int hi)
  19. {
  20.     int pivot = a[0];//是奇数还是偶数不重要
  21.     int i = lo+1;
  22.     int s = 0;
  23.     int temp = 0;
  24.     for (i = lo+1;i < hi;i++)
  25.     {
  26.         if (evenOrOdd(a[i]))
  27.         {
  28.             s = s+1;
  29.             swap(temp,a[s],a[i]);
  30.         }
  31. //        printf("%d\n",a[i]);
  32.     }
  33.     swap(temp,a[lo],a[s]);
  34.     // i = 0;
  35. //    printf("%d",a[0]);
  36. }
  37. int main()
  38. {
  39.     int a[] = {1,2,3,4,5};
  40.     sort(a,0,5);
  41.     int i = 0;
  42.     for (i = 0;i < 5;i++)
  43.         printf("%d ",a[i]);
  44.     printf("\n");
  45.     return 0;
  46. }
[root@localhost ~]# ./a.out
5 3 1 4 2 
[root@localhost ~]# 




阅读(1398) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~