Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141158
  • 博文数量: 56
  • 博客积分: 245
  • 博客等级: 二等列兵
  • 技术积分: 520
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-08 14:43
个人简介

慢慢来

文章分类

全部博文(56)

文章存档

2017年(5)

2016年(2)

2015年(6)

2014年(28)

2013年(5)

2012年(10)

我的朋友

分类: C/C++

2015-02-09 19:57:12

接STEP-8, 需求是一样的,SELECT算法的最坏复杂度是O(n?),快速SELECT算法是最坏情况为线性时间的选择算法。

快速SELECT是为了解决在RANDOM SELECT算法中的最坏情况,即每次都取最大/最小 值作为pivot。




* 箭头为 大->小。 阴影部分为确定比X大的部分

点击(此处)折叠或打开

  1. //copyright@ yansha && July && 飞羽
  2. //July、updated,2011.05.19.清晨。
  3. //版权所有,引用必须注明出处:http://blog.csdn.net/v_JULY_v。
  4. #include <iostream>
  5. #include <time.h>
  6. using namespace std;
  7.   
  8. const int num_array = 13;
  9. const int num_med_array = num_array / 5 + 1;
  10. int array[num_array];
  11. int midian_array[num_med_array];
  12.   
  13. //冒泡排序(晚些时候将修正为插入排序)
  14. /*void insert_sort(int array[], int left, int loop_times, int compare_times)
  15. {
  16.     for (int i = 0; i < loop_times; i++)
  17.     {
  18.         for (int j = 0; j < compare_times - i; j++)
  19.         {
  20.             if (array[left + j] > array[left + j + 1])
  21.                 swap(array[left + j], array[left + j + 1]);
  22.         }
  23.     }
  24. }*/
  25.   
  26. /*
  27. //插入排序算法伪代码
  28. INSERTION-SORT(A) cost times
  29. 1 for j ← 2 to length[A] c1 n
  30. 2 do key ← A[j] c2 n - 1
  31. 3 Insert A[j] into the sorted sequence A[1 ‥ j - 1]. 0...n - 1
  32. 4 i ← j - 1 c4 n - 1
  33. 5 while i > 0 and A[i] > key c5
  34. 6 do A[i + 1] ← A[i] c6
  35. 7 i ← i - 1 c7
  36. 8 A[i + 1] ← key c8 n - 1
  37. */
  38. //已修正为插入排序,如下:
  39. void insert_sort(int array[], int left, int loop_times)
  40. {
  41.     for (int j = left; j < left+loop_times; j++)
  42.     {
  43.         int key = array[j];
  44.         int i = j-1;
  45.         while ( i>left && array[i]>key )
  46.         {
  47.             array[i+1] = array[i];
  48.             i--;
  49.         }
  50.         array[i+1] = key;
  51.     }
  52. }
  53.   
  54. int find_median(int array[], int left, int right)
  55. {
  56.     if (left == right)
  57.         return array[left];
  58.       
  59.     int index;
  60.     for (index = left; index < right - 5; index += 5)
  61.     {
  62.         insert_sort(array, index, 4);
  63.         int num = index - left;
  64.         midian_array[num / 5] = array[index + 2];
  65.     }
  66.       
  67.     // 处理剩余元素
  68.     int remain_num = right - index + 1;
  69.     if (remain_num > 0)
  70.     {
  71.         insert_sort(array, index, remain_num - 1);
  72.         int num = index - left;
  73.         midian_array[num / 5] = array[index + remain_num / 2];
  74.     }
  75.       
  76.     int elem_aux_array = (right - left) / 5 - 1;
  77.     if ((right - left) % 5 != 0)
  78.         elem_aux_array++;
  79.       
  80.     // 如果剩余一个元素返回,否则继续递归
  81.     if (elem_aux_array == 0)
  82.         return midian_array[0];
  83.     else
  84.         return find_median(midian_array, 0, elem_aux_array);
  85. }
  86.   
  87. // 寻找中位数的所在位置
  88. int find_index(int array[], int left, int right, int median)
  89. {
  90.     for (int i = left; i <= right; i++)
  91.     {
  92.         if (array[i] == median)
  93.             return i;
  94.     }
  95.     return -1;
  96. }
  97.   
  98. int q_select(int array[], int left, int right, int k)
  99. {
  100.     // 寻找中位数的中位数
  101.     int median = find_median(array, left, right);
  102.       
  103.     // 将中位数的中位数与最右元素交换
  104.     int index = find_index(array, left, right, median);
  105.     swap(array[index], array[right]);
  106.       
  107.     int pivot = array[right];
  108.       
  109.     // 申请两个移动指针并初始化
  110.     int i = left;
  111.     int j = right - 1;
  112.       
  113.     // 根据枢纽元素的值对数组进行一次划分
  114.     while (true)
  115.     {
  116.         while(array[i] < pivot)
  117.             i++;
  118.         while(array[j] > pivot)
  119.             j--;
  120.         if (i < j)
  121.             swap(array[i], array[j]);
  122.         else
  123.             break;
  124.     }
  125.     swap(array[i], array[right]);
  126.       
  127.     /* 对三种情况进行处理:(m = i - left + 1)
  128.     1、如果m=k,即返回的主元即为我们要找的第k小的元素,那么直接返回主元a[i]即可;
  129.     2、如果m>k,那么接下来要到低区间A[0....m-1]中寻找,丢掉高区间;
  130.     3、如果m<k,那么接下来要到高区间A[m+1...n-1]中寻找,丢掉低区间。
  131.     */
  132.     int m = i - left + 1;
  133.     if (m == k)
  134.         return array[i];
  135.     else if(m > k)
  136.         //上条语句相当于if( (i-left+1) >k),即if( (i-left) > k-1 ),于此就与2.2节里的代码实现一、二相对应起来了。
  137.         return q_select(array, left, i - 1, k);
  138.     else
  139.         return q_select(array, i + 1, right, k - m);
  140. }
  141.   
  142. int main()
  143. {
  144.     //srand(unsigned(time(NULL)));
  145.     //for (int j = 0; j < num_array; j++)
  146.     //array[j] = rand();
  147.       
  148.     int array[num_array]={0,45,78,55,47,4,1,2,7,8,96,36,45};
  149.     // 寻找第k最小数
  150.     int k = 4;
  151.     int i = q_select(array, 0, num_array - 1, k);
  152.     cout << i << endl;
  153.       
  154.     return 0;
  155. }

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