根据书上内容实现了最大值,最小值,第i小的数,第i大的数和求数组的中位数。
statistic_tool.h
#pragma once
/*************************************************
Author:董小歪
Date:2016-06-07
Description:算法导论第九章-中位数和顺序统计量-Cpp代码实现
**************************************************/
//为了实现算法导论中的下标从1开始,在data下标为0的元素添加一个“哨兵”元素0
#pragma once
#ifndef STATISTIC_TOOL_H
#define STATISTIC_TOOL_H
using namespace std;
#include <iostream>
#include <vector>
#include <random>
#include <time.h>
class Statistic_Tool {
public:
template<typename T> T minimum(const vector<T> &vec); //最小值
template<typename T> T maximum(const vector<T> &vec); //最大值
template<typename T> T randomized_select(vector<T> &vec, int l, int r, int index); //返回数据中第i小的值
template<typename T> T randomized_select2(vector<T> &vec, int l, int r, int index); //返回数据中第i大的值
template<typename T> double fild_median(vector<T> &vec); //返回数据中的中位数
private:
template<typename T> unsigned randomized_partition(vector<T> &vec, int l, int r); //随机划分
};
template<typename T>
T Statistic_Tool::minimum(const vector<T> &vec)
{
if (vec.empty())
return INT_MIN;
T ret = vec[0];
for (int i = 1; i < vec.size(); ++i)
if (vec[i] < ret)
ret = vec[i];
return ret;
}
template<typename T>
T Statistic_Tool::maximum(const vector<T> &vec)
{
if (vec.empty())
return INT_MAX;
T ret = vec[0];
for (int i = 1; i < vec.size(); ++i)
if (vec[i] > ret)
ret = vec[i];
return ret;
}
template<typename T>
T Statistic_Tool::randomized_select(vector<T> &vec, int l, int r, int index)
{
if (l == r)
return vec[l];
int q = randomized_partition(vec, l, r);
int k = q - l + 1;
if (index == k)
return vec[q];
else if (k < index)
return randomized_select(vec, q + 1, r, index - k);
else
return randomized_select(vec, l, q - 1, index);
}
template<typename T>
T Statistic_Tool::randomized_select2(vector<T> &vec, int l, int r, int index)
{
if (l == r)
return vec[l];
int q = randomized_partition(vec, l, r);
int k = r - q + 1;
if (index == k)
return vec[q];
else if (k < index)
return randomized_select2(vec, l, q - 1, index - k);
else
return randomized_select2(vec, q + 1, r, index);
}
template<typename T>
unsigned Statistic_Tool::randomized_partition(vector<T> &vec, int l, int r)
{
uniform_int_distribution<unsigned> u(l, r);
default_random_engine e;
int random = u(e);
swap(vec[random], vec[r]);
int x = vec[r];
int i = l - 1;
for (int j = l; j < r; ++j)
{
if (vec[j] < x)
{
++i;
swap(vec[i], vec[j]);
}
}
swap(vec[r], vec[i + 1]);
return i + 1;
}
template<typename T>
double Statistic_Tool::fild_median(vector<T> &vec)
{
if (vec.size() & 0x00000001)
return randomized_select(vec, 0, vec.size() - 1, vec.size() / 2 + 1);
else
return static_cast<double>(randomized_select(vec, 0, vec.size() - 1, vec.size() / 2) + randomized_select(vec, 0, vec.size() - 1, vec.size() / 2 + 1)) / 2;
}
#endif // !STATISTIC_TOOL_H
测试用例:
#include "statistic_tool.h"
int main()
{
Statistic_Tool st;
vector<int> data = { 12,1,4,40,29,18,3,9 };
cout << "原数据是:";
for (auto e : data)
cout << e << " ";
cout << endl << endl;
cout << "最小值是:" << st.minimum(data) << endl << endl;
cout << "最大值是:" << st.maximum(data) << endl << endl;
vector<int> copy = data;
uniform_int_distribution<unsigned> u(1, copy.size());
default_random_engine e(time(0));
int index = u(e);
cout << "第" << index << "小的数字是:" << st.randomized_select(copy, 0, copy.size() - 1, index) << endl << endl;
cout << "第" << index << "大的数字是:" << st.randomized_select2(copy, 0, copy.size() - 1, index) << endl << endl;
cout << "数据:";
for (auto e : data)
cout << e << " ";
cout << "的中位数是:" << st.fild_median(data) << endl << endl;
vector<int> data2 = { 1,4,40,29,18,3,9 };
cout << "数据:";
for (auto e : data2)
cout << e << " ";
cout << "的中位数是:" << st.fild_median(data2) << endl << endl;
system("pause");
}
测试结果截图: