/*
p:期望为线性时间的选择算法
t:2018年5月2日 11:06:05
*/
#include<iostream>
#include<stdio.h>
//随机数
#include<stdlib.h>
#include<time.h>
using namespace std;
//随机化找出第i小的数
/*
a[] 数组名
p 起始位置
r 结束位置
i 第i小的数
*/
//划分程序
int Randomized_Partition(int a[], int p, int r);
//循环版本
int Randomized_Seletct(int a[], int p, int r, int i)
{
//划分数组
int q = Randomized_Partition(a, p, r);
while (p != r)
{
if (q == i)
{
return a[q];
}
else if (i < q)//主元的前半部分
{
r = q - 1;
q = Randomized_Partition(a, p, r);
}
else//主元的后半部
{
p = q + 1;
q = Randomized_Partition(a, p, r);
}
}
return a[p];
}
int Randomized_Seletct1(int a[], int p, int r, int i)
{
//只有一个数
if (p == r)
{
return a[p];
}
//划分数组
int q = Randomized_Partition(a, p, r);
//主元到数组开始元素的个数
int k = q - p +1;
//这里用 k == i比较,而不用 q == i比较,因为i是一直变化的
if (k == i)
{
return a[q];
}
else if ( i < k)//主元的前半部分
{
return Randomized_Seletct1(a, p, q - 1, i);
}
else//主元的后半部
{
return Randomized_Seletct1(a, q+1, r, i-k);//
}
}
//划分程序
int random(int min, int max);
//交换两数的值
void exchange(int &a, int &b);
int Randomized_Partition(int a[], int begin, int end)
{
//随机化
int r = random(begin, end);
int tmp = a[r];
a[r] = a[end];
a[end] = tmp;
//
int x = a[end];//比较的对象是最后一个元素
int i = begin - 1;//i是比x小的元素的最后一个位置
for (int j = begin; j < end; ++j)
{
if (a[j] < x)
{
i++;
exchange(a[i], a[j]);
}
}
exchange(a[end], a[i + 1]);
return i + 1;
}
//随机数产生 [min,max]
int random(int min, int max)
{
srand(time(0));
return rand() % (max - min +1 ) + min;
}
//交换
void exchange(int &a, int &b)
{
if (a != b)
{
int tmp = a;
a = b;
b = tmp;
}
}
int main()
{
//第一个位置不用,999999为垃圾值
int a[] = { 999999,0,1,3 ,5,7,9,8,6,4,2};
int len = sizeof(a) / sizeof(int);
for (int i = 1; i <len; ++i)
{
int num = Randomized_Seletct(a, 1, len-1 , i);
printf("第%d小的数是:%d\n", i, num);
}
for (int i = 1; i <len; ++i)
{
int num = Randomized_Seletct1(a, 1, len - 1, i);
printf("第%d小的数是:%d\n", i, num);
}
return 0;
}