';
聚类算法-Hierarchical(MIN)-C++
最后更新于:2022-04-01 20:31:28
程序流程图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d6e43044.jpg)
Hierarchical(MIN)核心功能函数,采用vector
>::dTable存储两点之间的距离。计算每两个point间的距离并保存到distance table中;判断是否达到需要聚类的cluster数量,若是,将point信息写入clustering文件,程序结束。否则,合并两个具有最小距离的point,将两个point中的所有node全部加入到一个point中,删除拷贝node数组后的多余point,跟新dataset数组。然后更新distance table,删除被合并point对应的distance table中行与列,进入下一步循环。
~~~
/*
K-means Algorithm
15S103182
Ethan
*/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class node{
public:
float x;
float y;
node(float a,float b){
x = a;
y = b;
}
};
class point{
public:
float x;
float y;
vector nds;
point (float a,float b){
x = a;
y = b;
node t(a,b);
nds.push_back(t);
}
};
float stringToFloat(string i){
stringstream sf;
float score=0;
sf<>score;
return score;
}
vector openFile(const char* dataset){
fstream file;
file.open(dataset,ios::in);
if(!file)
{
cout <<"Open File Failed!" < a;
return a;
}
vector data;
while(!file.eof()){
string temp;
file>>temp;
int split = temp.find(',',0);
point p(stringToFloat(temp.substr(0,split)),stringToFloat(temp.substr(split+1,temp.length()-1)));
data.push_back(p);
}
file.close();
cout<<"Read data successfully!"< dataset,int clusters){
//Similarity table:distance table
vector > dTable;
for(int i=0;i temp;
for(int j=0;ji)
temp.push_back(squareDistance(dataset[i],dataset[j]));
else if(jclusters){
//Merge two closest clusters
float minDt =INT_MAX;
int mi,mj;
for(int i=0;i::iterator imj = dataset.begin();
imj += mj;
dataset.erase(imj);
//Update the dTable
for(int j=0;jdTable[mj][j]){
dTable[mi][j] = dTable[mj][j];
dTable[j][mi] = dTable[mi][j];
}
}
//rm
vector >::iterator ii = dTable.begin();
ii += mj;
dTable.erase(ii);
for(int i=0;i::iterator ij = dTable[i].begin();
ij += mj;
dTable[i].erase(ij);
}
}
fstream clustering;
clustering.open("clustering.txt",ios::out);
for(int i=0;i dataset = openFile("dataset3.txt");
HierarchicalClustering(dataset,15);
return 0;
}
~~~
数据文件格式:(x,y)
运行结果格式:(x,y,cluster)
具体文件格式见DBSCAN篇:http://blog.csdn.net/k76853/article/details/50440182
图形化展现:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d6e5a775.jpg)
总结:
Hierarchical(MIN)算法能够很好处理非圆形状的数据。但对于噪音和离群点,Hierarchical(MIN)算法具有局限性。由于层次聚类具有不可恢复性,一旦聚类,就难以撤销聚类操作,刚开始编码的时候走了不少弯路,后来果断决定用数组存储node信息,方便cluster合并。对于近邻表的更新,也遇到一点小麻烦,由于二级指针对于行列的删除比较复杂,果断采用动态数组vector来存储距离信息,二级vector对于行的删除非常直接简单,对于列的删除也只需O(n)操作,比较简洁高效。
';
聚类算法-K-means-C++实现
最后更新于:2022-04-01 20:31:26
程序流程图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d6e09c55.jpg)
K-means核心功能函数,首先,随机选择K-中心点(中心点坐标为簇中所有点的x坐标的平均值,y坐标的平均值,该点用于记录位置,不属于原始数据集);循环判断中心点是否不变,若是,将二维点对信息写入clustering文件,程序结束。否则,对于每个二维数据点,选择与其距离最近的中心点,将点cluster编号更新为中心点的cluster编号。然后对于K-簇,重新计算K-中心点,进入下一个循环判断。
计算簇中心是否不变可以采用SSE方式,具体实现代码中已给出,或者直接循环运行多次(不推荐)。
~~~
/*
K-means Algorithm
15S103182
Ethan
*/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef struct Point{
float x;
float y;
int cluster;
Point (){}
Point (float a,float b,int c){
x = a;
y = b;
cluster = c;
}
}point;
float stringToFloat(string i){
stringstream sf;
float score=0;
sf<>score;
return score;
}
vector openFile(const char* dataset){
fstream file;
file.open(dataset,ios::in);
vector data;
while(!file.eof()){
string temp;
file>>temp;
int split = temp.find(',',0);
point p(stringToFloat(temp.substr(0,split)),stringToFloat(temp.substr(split+1,temp.length()-1)),0);
data.push_back(p);
}
file.close();
return data;
}
float squareDistance(point a,point b){
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
void k_means(vector dataset,int k){
vector centroid;
int n=1;
int len = dataset.size();
srand((int)time(0));
//random select centroids
while(n<=k){
int cen = (float)rand()/(RAND_MAX+1)*len;
point cp(dataset[cen].x,dataset[cen].y,n);
centroid.push_back(cp);
n++;
}
for(int i=0;i=1){
// while(time){
oSSE = nSSE;
nSSE = 0;
//update cluster for all the points
for(int i=0;i dataset = openFile("dataset3.txt");
k_means(dataset,7);
return 0;
}
~~~
数据文件格式:(x,y)
运行结果格式:(x,y,cluster)
具体文件格式见DBSCAN篇:http://blog.csdn.net/k76853/article/details/50440182
图形化展现:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d6e26247.jpg)
总结:
K-means算法运行速度快,实现简便。但K-means算法对具有变化大小,变化密度,非圆形状等特点的数据具有局限性。解决方法是增加K的大小,增加cluster数量,使得数据的特征能够更加明显。对于数据初始中心点的选择,采用随机的方式可能无法产生理想的聚类,这时可以采用二分K-means方法,或层次聚类进行处理。
';
聚类算法-DBSCAN-C++实现
最后更新于:2022-04-01 20:31:24
程序流程图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cfa19827.jpg)
DBSCAN核心功能函数,计算每个point的eps范围内的point数量pts;
对于所有pts >Minpts的point,记为Core point;
对于所有的corepoint,将其eps范围内的core point下标添加到vector
::corepts中;
对于所有的corepoint,采用深度优先的方式遍历core point的所有cluster,使得相互连接的core point具有相同的cluster编号;
计算所有pts < Minpts且在Core point范围内的,记为Borderpoint;
将所有Borderpoint加入到任意一个关联的core point;
剩余的point的为Noise point,文件写写入时忽略;
将point信息写入clustering文件,程序结束。
~~~
/*
DBSCAN Algorithm
15S103182
Ethan
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class point{
public:
float x;
float y;
int cluster=0;
int pointType=1;//1 noise 2 border 3 core
int pts=0;//points in MinPts
vector corepts;
int visited = 0;
point (){}
point (float a,float b,int c){
x = a;
y = b;
cluster = c;
}
};
float stringToFloat(string i){
stringstream sf;
float score=0;
sf<>score;
return score;
}
vector openFile(const char* dataset){
fstream file;
file.open(dataset,ios::in);
if(!file)
{
cout <<"Open File Failed!" < a;
return a;
}
vector data;
int i=1;
while(!file.eof()){
string temp;
file>>temp;
int split = temp.find(',',0);
point p(stringToFloat(temp.substr(0,split)),stringToFloat(temp.substr(split+1,temp.length()-1)),i++);
data.push_back(p);
}
file.close();
cout<<"successful!"< dataset,float Eps,int MinPts){
int len = dataset.size();
//calculate pts
cout<<"calculate pts"< corePoint;
for(int i=0;i=MinPts) {
dataset[i].pointType = 3;
corePoint.push_back(dataset[i]);
}
}
cout<<"joint core point"< ps;
if(corePoint[i].visited == 1) continue;
ps.push(&corePoint[i]);
point *v;
while(!ps.empty()){
v = ps.top();
v->visited = 1;
ps.pop();
for(int j=0;jcorepts.size();j++){
if(corePoint[v->corepts[j]].visited==1) continue;
corePoint[v->corepts[j]].cluster = corePoint[i].cluster;
corePoint[v->corepts[j]].visited = 1;
ps.push(&corePoint[v->corepts[j]]);
}
}
}
cout<<"border point,joint border point to core point"< dataset = openFile("dataset3.txt");
DBSCAN(dataset,1.5,2);
return 0;
}
~~~
数据文件格式:(x,y)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cfa2ea61.jpg)
运行结果格式:(x,y,cluster)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d363a488.jpg)
图形化展现:
特殊形状:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d364d035.jpg)
桥梁:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d3671f34.jpg)
变化密度:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187d6ddaa44.jpg)
总结:
DBSCAN算法能够很好处理不同形状与大小的数据,并且抗噪音数据。但对于变化的密度,DBSCAN算法具有局限性。在实现Core point连接时,遇到了一点小小的麻烦,很难将相互连接的core point的cluster编号统一,后来通过给每个core point增加一个数组用于记录相连core point的下标信息,并采用深度优先进行遍历的方式,不仅提高了计算速度,同时也保证了准确性。对于实验数据结果,如果不对其进行图形化展现,很难看出聚类的效果,采用WPF(C#)技术对数据点进行处理,对不同cluster编号的点,赋予不同的颜色,进行图形展现。
';
Apriori算法 (Introduction to data mining)
最后更新于:2022-04-01 20:31:21
前置概念:
**Support**: 支持度 s(X->Y) =(XUY)/N;
**Confidence**: 置信度 c(X->Y) =(XUY)/(X);
**Frequent ItemSet**: 频繁项集 Support >minSup;
**Apriori Principle**: 如果一个项集是频繁的,那它所有的子项集也都是频繁的。
**Frequent Itemset Generation in the AprioriAlgorithm:**
Apriori算法是第一个指出使用基于支持度剪枝策略的关联规则挖掘算法,系统地控制候选项集的指数增长。
Ck代表k候选项集, Fk代表频繁k项集
1 算法首先遍历一遍数据集,检测每项的支持度,获取频繁1-项集。Steps (1-2)
2 接下来,循环使用频繁(k-1)-项集派生k-候选项集。Step (5)
3 遍历数据集计算候选项集支持度Steps (6-10)
4 计算支持度后,消除非频繁项集Step (12)
5 当没有新的频繁项集产生的时候,算法结束Step(13)
**Frequent itemset generation of the AprioriAlgorithm.**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cf96b84e.jpg)
**Rule generation:**
若果一个规则X->Y-X不满足置信度阀值,那么所有的X’->Y-X’也不满足阀值, 其中X’⊂ X.
**Rule generation of the Apriori algorithm.**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cf981aac.jpg)
**Procedure ap-genrules(fk, Hm).**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cf994462.jpg)
**总结:**
**核心思想: 基于两阶段频繁项集,挖掘关联规则**
**算法优点: 简单、易理解、数据要求低**
**算法缺点: I/O负载大,产生过多的候选项集**
**Apriori例题(Introduction to data mining):**
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cf9b90df.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-21_57187cf9e7291.jpg)
(b)16/32=50%
(c)11/32=34.4%
(d)5/32=15.6%
';
顶点覆盖问题
最后更新于:2022-04-01 20:31:19
输入:无向图G(V,E)
输出:C属于V,C中点数最小,满足E中任意一条边中的两个顶点至少有一个在C中
APPROX_Vertex_Cover(G)
1 C=空集
2 E' = E
3 While E' != 空集 Do
4 任选{u,v}属于E'
5 C = C U {u,v}
6 删除E'中所有与u,v相连的边
7 Return C
Ratio Bound(近似比)
设A为算法第四步中选中的边集,由算法第六步可知,A中无邻接边
第五步中每次增加两个节点到C,因此|C| = 2|A|
设C*是优化解,则C*必须覆盖A
由于A中无邻接边,C*至少包含A中每条边的一个节点,
于是|A|<=|C*|,|C| = 2|A| <= 2|C*|
即|C| / |C*| <= 2.
因此,算法近似比为2.
';
判断两多项式之积是否等于另一多项式
最后更新于:2022-04-01 20:31:17
问题描述:判断p(x),q(x)之积是否等于r(x),p,q,r分别为m,n,l 阶多项式
Random_polynomial(p(x),q(x),r(x),m,n,l)
输入:随机选取X[1:k]
输出:p(x)*q(x)是否等于r(x)
1 K =max{m+n,l}
2 For k=1 to K do
3 X[k] = random(real) //no repeat
4 For k=1 to K do
5 If(p(X[k])* q(X[k])!= r(X[k])) then
6 Return false
7 Return true
获得正确解的概率:
若p(x)*q(x)与r(x)阶数相同成立,则对任意的k成立,输出正确解;若不成立,除非找到p(x)*q(x)-r(x)=0的k个根,否则等式一定不成立。
设实数集合大小为S,则找到k个根的概率为max{m+n,l}/S,因此一定为错误解的概率为max{m+n,l}/S。
时间复杂度:O(max{m+n,l})
综上所述,若算法返回false则一定位正确解;若放回true,则正确解的概率为1-max{m+n,l}/S。
由于算法并不能总获得问题的正确解,显然该随机算法为蒙特卡洛算法。
';
随机算法
最后更新于:2022-04-01 20:31:14
### 1. 数值随机算法
通过随机点数求解圆周率,定积分等问题。
主要利用大数定律与强大数定律。
### 2. 拉斯维加斯随机算法(Las Vegas)
通过随机选择法求解集合S中的第k小的数
算法得到的解一定是正确解,但算法也可能不获得问题的解,满足以上条件即为拉斯维加斯算法。
### 3. 舍伍德随机算法(Sherwood)
随机快速排序
舍伍德算法能够获得问题的正确解,它的精髓在于消除算法的最坏情况与特定实例之间的关联(例如,快速排序最坏时间复杂度为O(n方))
3. 蒙特卡洛随机算法(Monte Carlo)
a算法并不总能获得问题的正确解
b算法以较高的概率获得正确解
c不存在有效过程判定算法输出的解是否为问题的正确解
满足以上三条性质的算法称为蒙特卡洛算法。
';
并行机器最短调度问题
最后更新于:2022-04-01 20:31:12
输入:数组t,存储n个任务的执行时间
m台完全一样的机器
输出:使任务在m台机器并行执行时间最短的一个调度策略
基于贪心选择:选择具有最短任务队列的机器。
~~~
#include
#include
using namespace std;
int minTask(int *t,int n){
int tmp = t[0];
int min = 0;
for(int i=0;it[i]){
tmp = t[i];
min = i;
}
}
return min;
}
void makeSpanScheduling(int *t,int n,int num){
int *T = new int[num];
vector > M;
for(int i=0;i tmp;
M.push_back(tmp);
}
for(int i=0;i
';
求数组中的逆序对
最后更新于:2022-04-01 20:31:10
~~~
#include
using namespace std;
int count = 0;
void merge(int *a,int p,int q,int r){
int n1 = q-p+1;
int n2 = r-q;
int *m = new int[n1];
int *n = new int[n2];
for(int i=0;i
';
树搜索策略
最后更新于:2022-04-01 20:31:08
## 1. 深度优先
维护栈
将根节点放入栈
循环弹出栈顶元素,然后将栈顶元素的子节点放入栈中
当栈顶元素满足约束条件,对其进行处理。
当栈空时,搜索结束
## 2. 广度优先
维护队列
将根节点放入队列
循环弹出队首元素,然后将队首的子节点放入队列中
当队首元素满足约束条件,对其进行处理。
当队空时,搜索结束
## 3. 爬山法
深度优先+贪心
将栈首的子节点,采用贪心策略放入栈顶
##4. Best First
深度优先+广度优先
维护堆
将跟节点放入堆
将兄弟节点与孩子节点中的最优节点放入堆中
若堆首节点满足条件,对其进行处理。
堆空,搜索结束
## 5. 分支限界法
剪枝函数+广度优先
广度优先跑一次,找出可行解代价
对接下来的顶点,判断其代价是否优于可行解,若是,继续,否则孩子节点不予处理
## 6. A*算法
Best First + 代价函数
';
01背包-近似算法
最后更新于:2022-04-01 20:31:05
~~~
void dp2(int *w, int *v, int n, int c){cout<<"dp2:"<
0;i--){
if(m[n][i]<=c&&m[n][i]!=-1){
maxV = i;
break;
}
}
for(int i=n;i>0;i--){
if(m[i][maxV]==m[i-1][maxV]) x[i] = 0;
else {
x[i] = 1;
maxV -= v[i-1];
}
}
// for (int i = 1; i <= n; i++) cout << x[i] << "\t";
cout << endl;
}
void adp(int *w, int *v, int n, int c,int e){cout<<"adp:"<
';
动态规划算法的一般解题思路
最后更新于:2022-04-01 20:31:03
**1. 证明优化子结构**
对于问题的优化子结构,给出问题具有优化子结构的解代价,利用反证法,假设上解不是最优的,则存在另外一个解,其解优于上解,这与上解是最优的矛盾,于是该问题具有优化子结构。
证明优化子结构问题主要利用反证法。
**2. 证明重复子问题**
给出问题的递归公式则重叠子问题鍀证。
**3. 递归的定义最优解的代价**
给出最有解的代价递归公式,利于代码编写。
**4. 自底向上计算最优解的代价**
一般利用二维矩阵求解代价,或一行一行计算代价,或按列计算代价,或按照对角线逐级计算代价。
**5. 构造最优解**
根据最有接的代价矩阵信息,编写函数构造最优解。
';
整数序列合并问题
最后更新于:2022-04-01 20:31:01
~~~
#include
using namespace std;
void show(int **s,int i,int j){
if(i==j) cout<<"A"<m[i][j]) {
m[i][j] = p;
s[i][j] = k;
}
}
}
}
for(int i=0;i
';
01背包
最后更新于:2022-04-01 20:30:59
~~~
void dp(int *w, int *v, int n, int c){
int **m;
m = new int*[n+1];
for (int i = 0; i
= 2; i--){
for (int j = c; j >= 1; j--){
if (j - w[i - 1] >= 0){
int tmp = m[i + 1][j - w[i - 1]] + v[i - 1];
m[i][j] = m[i + 1][j]>tmp ? m[i + 1][j] : tmp;
}
else{
m[i][j] = m[i + 1][j];
}
}
}
if (c >= w[0]) m[1][c] = m[2][c - w[0]] + v[0];
else m[1][c] = m[2][c];
// for (int i = 1; i <= n; i++) {
// for (int j = 1; j <= c; j++) cout << m[i][j] << "\t";
// cout << endl;
// }
int *x;
x = new int[n+1];
for (int i = 0; i
';
求n*n阶矩阵最大子矩阵阶数
最后更新于:2022-04-01 20:30:56
~~~
int MaxSubMatrixOrder(int **a,int n){
int result[n][n] = {a[0][0]};
for(int i=1;i
=result[i-1][j]) result[i][j] = result[i-1][j];
else result[i][j] = result[i][j-1];
if(result[i-1][j-1]>0) result[i][j]++;
if(max
';
斐波那契数列-台阶问题
最后更新于:2022-04-01 20:30:54
~~~
int fibonacciSequence(int n){
if(n<1) return 0;
if(n<2) return 1;
if(n<3) return 2;
int a[n+1];
a[0]=1;
a[1]=1;
for(int i=2;i<=n;i++){
a[i] = a[i-1] + a[i-2];
}
return a[n];
}
~~~
';
最长公共子序列
最后更新于:2022-04-01 20:30:52
~~~
int ** lcsLength(int *x,int *y,int m,int n){
int b[m][n],c[m][n];
for(int i=0;ic[i][j-1]){
c[i][j] = c[i-1][j];
b[i][j] = 2;
}
else {
c[i][j] = c[i][j-1];
b[i][j] = -1;
}
}
}
int **a = new int*[m];
for(int i=0;i
';