#include memory
#include cstdlib
#include string
#include algorithm
#include numeric
#include deque
#include sstream
#include iostream
#include fstream
#include "TupleArray.h"
class StudentList
{
public:
enum StudentIndex
{
StudentID=0,
StudentName,
StudentCScore,
StudentStructScore,
StudentAlgorithmScore,
StudentDataSize
};
typedef std::string data_type;
typedef TupleArray data_type, StudentDataSize ::type value_type;
//插入
void insert(const value_type element) { pool.push_back(element); }
void insert(value_type element) { pool.push_back(std::move(element)); }
//搜索
const value_type search(StudentIndex i,const data_type key)const
{
auto e = pool.cend();
auto ans = std::find_if(pool.cbegin(), pool.cend(),
[i,key](const value_type v) -bool {
return TupleArray data_type, StudentDataSize ::getReader(i)(v)==key;
});
if (ans != e) { return *ans; }
static value_type null;
return null;
}
templateStudentIndex N
const value_type search( const data_type key)const
{
auto e = pool.cend();
auto ans = std::find_if(pool.cbegin(), pool.cend(),
[ key](const value_type v) -bool {
return std::getN(v) == key;
});
if (ans != e) { return *ans; }
static value_type null;
return null;
}
//获取平均成绩
double getAverage(StudentIndex i) const
{
double ans = 0;
ans = std::accumulate(pool.cbegin(), pool.cend(), ans,
[i]( const double d, const value_type v) -double
{
std::stringstream ss;
ss TupleArray data_type, StudentDataSize ::getReader(i)(v);
double temp;
ss temp;
return d+temp;
});
if (pool.size()) { return ans / pool.size(); }
return ans;
}
templateStudentIndex i
double getAverage() const
{
double ans = 0;
ans = std::accumulate(pool.cbegin(), pool.cend(), ans,
[](const double d, const value_type v) -double
{
std::stringstream ss;
ss std::geti(v);
double temp;
ss temp;
return d + temp;
});
if (pool.size()) { return ans / pool.size(); }
return ans;
}
//修改
value_type search(StudentIndex i, const data_type key)
{
auto e = pool.end();
auto ans = std::find_if(pool.begin(), pool.end(),
[i, key](const value_type v) -bool {
return TupleArray data_type, StudentDataSize ::getReader(i)(v) == key;
});
if (ans != e) { return *ans; }
static value_type null;
return null;
}
templateStudentIndex N
value_type search(const data_type key)
{
auto e = pool.end();
auto ans = std::find_if(pool.begin(), pool.end(),
[key](const value_type v) -bool {
return std::getN(v) == key;
});
if (ans != e) { return *ans; }
static value_type null;
return null;
}
//显示
friend std::ostream operator(std::ostream o, const StudentList::value_type v);
friend std::iostream operator(std::iostream i, StudentList::value_type v);
void show() const
{
for (const auto ii:pool)
{
std::cout ii std::endl;
}
}
//保存
void save(const std::string fileName)
{
std::ofstream ofs(fileName);
if (false == ofs.is_open()) { return; }
for (const auto ii : pool)
{
ofs ii std::endl;
}
}
//加载
void load(const std::string fileName)
{
std::ifstream ifs(fileName);
if (false == ifs.is_open()) { return; }
std::string line;
while (std::getline(ifs,line))
{
std::stringstream ss;
ss std::move(line);
value_type v;
ss v;
pool.push_back(std::move(v));
}
}
//清空
void clear() { pool.clear(); }
//排序
void sort(StudentIndex i)
{
std::sort(pool.begin(), pool.end(), [i](const value_type l,const value_type r) - bool
{
const auto rd = TupleArray data_type, StudentDataSize ::getReader(i);
return rd(l) rd(r);
});
}
templateStudentIndex i
void sort()
{
std::sort(pool.begin(), pool.end(), [](const value_type l, const value_type r) - bool
{
return std::geti(l) std::geti(r);
});
}
private:
std::deque value_type pool;
};
//显示
std::ostream operator(std::ostream o, const StudentList::value_type v)
{
for (auto ii = 0; ii std::tuple_sizeStudentList::value_type::value;++ii)
{
o TupleArray StudentList::data_type, StudentList::StudentDataSize ::getReader(ii)(v) " ";
}
return o;
}
std::iostream operator(std::iostream i, StudentList::value_type v)
{
for (auto ii = 0; ii std::tuple_sizeStudentList::value_type::value; ++ii)
{
i TupleArray StudentList::data_type, StudentList::StudentDataSize ::getWriter(ii)(v) ;
}
return i;
}
int main()
{
StudentList list;
//插入
list.insert(StudentList::value_type{ "1","21","3","4","5"});
list.insert(StudentList::value_type{ "5","22","3","4","5"});
list.insert(StudentList::value_type{ "3","23","3","4","5"});
list.insert(StudentList::value_type{ "4","24","3","4","5"});
list.insert(StudentList::value_type{ "2","25","3","4","5"});
list.insert(StudentList::value_type{ "6","26","3","4","5"});
//搜索
const StudentList clist = list;
auto ans = clist.search(StudentList::StudentName,"23") ;
auto ans1 = clist.searchStudentList::StudentName( "23");
//平均值
auto av2 = list.getAverageStudentList::StudentCScore();
//修改
std::getStudentList::StudentCScore(list.search(StudentList::StudentID,"6"))="99";
//显示
list.show();
//保存
list.save("ans.txt");
//清空
list.clear();
//加载
list.load("ans.txt");
//排序
list.sort(StudentList::StudentID);
list.sortStudentList::StudentID();
list.show();
}
#include list
#include iostream
using namespace std;
class CMyList
{
public:
templatetypename T
void push_back( T t )
{
m_list.push_back( (int )t);
}
templatetypename T
void pop_back(T t)
{
t=*(T*)(m_list.back());
}
private:
listint m_list;
};
class A
{
public:
A() {
SayHello();
}
void SayHello() {
cout "Hello, I am A" endl;
}
private:
};
class B
{
public:
B() {
SayHello();
}
void SayHello() {
cout "I am B"endl;
}
};
int main( int, char** )
{
CMyList mylist;
A a;
B b;
mylist.push_back( a );
mylist.push_back( b );
B bb;
mylist.pop_back(bb);
bb.SayHello();
A aa;
mylist.pop_back( aa );
aa.SayHello();
system( "pause" );
return 0;
}
花了几分钟写出来一个简单的CMyList通用类,你可以在此基础上修改。理论上可以放置任何类。支持所有C++平台哦!需要注意的是你存取的顺序要对,否则崩溃。如果你有兴趣的话可以看看tuple的实现,他可以放置任意类型的数据,而且类型安全。
[cpp] view plain copy
#include iostream
#include tuple
#include string
#include type_traits
templatestd::size_t N
struct print_hlp {
templateclass... Args
static void exec(std::tupleArgs... t)
{
print_hlpN-1::exec(t);
std::cout " , ";
using type_t = std::tuple_elementN
有人问获得的tuple怎么解包给类的构造函数呢。在语法上并没有直接提供的解决方案,但是我们可以绕个圈子来达成我们的目的。
首先我们的之一步当然是将tuple解包。tuple提供了一个get函数来获取第N个元素。例如:
get1(make_tuple(...));
要将一个tuple全部拆解,就可以使用通过多次调用这个函数来进行解析,例如:
auto tup = make_tuple(..........);
func( get0(tup),get1(tup),get2(tup)......getn(tup) );
而实际上,0,1,...n这个数列我们可以构建一个std::index_squence0,1,2,...,n,而其中,n = std::tuple_size decltype(tup) ::value -1,然后我们通过
templatesize_t ...i,typename T
auto func( std::index_squencei..., T t )
{
return funcc_(geti(t)...);
}
这种方式就能将tuple的全部元素进行解包。其中std::index_squence0,1,2,...,n由std::make_index_sequencen+1来获得。
那么现在开始解包给类的构造函数了,若有如下情景:
auto tup = make_tuple(...);
A a(tup);
我们只要定义以下几个构造函数即可。
struct A{
//之一个被调用的构造函数,这里生成一个index_squence,并调用第二个构造函数。
templatetypename T A(T t):A(
std::make_index_squence std::tuple_sizeT::value ,
t
){}
//这里是第二个构造函数,这里将tuple解包,然后调用第三个构造函数
templatesize_t ...i,typename T
A(std::index_squencei...,T t):
A(geti(t)...){}
//第三个构造函数,也就是直接用普通参数的构造函数。
A(....){}
}
基本Kmeans算法实现 C++代码
#include iostream
#include sstream
#include fstream
#include vector
#include math.h
#include stdlib.h
#define k 3//簇的数目
using namespace std;
//存放元组的属性信息
typedef vectordouble Tuple;//存储每条数据记录
int dataNum;//数据集中数据记录数目
int dimNum;//每条记录的维数
//计算两个元组间的欧几里距离
double getDistXY(const Tuple t1, const Tuple t2)
{
double sum = 0;
for(int i=1; i=dimNum; ++i)
{
sum += (t1[i]-t2[i]) * (t1[i]-t2[i]);
}
return sqrt(sum);
}
//根据质心,决定当前元组属于哪个簇
int clusterOfTuple(Tuple means[],const Tuple tuple){
double dist=getDistXY(means[0],tuple);
double tmp;
int label=0;//标示属于哪一个簇
for(int i=1;ik;i++){
tmp=getDistXY(means[i],tuple);
if(tmpdist) {dist=tmp;label=i;}
}
return label;
}
//获得给定簇集的平方误差
double getVar(vectorTuple clusters[],Tuple means[]){
double var = 0;
for (int i = 0; i k; i++)
{
vectorTuple t = clusters[i];
for (int j = 0; j t.size(); j++)
{
var += getDistXY(t[j],means[i]);
}
}
//cout"sum:"sumendl;
return var;
}
//获得当前簇的均值(质心)
Tuple getMeans(const vectorTuple cluster){
int num = cluster.size();
Tuple t(dimNum+1, 0);
for (int i = 0; i num; i++)
{
for(int j=1; j=dimNum; ++j)
{
t[j] += cluster[i][j];
}
}
for(int j=1; j=dimNum; ++j)
t[j] /= num;
return t;
//cout"sum:"sumendl;
}
void print(const vectorTuple clusters[])
{
for(int lable=0; lablek; lable++)
{
cout"第"lable+1"个簇:"endl;
vectorTuple t = clusters[lable];
for(int i=0; it.size(); i++)
{
couti+1".(";
for(int j=0; j=dimNum; ++j)
{
coutt[i][j]", ";
}
cout")\n";
}
}
}
void KMeans(vectorTuple tuples){
vectorTuple clusters[k];//k个簇
Tuple means[k];//k个中心点
int i=0;
//一开始随机选取k条记录的值作为k个簇的质心(均值)
srand((unsigned int)time(NULL));
for(i=0;ik;){
int iToSelect = rand()%tuples.size();
if(means[iToSelect].size() == 0)
{
for(int j=0; j=dimNum; ++j)
{
means[i].push_back(tuples[iToSelect][j]);
}
++i;
}
}
int lable=0;
//根据默认的质心给簇赋值
for(i=0;i!=tuples.size();++i){
lable=clusterOfTuple(means,tuples[i]);
clusters[lable].push_back(tuples[i]);
}
double oldVar=-1;
double newVar=getVar(clusters,means);
cout"初始的的整体误差平方和为:"newVarendl;
int t = 0;
while(abs(newVar - oldVar) = 1) //当新旧函数值相差不到1即准则函数值不发生明显变化时,算法终止
{
cout"第 "++t" 次迭代开始:"endl;
for (i = 0; i k; i++) //更新每个簇的中心点
{
means[i] = getMeans(clusters[i]);
}
oldVar = newVar;
newVar = getVar(clusters,means); //计算新的准则函数值
for (i = 0; i k; i++) //清空每个簇
{
clusters[i].clear();
}
//根据新的质心获得新的簇
for(i=0; i!=tuples.size(); ++i){
lable=clusterOfTuple(means,tuples[i]);
clusters[lable].push_back(tuples[i]);
}
cout"此次迭代之后的整体误差平方和为:"newVarendl;
}
cout"The result is:\n";
print(clusters);
}
int main(){
char fname[256];
cout"请输入存放数据的文件名: ";
cinfname;
coutendl" 请依次输入: 维数 样本数目"endl;
coutendl" 维数dimNum: ";
cindimNum;
coutendl" 样本数目dataNum: ";
cindataNum;
ifstream infile(fname);
if(!infile){
cout"不能打开输入的文件"fnameendl;
return 0;
}
vectorTuple tuples;
//从文件流中读入数据
for(int i=0; idataNum !infile.eof(); ++i)
{
string str;
getline(infile, str);
istringstream istr(str);
Tuple tuple(dimNum+1, 0);//之一个位置存放记录编号,第2到dimNum+1个位置存放实际元素
tuple[0] = i+1;
for(int j=1; j=dimNum; ++j)
{
istrtuple[j];
}
tuples.push_back(tuple);
}
coutendl"开始聚类"endl;
KMeans(tuples);
return 0;
}
稀疏矩阵代码如下
#include iostream
#include iomanip
using namespace std;
templateclass T
//三元组
struct Trituple
{
int row;
int col;
T val;
};
//稀疏矩阵声明
templateclass T
class SparseMatrix
{
public:
SparseMatrix(int maxt=100);
~SparseMatrix();
bool TransposeTo(SparseMatrix );
bool AddTo(const SparseMatrix);
bool TransposeTo_Faster(SparseMatrix);
void Input();
void Output();
private:
TritupleT* data;
int rows,cols,terms;
int maxterms;
};
templateclass T
SparseMatrixT::SparseMatrix(int maxt)
{
maxterms=maxt;
data=new TritupleT[maxterms];
terms=rows=cols=0;
}
templateclass T
SparseMatrixT::~SparseMatrix()
{
if (data!=NULL)
{
delete[] data;
}
}
//普通转置
templateclass T
bool SparseMatrixT::TransposeTo(SparseMatrix B)
{
if (termsB.maxterms)
{
return false;
}
B.rows=cols;
B.cols=rows;
B.terms=terms;
if (terms0)
{
int p=0;
for (int j=1;j=cols;j++)
{
for (int k=0;kterms;k++)
{
if (data[k].col==j)
{
B.data[p].row=j;
B.data[p].col=data[k].row;
B.data[p].val=data[k].val;
p++;
}
}
}
}
return true;
}
//快速转置
templateclass T
bool SparseMatrixT::TransposeTo_Faster(SparseMatrix B)
{
if (termsB.maxterms)
{
return false;
}
B.rows=cols;
B.cols=rows;
B.terms=terms;
if (terms0)
{
int *num,*cpot;
num=new int[cols];
cpot=new int[cols];
for (int j=0;jcols;j++)
{
num[j]=0;
}
for (int k=0;kterms;k++)
{
num[data[k].col-1]++;
}
//求出B中每一行的起始下标cpot[]
cpot[0]=0;
for (int j=1;jcols;j++)
{
cpot[j]=cpot[j-1]+num[j-1];
}
//执行转置操作
for (int p,k=0;kterms;k++)
{
p=cpot[data[k].col-1]++;
B.data[p].row=data[k].col;
B.data[p].col=data[k].row;
B.data[p].val=data[k].val;
}
delete[] num;
delete[] cpot;
}
return true;
}
templateclass T
void SparseMatrixT::Input()
{
cout"intput the matrix' row:";
int row1;
cinrow1;
cout"intput the matrix' col:";
int col1;
cincol1;
cout"input "row1"*"col1" matrix"endl;
int number;
rows=row1;
cols=col1;
for (int i=0;irows;i++)
{
for (int j=0;jcols;j++)
{
cinnumber;
if (number!=0)
{
data[terms].row=i+1;
data[terms].col=j+1;
data[terms].val=number;
terms++;
}
}
}
}
templateclass T //输出好看,但是违背了最初的原则
void SparseMatrixT::Output()
{
T **tempArray=new T*[rows];
for (int i1=0;i1rows;i1++)
{
tempArray[i1]=new int[cols];
}
for (int j=0;jrows;j++)
{
for (int k=0;kcols;k++)
{
tempArray[j][k]=0;
}
}
for (int i=0;iterms;i++)
{
tempArray[data[i].row-1][data[i].col-1]=data[i].val;
}
for (int j=0;jrows;j++)
{
for (int k=0;kcols;k++)
{
coutsetw(4)tempArray[j][k];
}
coutendl;
}
for (int l=0;lrows;l++)
{
delete[] tempArray[l];
}
delete tempArray;
coutendl;
}
templateclass T
bool SparseMatrixT::AddTo(const SparseMatrix B)
{
if (rows!=B.rows||cols!=B.cols)
{
return false;
}
bool flag=false;
int tempTerms=terms;
for (int i=0;iB.terms;i++)
{
flag=false;
for (int j=0;jtempTerms;j++)
{
if (data[j].col==B.data[i].coldata[j].row==B.data[i].row)
{
data[j].val+=B.data[i].val;
flag=true;
}
}
if (flag==false)
{
data[++terms-1].col=B.data[i].col; //数组下标操作注意事项
data[terms-1].row=B.data[i].row;
data[terms-1].val=B.data[i].val;
}
}
return true;
}
int main()
{
cout"此程序演示稀疏矩阵的普通转置和快速转置操作"endl;
SparseMatrixint *** (50);
SparseMatrixint *** 1(50);
SparseMatrixint *** 2(50);
*** .Input();
cout" *** is"endl;
*** .Output();
*** .TransposeTo( *** 1);
cout"Transposition of *** is "endl;
*** 1.Output();
*** .TransposeTo_Faster( *** 2);
cout"Transposition of *** is "endl;
*** 2.Output();
SparseMatrixint *** 3;
cout"input a new matrix"endl;
*** 3.Input();
cout" *** 3 is"endl;
*** 3.Output();
if( *** .AddTo( *** 3))
{
cout"after adding *** 3 , *** is"endl;
*** .Output();
}
else
cout"the two matrix can't add"endl;
cout"Good job!"endl;
system("pause");
return 0;
}